zoukankan      html  css  js  c++  java
  • Android应用的自动升级、更新模块的实现

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


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

    1. <manifest xmlns: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,参考以下代码:
    1. public static int getVerCode(Context context) {  
    2.         int verCode = -1;  
    3.         try {  
    4.             verCode = context.getPackageManager().getPackageInfo(  
    5.                     "com.myapp"0).versionCode;  
    6.         } catch (NameNotFoundException e) {  
    7.             Log.e(TAG, e.getMessage());  
    8.         }  
    9.         return verCode;  
    10.     }  
    11.      
    12.     public static 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.         return verName;     
    21. }  

    或者在AndroidManifest中将android:versionName="1.2.0"写成android:versionName="@string/app_versionName",然后在values/strings.xml中添加对应字符串,这样实现之后,就可以使用如下代码获得版本名称:
    1. public static String getVerName(Context context) {  
    2.         String verName = context.getResources()  
    3.         .getText(R.string.app_versionName).toString();  
    4.         return verName;  
    5. }  

    同理,apk的应用名称可以这样获得:
    1. public static String getAppName(Context context) {  
    2.         String verName = context.getResources()  
    3.         .getText(R.string.app_name).toString();  
    4.         return verName;  
    5. }  

    2. 流程框架

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

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

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

    1. private boolean getServerVer () {  
    2.         try {  
    3.             String verjson = NetworkTool.getContent(Config.UPDATE_SERVER  
    4.                     + Config.UPDATE_VERJSON);  
    5.             JSONArray array = new JSONArray(verjson);  
    6.             if (array.length() > 0) {  
    7.                 JSONObject obj = array.getJSONObject(0);  
    8.                 try {  
    9.                     newVerCode = Integer.parseInt(obj.getString("verCode"));  
    10.                     newVerName = obj.getString("verName");  
    11.                 } catch (Exception e) {  
    12.                     newVerCode = -1;  
    13.                     newVerName = "";  
    14.                     return false;  
    15.                 }  
    16.             }  
    17.         } catch (Exception e) {  
    18.             Log.e(TAG, e.getMessage());  
    19.             return false;  
    20.         }  
    21.         return true;  
    22.     }  

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

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

    详细方法:

    1. private void notNewVersionShow() {  
    2.     int verCode = Config.getVerCode(this);  
    3.     String verName = Config.getVerName(this);  
    4.     StringBuffer sb = new StringBuffer();  
    5.     sb.append("当前版本:");  
    6.     sb.append(verName);  
    7.     sb.append(" Code:");  
    8.     sb.append(verCode);  
    9.     sb.append(",/n已是最新版,无需更新!");  
    10.     Dialog dialog = new AlertDialog.Builder(Update.this).setTitle("软件更新")  
    11.             .setMessage(sb.toString())// 设置内容  
    12.             .setPositiveButton("确定",// 设置确定按钮  
    13.                     new DialogInterface.OnClickListener() {  
    14.                         @Override  
    15.                         public void onClick(DialogInterface dialog,  
    16.                                 int which) {  
    17.                             finish();  
    18.                         }  
    19.                     }).create();// 创建  
    20.     // 显示对话框  
    21.     dialog.show();  
    22. }  
    23. private void doNewVersionUpdate() {  
    24.     int verCode = 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.                     new DialogInterface.OnClickListener() {  
    42.                         @Override  
    43.                         public void onClick(DialogInterface dialog,  
    44.                                 int which) {  
    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.                     new DialogInterface.OnClickListener() {  
    54.                         public void onClick(DialogInterface dialog,  
    55.                                 int whichButton) {  
    56.                             // 点击"取消"按钮之后退出程序  
    57.                             finish();  
    58.                         }  
    59.                     }).create();// 创建  
    60.     // 显示对话框  
    61.     dialog.show();  
    62. }  

    4. 下载模块

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

    1. void downFile(final String url) {  
    2.     pBar.show();  
    3.     new Thread() {  
    4.         public void run() {  
    5.             HttpClient client = new DefaultHttpClient();  
    6.             HttpGet get = new HttpGet(url);  
    7.             HttpResponse response;  
    8.             try {  
    9.                 response = client.execute(get);  
    10.                 HttpEntity entity = response.getEntity();  
    11.                 long length = 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.                     int ch = -1;  
    21.                     int count = 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(new Runnable() {  
    3.             public void run() {  
    4.                 pBar.cancel();  
    5.                 update();  
    6.             }  
    7.         });  
    8. }  
       

    5. 安装应用 

    1. void update() {  
    2.     Intent intent = new Intent(Intent.ACTION_VIEW);  
    3.     intent.setDataAndType(Uri.fromFile(new File(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

  • 相关阅读:
    P2082 区间覆盖(加强版)
    Java基础
    @import
    POST方式"Content-type"是"application/x-www-form-urlencoded 的请求遇到的问题
    VBox 安装 macOS 10.12
    对称加密和分组加密中的四种模式(ECB、CBC、CFB、OFB)
    window.location 属性
    post get 区别
    vue 生命周期
    记事本
  • 原文地址:https://www.cnblogs.com/chinatefl/p/2219956.html
Copyright © 2011-2022 走看看