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> 


 
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.} 

 
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.} 

 
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.} 

 
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.[{"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.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.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.} 


 
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.}  

 

注,本部分参考了前人的相关实现,见 http://www.linuxidc.com/Linux/2011-08/40309.htm
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.} 


 
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.} 


 
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.} 
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,这样的使用体验更加平滑。


关于Tomcat这部分我自己整理如下:

1)在Apache 官网http://tomcat.apache.org/下载安装就可以了,我自己装的是Tomcat 7.0版本。

2)在Tomcat安装默认路径下找到webapps文件夹并在该文件夹下新建一个myapp文件夹(你可以命名成你自己喜欢的文件夹名)

3)把上面提到的ver.json 文件保存放到myapp文件夹下

4)把你要升级安装的apk文件也放到myapp文件夹下就可以了

注意事项:访问android模拟器的端口是http://10.0.2.2:8080

 

 

本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2011-08/40308p3.htm

 

 

另附一篇文章:

/**
     * 安装新版本
     * @param context 当前实例上下文
     */
    public void InstallApk(Context context,String fileName){
        File f = new File(BasePath.DOWNLOAD_DIR,fileName);
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setAction(android.content.Intent.ACTION_VIEW);
        
        // 调用getMIMEType()来取得MimeType 
        String type = getMIMEType(f);
        //设定intent的file与MimeType 
        intent.setDataAndType(Uri.fromFile(f),type);
        context.startActivity(intent); 
    }
    
    /**
     * 判断文件MimeType的method 
     * @param f 要判断类型的文件
     * @return 文件的MiMe类型
     */
    public String getMIMEType(File f) 
    { 
        String type="";
        String fName=f.getName();
        // 取得扩展名 
        String end=fName.substring(fName.lastIndexOf(".")+1,fName.length()).toLowerCase(); 
    
        // 按扩展名的类型决定MimeType 
        if(end.equals("m4a")||end.equals("mp3")||end.equals("mid")||end.equals("xmf")||end.equals("ogg")||end.equals("wav")){
            type = "audio"; 
        }else if(end.equals("3gp")||end.equals("mp4")){
            type = "video";
        }else if(end.equals("jpg")||end.equals("gif")||end.equals("png")||end.equals("jpeg")||end.equals("bmp")){
            type = "image";
        }else if(end.equals("apk")) { 
            // android.permission.INSTALL_PACKAGES 
            type = "application/vnd.android.package-archive"; 
        } else{
            type="*";
        }
        //如果无法直接打开,就跳出软件清单给使用者选择 
        if(end.equals("apk")) { 
        } else { 
            type += "/*";  
        } 
        return type;  
      }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值