我们看到很多Android应用都具有自动更新功能,用户一键就可以完成软件的升级更新。得益于Android系统的软件包管理和安装机制,这一功能实现起来相当简单,下面我们就来实践一下。首先给出界面效果:

Android 应用的自动升级、更新模块的实现_第1张图片


1. 准备知识
在AndroidManifest.xml里定义了每个Android apk的版本标识:

1 <manifestxmlns:android="http://schemas.android.com/apk/res/android" 
2       package="com.myapp" 
3       android:versionCode="1" 
4       android:versionName="1.0.0"
5 <application>application
6 manifest>

其中,android:versionCode和android:versionName两个字段分别表示版本代码,版本名称。versionCode是 整型数字,versionName是字符串。由于version是给用户看的,不太容易比较大小,升级检查时,可以以检查versionCode为主,方 便比较出版本的前后大小。
那么,在应用中如何读取AndroidManifest.xml中的versionCode和versionName呢?可以使用PackageManager的API,参考以下代码:

01 public staticint getVerCode(Context context) {
02         intverCode = -1;
03         try{
04             verCode = context.getPackageManager().getPackageInfo(
05                     "com.myapp",0).versionCode;
06         } catch (NameNotFoundException e) {
07             Log.e(TAG, e.getMessage());
08         }
09         returnverCode;
10     }
11     
12     publicstatic String getVerName(Context context) {
13         String verName ="";
14         try{
15             verName = context.getPackageManager().getPackageInfo(
16                     "com.myapp",0).versionName;
17         } catch (NameNotFoundException e) {
18             Log.e(TAG, e.getMessage());
19         }
20         returnverName;  
21 }

或者在AndroidManifest中将android:versionName="1.2.0"写成 android:versionName="@string/app_versionName",然后在values/strings.xml中添加对应 字符串,这样实现之后,就可以使用如下代码获得版本名称:

1 public staticString getVerName(Context context) {
2         String verName = context.getResources()
3         .getText(R.string.app_versionName).toString();
4         returnverName;
5 }

同理,apk的应用名称可以这样获得:

1 public staticString getAppName(Context context) {
2         String verName = context.getResources()
3         .getText(R.string.app_name).toString();
4         returnverName;
5 }

2. 流程框架

Android 应用的自动升级、更新模块的实现_第2张图片

3. 版本检查
在服务端放置最新版本的apk文件,如:http://localhost/myapp/myapp.apk
同时,在服务端放置对应此apk的版本信息调用接口或者文件,如:http://localhost/myapp/ver.json
ver.json中的内容为:

[{"appname":"jtapp12","apkname":"jtapp-12-updateapksamples.apk","verName":1.0.1,"verCode":2}]  

然后,在手机客户端上进行版本读取和检查:

01 private booleangetServerVer () {
02         try{
03             String verjson = NetworkTool.getContent(Config.UPDATE_SERVER
04                     + Config.UPDATE_VERJSON);
05             JSONArray array =new JSONArray(verjson);
06             if(array.length() > 0) {
07                 JSONObject obj = array.getJSONObject(0);
08                 try{
09                     newVerCode = Integer.parseInt(obj.getString("verCode"));
10                     newVerName = obj.getString("verName");
11                 }catch (Exception e) {
12                     newVerCode = -1;
13                     newVerName ="";
14                     returnfalse;
15                 }
16             }
17         } catch (Exception e) {
18             Log.e(TAG, e.getMessage());
19             returnfalse;
20         }
21         returntrue;
22     }

比较服务器和客户端的版本,并进行更新操作。

1 if (getServerVerCode()) {
2          intvercode = Config.getVerCode(this);// 用到前面第一节写的方法
3          if(newVerCode > vercode) {
4              doNewVersionUpdate();// 更新新版本
5          } else {
6              notNewVersionShow();// 提示当前为最新版本
7          }
8      }

详细方法:

01 private voidnotNewVersionShow() {
02     intverCode = Config.getVerCode(this);
03     String verName = Config.getVerName(this);
04     StringBuffer sb =new StringBuffer();
05     sb.append("当前版本:");
06     sb.append(verName);
07     sb.append(" Code:");
08     sb.append(verCode);
09     sb.append(",/n已是最新版,无需更新!");
10     Dialog dialog =new AlertDialog.Builder(Update.this).setTitle("软件更新")
11             .setMessage(sb.toString())// 设置内容
12             .setPositiveButton("确定",// 设置确定按钮
13                     newDialogInterface.OnClickListener() {
14                         @Override
15                         publicvoid onClick(DialogInterface dialog,
16                                 intwhich) {
17                             finish();
18                         }
19                     }).create();// 创建
20     // 显示对话框
21     dialog.show();
22 }
23 private voiddoNewVersionUpdate() {
24     intverCode = Config.getVerCode(this);
25     String verName = Config.getVerName(this);
26     StringBuffer sb =new StringBuffer();
27     sb.append("当前版本:");
28     sb.append(verName);
29     sb.append(" Code:");
30     sb.append(verCode);
31     sb.append(", 发现新版本:");
32     sb.append(newVerName);
33     sb.append(" Code:");
34     sb.append(newVerCode);
35     sb.append(", 是否更新?");
36     Dialog dialog =new AlertDialog.Builder(Update.this)
37         .setTitle("软件更新")
38         .setMessage(sb.toString())
39         // 设置内容
40         .setPositiveButton("更新",// 设置确定按钮
41             newDialogInterface.OnClickListener() {
42                 @Override
43                 publicvoid onClick(DialogInterface dialog,
44                         intwhich) {
45                     pBar =new ProgressDialog(Update.this);
46                     pBar.setTitle("正在下载");
47                     pBar.setMessage("请稍候...");
48                     pBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
49                     downFile(Config.UPDATE_SERVER + Config.UPDATE_APKNAME);
50                 }
51             })
52         .setNegativeButton("暂不更新",
53             newDialogInterface.OnClickListener() {
54                 publicvoid onClick(DialogInterface dialog,
55                         intwhichButton) {
56                     // 点击"取消"按钮之后退出程序
57                     finish();
58                 }
59             }).create();// 创建
60     // 显示对话框
61     dialog.show();
62 }

4. 下载模块

注,本部分参考了前人的相关实现,见 http://apps.hi.baidu.com/share/detail/24172508

01 void downFile(finalString url) {
02 pBar.show();
03 new Thread() {
04     publicvoid run() {
05     HttpClient client =new DefaultHttpClient();
06     HttpGet get =new HttpGet(url);
07     HttpResponse response;
08     try{
09         response = client.execute(get);
10         HttpEntity entity = response.getEntity();
11         longlength = entity.getContentLength();
12         InputStream is = entity.getContent();
13         FileOutputStream fileOutputStream =null;
14         if(is != null) {
15         File file =new File(
16             Environment.getExternalStorageDirectory(),
17             Config.UPDATE_SAVENAME);
18         fileOutputStream =new FileOutputStream(file);
19         byte[] buf =new byte[1024];
20         intch = -1;
21         intcount = 0;
22         while((ch = is.read(buf)) != -1) {
23             fileOutputStream.write(buf,0, ch);
24             count += ch;
25             if(length > 0) {
26             }
27         }
28         }
29         fileOutputStream.flush();
30         if(fileOutputStream != null) {
31         fileOutputStream.close();
32         }
33         down();
34     } catch (ClientProtocolException e) {
35         e.printStackTrace();
36     } catch (IOException e) {
37         e.printStackTrace();
38     }
39     }
40 }.start();
41 }

下载完成,通过handler通知主ui线程将下载对话框取消。

1 void down() {
2         handler.post(newRunnable() {
3             publicvoid run() {
4                 pBar.cancel();
5                 update();
6             }
7         });
8 }

5. 安装应用

1     voidupdate() {
2         Intent intent =new Intent(Intent.ACTION_VIEW);
3         intent.setDataAndType(Uri.fromFile(newFile(Environment
4                 .getExternalStorageDirectory(), Config.UPDATE_SAVENAME)),
5                 "application/vnd.android.package-archive");
6         startActivity(intent);
7     }

如果你将apk应用发布到market上,那么,你会发现market内建了类似的模块,可以自动更新或者提醒你是否更新应用。那么,对于你自己的 应用需要自动更新的话,自己内建一个是不是更加方便了呢?本文提到的代码大多是在UpdateActivity.java中实现,为了能够使更新过程更加 友好,可以在最初launcher的Activity中建立一个线程,用来检查服务端是否有更新。有更新的时候就启动UpdateActivity,这样 的使用体验更加平滑。

本文例程源码查看/下载:
http://code.google.com/p/androidex/source/browse/trunk/jtapp-12-updateapksamples

版权归个人所有,转载请注明出处

http://blog.csdn.net/xjanker2/archive/2011/04/06/6303937.aspx


更多相关文章

  1. 2020版本Android 开发者学习路线(热门技术+学习方法+书籍+必须知
  2. Android studio中Git的学习和使用心得(二)在Android studio中如何
  3. Android Studio代码调试大全
  4. Android 实现闪屏页和右上角的倒计时跳转实例代码
  5. android语音识别方法示例代码
  6. Linux 3.3内核发布 融合Android源代码
  7. Android的代码都得自己一个个敲一遍吗?
  8. Android 电子书应用完全开源代码

随机推荐

  1. android版本号版本名
  2. Android(安卓)textview显示多行
  3. Ten Tips for Android(安卓)Application
  4. android 自学笔记2-布局
  5. android 指南针
  6. Custom Android(安卓)Window Title
  7. android中各种颜色在drawable.xml的值
  8. Android自定义对话框的使用
  9. Android之模仿微信登陆界面(二)
  10. Android(安卓)ProgressBar的动画效果