Android程序自動(dòng)更新功能模塊的實(shí)現(xiàn)方法【附完整demo源碼下載】
本文實(shí)例講述了Android程序自動(dòng)更新功能模塊的實(shí)現(xiàn)方法。分享給大家供大家參考,具體如下:
在程序啟動(dòng)的時(shí)候檢測(cè)服務(wù)器上有沒有對(duì)應(yīng)版本更新,如果有更新,提示用戶是否更新。
在程序啟動(dòng)的時(shí)候首先調(diào)用更新模塊檢測(cè)服務(wù)器上存放的版本號(hào)跟當(dāng)前程序的版本號(hào)如果大于當(dāng)前版本號(hào),彈出更新對(duì)話框,如果用戶選擇更新,則顯示當(dāng)前更新狀態(tài),然后替換當(dāng)前程序。
程序調(diào)用版本更新檢測(cè):
private UpdateManager updateMan;
private ProgressDialog updateProgressDialog;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//沒有判斷網(wǎng)路是否連接
//檢查是否有更新
//如果有更新提示下載
updateMan = new UpdateManager(Update_TestActivity.this, appUpdateCb);
updateMan.checkUpdate();
}
執(zhí)行檢測(cè)版本號(hào)以及回調(diào)更新提示
下載更新文件等實(shí)現(xiàn):
package update.test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.json.JSONArray;
import org.json.JSONObject;
import com.trinet.util.NetHelper;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class UpdateManager {
private String curVersion;
private String newVersion;
private int curVersionCode;
private int newVersionCode;
private String updateInfo;
private UpdateCallback callback;
private Context ctx;
private int progress;
private Boolean hasNewVersion;
private Boolean canceled;
//存放更新APK文件的路徑
public static final String UPDATE_DOWNURL = "http://www.baidu.com/update/update_test.apk";
//存放更新APK文件相應(yīng)的版本說明路徑
public static final String UPDATE_CHECKURL = "http://www.baidu.com/update/update_verson.txt";
public static final String UPDATE_APKNAME = "update_test.apk";
//public static final String UPDATE_VERJSON = "ver.txt";
public static final String UPDATE_SAVENAME = "updateapk.apk";
private static final int UPDATE_CHECKCOMPLETED = 1;
private static final int UPDATE_DOWNLOADING = 2;
private static final int UPDATE_DOWNLOAD_ERROR = 3;
private static final int UPDATE_DOWNLOAD_COMPLETED = 4;
private static final int UPDATE_DOWNLOAD_CANCELED = 5;
//從服務(wù)器上下載apk存放文件夾
private String savefolder = "/mnt/innerDisk/";
//private String savefolder = "/sdcard/";
//public static final String SAVE_FOLDER =Storage. // "/mnt/innerDisk";
public UpdateManager(Context context, UpdateCallback updateCallback) {
ctx = context;
callback = updateCallback;
//savefolder = context.getFilesDir();
canceled = false;
getCurVersion();
}
public String getNewVersionName()
{
return newVersion;
}
public String getUpdateInfo()
{
return updateInfo;
}
private void getCurVersion() {
try {
PackageInfo pInfo = ctx.getPackageManager().getPackageInfo(
ctx.getPackageName(), 0);
curVersion = pInfo.versionName;
curVersionCode = pInfo.versionCode;
} catch (NameNotFoundException e) {
Log.e("update", e.getMessage());
curVersion = "1.1.1000";
curVersionCode = 111000;
}
}
public void checkUpdate() {
hasNewVersion = false;
new Thread(){
// ***************************************************************
/**
* @by wainiwann
*
*/
@Override
public void run() {
Log.i("@@@@@", ">>>>>>>>>>>>>>>>>>>>>>>>>>>getServerVerCode() ");
try {
String verjson = NetHelper.httpStringGet(UPDATE_CHECKURL);
Log.i("@@@@", verjson
+ "**************************************************");
JSONArray array = new JSONArray(verjson);
if (array.length() > 0) {
JSONObject obj = array.getJSONObject(0);
try {
newVersionCode = Integer.parseInt(obj.getString("verCode"));
newVersion = obj.getString("verName");
updateInfo = "";
Log.i("newVerCode", newVersionCode
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
Log.i("newVerName", newVersion
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
if (newVersionCode > curVersionCode) {
hasNewVersion = true;
}
} catch (Exception e) {
newVersionCode = -1;
newVersion = "";
updateInfo = "";
}
}
} catch (Exception e) {
Log.e("update", e.getMessage());
}
updateHandler.sendEmptyMessage(UPDATE_CHECKCOMPLETED);
};
// ***************************************************************
}.start();
}
public void update() {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(
Uri.fromFile(new File(savefolder, UPDATE_SAVENAME)),
"application/vnd.android.package-archive");
ctx.startActivity(intent);
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public void downloadPackage()
{
new Thread() {
@Override
public void run() {
try {
URL url = new URL(UPDATE_DOWNURL);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.connect();
int length = conn.getContentLength();
InputStream is = conn.getInputStream();
File ApkFile = new File(savefolder,UPDATE_SAVENAME);
if(ApkFile.exists())
{
ApkFile.delete();
}
FileOutputStream fos = new FileOutputStream(ApkFile);
int count = 0;
byte buf[] = new byte[512];
do{
int numread = is.read(buf);
count += numread;
progress =(int)(((float)count / length) * 100);
updateHandler.sendMessage(updateHandler.obtainMessage(UPDATE_DOWNLOADING));
if(numread <= 0){
updateHandler.sendEmptyMessage(UPDATE_DOWNLOAD_COMPLETED);
break;
}
fos.write(buf,0,numread);
}while(!canceled);
if(canceled)
{
updateHandler.sendEmptyMessage(UPDATE_DOWNLOAD_CANCELED);
}
fos.close();
is.close();
} catch (MalformedURLException e) {
e.printStackTrace();
updateHandler.sendMessage(updateHandler.obtainMessage(UPDATE_DOWNLOAD_ERROR,e.getMessage()));
} catch(IOException e){
e.printStackTrace();
updateHandler.sendMessage(updateHandler.obtainMessage(UPDATE_DOWNLOAD_ERROR,e.getMessage()));
}
}
}.start();
}
public void cancelDownload()
{
canceled = true;
}
Handler updateHandler = new Handler()
{
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_CHECKCOMPLETED:
callback.checkUpdateCompleted(hasNewVersion, newVersion);
break;
case UPDATE_DOWNLOADING:
callback.downloadProgressChanged(progress);
break;
case UPDATE_DOWNLOAD_ERROR:
callback.downloadCompleted(false, msg.obj.toString());
break;
case UPDATE_DOWNLOAD_COMPLETED:
callback.downloadCompleted(true, "");
break;
case UPDATE_DOWNLOAD_CANCELED:
callback.downloadCanceled();
default:
break;
}
}
};
public interface UpdateCallback {
public void checkUpdateCompleted(Boolean hasUpdate,
CharSequence updateInfo);
public void downloadProgressChanged(int progress);
public void downloadCanceled();
public void downloadCompleted(Boolean sucess, CharSequence errorMsg);
}
}
需要連接服務(wù)器模塊:
package com.trinet.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
public class NetHelper {
public static String httpStringGet(String url) throws Exception {
return httpStringGet(url, "utf-8");
}
/**
*
*
* @param url
* @return
*/
public static Drawable loadImage(String url) {
try {
return Drawable.createFromStream(
(InputStream) new URL(url).getContent(), "test");
} catch (MalformedURLException e) {
Log.e("exception", e.getMessage());
} catch (IOException e) {
Log.e("exception", e.getMessage());
}
return null;
}
public static String httpStringGet(String url, String enc) throws Exception {
// This method for HttpConnection
String page = "";
BufferedReader bufferedReader = null;
try {
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, "android");
HttpParams httpParams = client.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 3000);
HttpConnectionParams.setSoTimeout(httpParams, 5000);
HttpGet request = new HttpGet();
request.setHeader("Content-Type", "text/plain; charset=utf-8");
request.setURI(new URI(url));
HttpResponse response = client.execute(request);
bufferedReader = new BufferedReader(new InputStreamReader(response
.getEntity().getContent(), enc));
StringBuffer stringBuffer = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line + NL);
}
bufferedReader.close();
page = stringBuffer.toString();
Log.i("page", page);
System.out.println(page + "page");
return page;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
Log.d("BBB", e.toString());
}
}
}
}
public static boolean checkNetWorkStatus(Context context) {
boolean result;
ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netinfo = cm.getActiveNetworkInfo();
if (netinfo != null && netinfo.isConnected()) {
result = true;
Log.i("NetStatus", "The net was connected");
} else {
result = false;
Log.i("NetStatus", "The net was bad!");
}
return result;
}
}
以及提示對(duì)話框:
package com.trinet.util;
import java.lang.reflect.Field;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.view.View;
public class DialogHelper {
public static void Alert(Context ctx, CharSequence title, CharSequence message,
CharSequence okText, OnClickListener oklistener) {
AlertDialog.Builder builder = createDialog(ctx, title, message);
builder.setPositiveButton(okText, oklistener);
builder.create().show();
}
public static void Alert(Context ctx, int titleId, int messageId,
int okTextId, OnClickListener oklistener) {
Alert(ctx, ctx.getText(titleId), ctx.getText(messageId), ctx.getText(okTextId), oklistener);
}
public static void Confirm(Context ctx, CharSequence title, CharSequence message,
CharSequence okText, OnClickListener oklistener, CharSequence cancelText,
OnClickListener cancellistener) {
AlertDialog.Builder builder = createDialog(ctx, title, message);
builder.setPositiveButton(okText, oklistener);
builder.setNegativeButton(cancelText, cancellistener);
builder.create().show();
}
public static void Confirm(Context ctx, int titleId, int messageId,
int okTextId, OnClickListener oklistener, int cancelTextId,
OnClickListener cancellistener) {
Confirm(ctx, ctx.getText(titleId), ctx.getText(messageId), ctx.getText(okTextId), oklistener, ctx.getText(cancelTextId), cancellistener);
}
private static AlertDialog.Builder createDialog(Context ctx, CharSequence title,
CharSequence message) {
AlertDialog.Builder builder = new Builder(ctx);
builder.setMessage(message);
if(title!=null)
{
builder.setTitle(title);
}
return builder;
}
@SuppressWarnings("unused")
private static AlertDialog.Builder createDialog(Context ctx,int titleId, int messageId) {
AlertDialog.Builder builder = new Builder(ctx);
builder.setMessage(messageId);
builder.setTitle(titleId);
return builder;
}
public static void ViewDialog(Context ctx, CharSequence title, View view,
CharSequence okText, OnClickListener oklistener, CharSequence cancelText,
OnClickListener cancellistener) {
}
public static void ViewDialog(Context ctx, int titleId, View view,
int okTextId, OnClickListener oklistener, int cancelTextId,
OnClickListener cancellistener) {
ViewDialog(ctx, ctx.getText(titleId), view, ctx.getText(okTextId), oklistener, ctx.getText(cancelTextId), cancellistener);
}
//
public static void SetDialogShowing(DialogInterface dialog, boolean showing)
{
try {
Field field = dialog.getClass().getSuperclass().getDeclaredField("mShowing");
field.setAccessible(true);
field.set(dialog, showing);
} catch (Exception e) {
e.printStackTrace();
}
}
}
下面是又更新的話執(zhí)行回調(diào)函數(shù)提示用戶:
// 自動(dòng)更新回調(diào)函數(shù)
UpdateManager.UpdateCallback appUpdateCb = new UpdateManager.UpdateCallback()
{
public void downloadProgressChanged(int progress) {
if (updateProgressDialog != null
&& updateProgressDialog.isShowing()) {
updateProgressDialog.setProgress(progress);
}
}
public void downloadCompleted(Boolean sucess, CharSequence errorMsg) {
if (updateProgressDialog != null
&& updateProgressDialog.isShowing()) {
updateProgressDialog.dismiss();
}
if (sucess) {
updateMan.update();
} else {
DialogHelper.Confirm(Update_TestActivity.this,
R.string.dialog_error_title,
R.string.dialog_downfailed_msg,
R.string.dialog_downfailed_btnnext,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
updateMan.downloadPackage();
}
}, R.string.dialog_downfailed_btnnext, null);
}
}
public void downloadCanceled()
{
// TODO Auto-generated method stub
}
public void checkUpdateCompleted(Boolean hasUpdate,
CharSequence updateInfo) {
if (hasUpdate) {
DialogHelper.Confirm(Update_TestActivity.this,
getText(R.string.dialog_update_title),
getText(R.string.dialog_update_msg).toString()
+updateInfo+
getText(R.string.dialog_update_msg2).toString(),
getText(R.string.dialog_update_btnupdate),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
updateProgressDialog = new ProgressDialog(
Update_TestActivity.this);
updateProgressDialog
.setMessage(getText(R.string.dialog_downloading_msg));
updateProgressDialog.setIndeterminate(false);
updateProgressDialog
.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
updateProgressDialog.setMax(100);
updateProgressDialog.setProgress(0);
updateProgressDialog.show();
updateMan.downloadPackage();
}
},getText( R.string.dialog_update_btnnext), null);
}
}
};
要記得給程序添加權(quán)限:
<uses-permission android:name="android.permission.INTERNET"></uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
完整實(shí)例代碼點(diǎn)擊此處本站下載。
更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Android視圖View技巧總結(jié)》、《Android編程之a(chǎn)ctivity操作技巧總結(jié)》、《Android操作SQLite數(shù)據(jù)庫技巧總結(jié)》、《Android操作json格式數(shù)據(jù)技巧總結(jié)》、《Android數(shù)據(jù)庫操作技巧總結(jié)》、《Android文件操作技巧匯總》、《Android編程開發(fā)之SD卡操作方法匯總》、《Android開發(fā)入門與進(jìn)階教程》、《Android資源操作技巧匯總》及《Android控件用法總結(jié)》
希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。
- Android App自動(dòng)更新之通知欄下載
- Android實(shí)現(xiàn)APP自動(dòng)更新功能
- Android應(yīng)用APP自動(dòng)更新功能的代碼實(shí)現(xiàn)
- Android軟件自動(dòng)更新實(shí)現(xiàn)代碼
- Android如何實(shí)現(xiàn)APP自動(dòng)更新
- Android應(yīng)用自動(dòng)更新功能實(shí)現(xiàn)的方法
- 淺析Android手機(jī)衛(wèi)士關(guān)閉自動(dòng)更新
- Android App實(shí)現(xiàn)應(yīng)用內(nèi)部自動(dòng)更新的最基本方法示例
- Android編程實(shí)現(xiàn)應(yīng)用自動(dòng)更新、下載、安裝的方法
- Android7.0自動(dòng)更新適配 包解析異常
相關(guān)文章
Android使用Flutter實(shí)現(xiàn)錄音插件
這篇文章主要介紹了基于flutter實(shí)現(xiàn)錄音功能,介紹了如何錄音,如何把文件存放到本地,這些都是我們平常使用這個(gè)功能會(huì)遇到的問題。在使用的過程中遇到的問題也有列出,需要的朋友可以參考下2022-08-08
Android開發(fā)實(shí)現(xiàn)讀取Assets下文件及文件寫入存儲(chǔ)卡的方法
這篇文章主要介紹了Android開發(fā)實(shí)現(xiàn)讀取Assets下文件及文件寫入存儲(chǔ)卡的方法,涉及Android文件與目錄的讀取、寫入、轉(zhuǎn)換等相關(guān)操作技巧,需要的朋友可以參考下2017-10-10
Android實(shí)現(xiàn)支付寶6位密碼輸入界面
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)支付寶6位密碼輸入界面的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12
Android動(dòng)態(tài)模糊效果的快速實(shí)現(xiàn)方法
這篇文章主要介紹了Android動(dòng)態(tài)模糊效果的快速實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01
PopupWindow自定義位置顯示的實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了PopupWindow自定義位置顯示,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
Android實(shí)現(xiàn)狀態(tài)欄(statusbar)漸變效果的示例
本篇文章主要介紹了Android實(shí)現(xiàn)狀態(tài)欄(statusbar)漸變效果的示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09
Android實(shí)現(xiàn)點(diǎn)擊獲取驗(yàn)證碼倒計(jì)時(shí)效果
這篇文章主要介紹了Android實(shí)現(xiàn)點(diǎn)擊獲取驗(yàn)證碼倒計(jì)時(shí)效果,這種效果大家經(jīng)常遇到,想知道如何實(shí)現(xiàn)的,請(qǐng)閱讀本文2016-08-08
android實(shí)現(xiàn)倒計(jì)時(shí)功能的方法
這篇文章主要為大家詳細(xì)介紹了兩種android實(shí)現(xiàn)倒計(jì)時(shí)功能的方法,具有一定的實(shí)用性,感興趣的小伙伴們可以參考一下2016-08-08

