Android程序自动更新功能模块的实现方法【附完整demo源码下载】
本文实例讲述了Android程序自动更新功能模块的实现方法。分享给大家供大家参考,具体如下:
在程序启动的时候检测服务器上有没有对应版本更新,如果有更新,提示用户是否更新。
在程序启动的时候首先调用更新模块检测服务器上存放的版本号跟当前程序的版本号如果大于当前版本号,弹出更新对话框,如果用户选择更新,则显示当前更新状态,然后替换当前程序。
程序调用版本更新检测:
private UpdateManager updateMan;
private ProgressDialog updateProgressDialog;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//没有判断网路是否连接
//检查是否有更新
//如果有更新提示下载
updateMan = new UpdateManager(Update_TestActivity.this, appUpdateCb);
updateMan.checkUpdate();
}
执行检测版本号以及回调更新提示
下载更新文件等实现:
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文件相应的版本说明路径
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;
//从服务器上下载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(){
// ***************************************************************
@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);
}
}
需要连接服务器模块:
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");
}
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;
}
}
以及提示对话框:
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();
}
}
}
下面是又更新的话执行回调函数提示用户:
// 自动更新回调函数
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);
}
}
};
要记得给程序添加权限:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
完整实例代码点击此处本站下载。
更多关于Android相关内容感兴趣的读者可查看本站专题:《Android视图View技巧总结》、《Android编程之activity操作技巧总结》、《Android操作SQLite数据库技巧总结》、《Android操作json格式数据技巧总结》、《Android数据库操作技巧总结》、《Android文件操作技巧汇总》、《Android编程开发之SD卡操作方法汇总》、《Android开发入门与进阶教程》、《Android资源操作技巧汇总》及《Android控件用法总结》
希望本文所述对大家Android程序设计有所帮助。
您可能感兴趣的文章:Android App自动更新之通知栏下载Android实现APP自动更新功能Android应用APP自动更新功能的代码实现Android软件自动更新实现代码Android如何实现APP自动更新Android应用自动更新功能实现的方法浅析Android手机卫士关闭自动更新Android App实现应用内部自动更新的最基本方法示例Android编程实现应用自动更新、下载、安装的方法Android7.0自动更新适配 包解析异常
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341