/*

 *注意,这篇文章转载自:

 *http://blog.csdn.net/xjanker2/article/details/6303937

 *一切权利归作者所有,这里只是转载,曾经用到过这篇文章里的方法。复制过来格式混乱,建议去原作者那里获得更好体验。

 *我在百度知道的提问

 */

我们看到很多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. public static String getVerName(Context context) {
  12. String verName = "";
  13. try {
  14. verName = context.getPackageManager().getPackageInfo(
  15. "com.myapp", 0).versionName;
  16. } catch (NameNotFoundException e) {
  17. Log.e(TAG, e.getMessage());
  18. }
  19. return verName;
  20. }

或者在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

[转载]Android版本更新与JSON解析的更多相关文章

  1. Android总结之json解析(FastJson Gson 对比)[申明:来源于网络]

    Android总结之json解析(FastJson Gson 对比)[申明:来源于网络] 地址:http://blog.csdn.net/u014031072/article/details/5392 ...

  2. Android开发之json解析

    目前正在尝试着写app,发现看懂代码和能写出来差距很大,最关键的是java基础比较的差,因为只会python,java基础只学习了一个礼拜就过了.感觉java写出来的代码不如python简单明了. 上 ...

  3. Android总结之json解析(FastJson Gson 对比)

    前言: 最近为了统一项目中使用的框架,发现项目中用到了两种json解析框架,他们就是当今非常主流的json解析框架:google的Gson 和阿里巴巴的FastJson,为了废除其中一个所以来个性能和 ...

  4. Android 中的Json解析工具fastjson 、序列化、反序列化

    Android中通常需要访问服务器,然而服务器返回的数据很多时候都是Json格式 1.fastjson简介 阿里巴巴FastJson是一个Json处理工具包,包括“序列化”和“反序列化”两部分,它具备 ...

  5. Android 图文数据JSON解析,金山词霸每日一句API的调用

    金山词霸开发的免费API http://open.iciba.com/dsapi/ 数据格式为 {","name":"\u7535\u5f71\u7ecf\u5 ...

  6. Android 图文数据JSON解析

    数据格式为 {"sid":"737","tts":"http:\/\/news.iciba.com\/admin\/tts\/20 ...

  7. 常用json解析库比较及选择 fastjson & gson

    一.常用json解析库比较及选择 1.简介 fastjson和gson是目前比较常用的json解析库,并且现在我们项目代码中,也在使用这两个解析库. fastjson 是由阿里开发的,号称是处理jso ...

  8. Android网络之数据解析----使用Google Gson解析Json数据

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  9. Qt on Android: http下载与Json解析

    百度提供有查询 ip 归属地的开放接口,当你在搜索框中输入一个 ip 地址进行搜索,就会打开由 ip138 提供的百度框应用,你能够在框内直接输入 ip 地址查询.我查看了页面请求,提取出查询 ip ...

随机推荐

  1. 邁向IT專家成功之路的三十則鐵律 鐵律十三:IT人理財之道-知足

    身為一位專業的IT人士,工作上不僅要做到滿足興趣與專業熱忱,當然也要做到能夠滿足荷包.現代人賺錢不是問題,但花錢卻出了很大問題,親愛的IT朋友們,請不要將您辛苦賺來的錢花在想要的東西上,實際上需要的卻 ...

  2. 一道简单DP题

    问题: 给定一个整数的数组,相邻的数不能同时选,求从该数组选取若干整数,使得他们的和最大,要求只能使用o(1)的空间复杂度.要求给出伪码. 解答: int maxSum(vector<int&g ...

  3. NN优化方法对照:梯度下降、随机梯度下降和批量梯度下降

    1.前言 这几种方法呢都是在求最优解中常常出现的方法,主要是应用迭代的思想来逼近.在梯度下降算法中.都是环绕下面这个式子展开: 当中在上面的式子中hθ(x)代表.输入为x的时候的其当时θ參数下的输出值 ...

  4. vim 树形菜单插件NERDTree 的安装

    vim 树形菜单插件的安装 NERDTree 1. mkdir ~/.vim cd ~/.vim mkdir bundle mkdir autoload 2.  curl -Sso ~/.vim/au ...

  5. 小胖说事20--------GCD笔记

    1.系统提供的dispatch方法 为了方便的使用GCD.苹果提供了一些方法方便我们将BLOCK放在主线程或者后台程序运行.或者延后运行. //后台运行: dispatch_async(dispatc ...

  6. 内核顶层Makefile相关4

    http://www.groad.net/bbs/simple/?f104.html make 的递归执行与 MAKEFLAGS 变量 make 的递归调用是指:在 Makefile 中使用 make ...

  7. jmeter后置处理器之正則表達式提取器

    新浪围脖>@o蜗牛快跑o    使用这个组件时,注意使用带分组的正則表達式 使用正则分组方便提取干净数据.以免再次处理数据字符串 正則表達式在线工具推荐:点击打开链接 正則表達式语法參考:点击打 ...

  8. AngularJs 在控制器中过滤

    <html> <head> <title>Simple app</title> <script src="https://ajax.go ...

  9. OSEck中odo_vect2pcb的作用

    在基于OSEck RTOS的TI DSP中,中断能够作为一个进程存在,在OSEck系统中,进程分为两类:优先级进程,中断进程. 当可屏蔽中断(INT4~15)发生后,就会运行相应的中断vector,在 ...

  10. C# wince 实现软件忙鼠标状态改变

    eg: Cursor.Current = Cursors.WaitCursor; dosomething(); Cursor.Current = Cursors.Default; Cursor.Cur ...