• Android应用的自动升级、更新模块的实现(转)


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


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

    [xhtml] view plaincopy
     
    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,参考以下代码:

    [java] view plaincopy
     
    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中添加对应字符串,这样实现之后,就可以使用如下代码获得版本名称:

    [java] view plaincopy
     
    1. public static String getVerName(Context context) {  
    2.         String verName = context.getResources()  
    3.         .getText(R.string.app_versionName).toString();  
    4.         return verName;  
    5. }  


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

    [java] view plaincopy
     
    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中的内容为:

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

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

    [java] view plaincopy
     
    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.     }  

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

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

    详细方法:

    [java] view plaincopy
     
    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

    [java] view plaincopy
     
    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线程将下载对话框取消。

    [java] view plaincopy
     
    1. void down() {  
    2.         handler.post(new Runnable() {  
    3.             public void run() {  
    4.                 pBar.cancel();  
    5.                 update();  
    6.             }  
    7.         });  
    8. }  

       

    5. 安装应用 

    [java] view plaincopy
     
    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

  • 相关阅读:
    《Django By Example》第十二章(终章) 中文 翻译 (个人学习,渣翻)
    《Django By Example》第十一章 中文 翻译 (个人学习,渣翻)
    《Django By Example》第十章 中文 翻译 (个人学习,渣翻)
    《Django By Example》第九章 中文 翻译 (个人学习,渣翻)
    《Django By Example》第八章 中文 翻译 (个人学习,渣翻)
    《Django By Example》第五章 中文 翻译 (个人学习,渣翻)
    我的superui开源后台bootstrap开发框架
    LayoutInflater 总结
    Android屏幕分辨率概念(dp、dip、dpi、sp、px)
    android studio安装问题
  • 原文地址:https://www.cnblogs.com/ada-zheng/p/3458909.html
Copyright © 2020-2023  润新知