`
xiexd
  • 浏览: 245479 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

为程序添加版本自动更新功能(转+详细分析)

阅读更多

OverView:
程序 通过后台每天检查是否有最新版本,如果需要更新当前版本,将弹出对话框让用户选择是否在当前通过Market来更新软件
Knowledge Points:

  • SharedPreferences: 一个轻量级的存储方法,类似于经常使用的.ini文件,它也是通过检索关键字来取得相应的数值。之所以是成为轻量级,是因为它所能应用 的数值类型有限,对于存储较大数值,效率相对较低。官方参考
  • System.currentTimeMillis:将当前时间以毫秒作为单位来表示,用于比较两个时间的先后顺序。(其数值表示从1970-01-01 00:00:00直到当前时间的总毫秒数)官方参考
  • 通过网络 来读取信息:在checkUpdate()方法中包含了通过制定的URL来读取网络资源。具体操作步骤,请参考源代码
  • Runnable: 在其内部的Run()方法中实现所要执行的任何代码,当这个runnable interface被调用后可以视作为新的线程。

Source Code:

  1. public class hello extends Activity  {
  2.         /** Called when the activity is first created. */
  3.         private Handler mHandler;
  4.          
  5.     @Override
  6.     public void onCreate(Bundle savedInstanceState) {
  7.         super.onCreate(savedInstanceState);
  8.         setContentView(R.layout.main);
  9.         
  10.         mHandler = new Handler();

  11.         /* Get Last Update Time from Preferences */
  12.         SharedPreferences prefs = getPreferences(0);
  13.         long lastUpdateTime =  prefs.getLong("lastUpdateTime", System.currentTimeMillis());

  14.         int curVersion = 0;
  15.                 try {
  16.                         curVersion = getPackageManager().getPackageInfo("linhai.com.hello", 0).versionCode;
  17.                 } catch (NameNotFoundException e) {
  18.                         // TODO Auto-generated catch block
  19.                         e.printStackTrace();
  20.                 }
  21.         Log.i("DEMO",String.valueOf(curVersion));
  22.         /* Should Activity Check for Updates Now? */
  23.         if ((lastUpdateTime + (24 * 60 * 60 * 1000)) < System.currentTimeMillis()) {

  24.             /* Save current timestamp for next Check*/
  25.            lastUpdateTime = System.currentTimeMillis();
  26.             SharedPreferences.Editor editor = getPreferences(0).edit();
  27.             editor.putLong("lastUpdateTime", lastUpdateTime);
  28.             editor.commit();      

  29.             /* Start Update */
  30.          //   checkUpdate.start();
  31.         }
  32.     }

  33.     /* This Thread checks for Updates in the Background */
  34.     private Thread checkUpdate = new Thread()
  35.     {
  36.         public void run() {
  37.             try {
  38.                 URL updateURL = new URL("http://my.company.com/update");
  39.                 URLConnection conn = updateURL.openConnection();
  40.                 InputStream is = conn.getInputStream();
  41.                 BufferedInputStream bis = new BufferedInputStream(is);
  42.                 ByteArrayBuffer baf = new ByteArrayBuffer(50);

  43.                 int current = 0;
  44.                 while((current = bis.read()) != -1){
  45.                      baf.app end((byte)current);
  46.                 }

  47.                 /* Convert the Bytes read to a String. */
  48.                 final String s = new String(baf.toByteArray());        

  49.                 /* Get current Version Number */
  50.                 int curVersion = getPackageManager().getPackageInfo("your.app.id", 0).versionCode;
  51.                 int newVersion = Integer.valueOf(s);

  52.                 /* Is a higher version than the current already out? */
  53.                 if (newVersion > curVersion) {
  54.                     /* Post a Handler for the UI to pick up and open the Dialog */
  55.                     mHandler.post(showUpdate);
  56.                 }
  57.             } catch (Exception e) {
  58.             }
  59.         }
  60.     };

  61.     /* This Runnable creates a Dialog and asks the user to open the Market */
  62.     private Runnable showUpdate = new Runnable(){
  63.            public void run(){
  64.             new AlertDialog.Builder(hello.this)
  65.             .setIcon(R.drawable.ok)
  66.             .setTitle("Update Available")
  67.             .setMessage ("An update for is available!\n\nOpen Android Market and see the details?")
  68.             .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
  69.                     public void onClick(DialogInterface dialog, int whichButton) {
  70.                             /* User clicked OK so do some stuff */
  71.                             Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market ://search?q=pname:your.app.id"));
  72.                             startActivity(intent);
  73.                     }
  74.             })
  75.             .setNegativeButton("No", new DialogInterface.OnClickListener() {
  76.                     public void onClick(DialogInterface dialog, int whichButton) {
  77.                             /* User clicked Cancel */
  78.                     }
  79.             })
  80.             .show();
  81.            }
  82.     };
  83.   
  84. }
复制代码



分为三个部分:

  • 置于onCreate()方法中的程序用于判断当前时间是否需要检查更新(如果距离上次更新时间大于1天,将启动检查更新)
  • 当以上条件满足时,启动checkUpdate来检查当前程序是否为最新版本。
  • 如果确定版本已过期,那么将登录market,并直接指向当前程序页面。

*******************************************************************************************
向上言:
     本人在论坛 曾经发过一关于此问题的求助 帖,虽然大至的思路和上文差不多,关键点是在于程序如何更新,现在看到它这里指出的更新方法居然是登录market。不过以后发布的程序都是在market中,问题就不存在。

  1.                             Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=pname:your.app.id"));
  2.                             startActivity(intent);
复制代码

大家都是在eclipse上开发 吧,在每次更新代码,运行 模拟器 时,大家是否有注意到console的提示信息:

  1. [2009-06-06 19:53:50 - Hello] Android Launch!
  2. [2009-06-06 19:53:50 - Hello] adb is running normally.
  3. [2009-06-06 19:53:50 - Hello] Performing linhai.com.hello.hello activity launch
  4. [2009-06-06 19:53:50 - Hello] Automatic Target Mode: using existing emulator 'emulator-5554' running compatible AVD 'avd'
  5. [2009-06-06 19:53:50 - Hello] WARNING: Application does not specify an API level requirement!
  6. [2009-06-06 19:53:50 - Hello] Device API version is 3 (Android 1.5)
  7. [2009-06-06 19:53:50 - Hello] Uploading Hello.apk onto device 'emulator-5554'
  8. [2009-06-06 19:53:50 - Hello] Installing Hello.apk...
  9. [2009-06-06 19:54:05 - Hello] Application already exists. Attempting to re-install instead...
  10. [2009-06-06 19:54:31 - Hello] Success!
复制代码

分析:
1。android 正常运行
2。通过配置文件AndroidManifest.xml中运行我们的程序
3。Uploading Hello.apk onto device 'emulator-5554' 这句是关键,更新我们的程序
4。Installing Hello.apk...
5。Application already exists. Attempting to re-install instead... //程序已经存在,尝试重新安装

所以如果我们的程序要自动更新,本人初步猜想是和上面的步骤是一样的。
详看logcat中的log

  1. 06-06 11:54:02.567: DEBUG/PackageParser(582): Scanning package: /data/app/vmdl12464.tmp
  2. 06-06 11:54:08.048: INFO/PackageManager(582): Removing non-system package:linhai.com.hello
  3. 06-06 11:54:08.187: DEBUG/PackageManager(582): Removing package linhai.com.hello
  4. 06-06 11:54:08.286: DEBUG/PackageManager(582):   Activities: linhai.com.hello.hello
  5. 06-06 11:54:11.136: DEBUG/PackageManager(582): Scanning package linhai.com.hello
  6. 06-06 11:54:11.301: INFO/PackageManager(582): /data/app/vmdl12464.tmp changed; unpacking
  7. 06-06 11:54:11.626: DEBUG/installd(555): DexInv: --- BEGIN '/data/app/vmdl12464.tmp' ---
  8. 06-06 11:54:12.987: DEBUG/dalvikvm(7756): DexOpt: load 224ms, verify 265ms, opt 1ms
  9. 06-06 11:54:13.047: DEBUG/installd(555): DexInv: --- END '/data/app/vmdl12464.tmp' (success) ---
  10. 06-06 11:54:13.057: DEBUG/PackageManager(582):   Activities: linhai.com.hello.hello
  11. 06-06 11:54:15.608: INFO/installd(555): move /data/dalvik-cache/data@app@vmdl12464.tmp@classes.dex -> /data/dalvik-cache/data@app@linhai.com.hello.apk@classes.dex
  12. 06-06 11:54:15.737: DEBUG/PackageManager(582): New package installed in /data/app/linhai.com.hello.apk
复制代码

关于此类的自动更新的第三方管理 软件已经有了叫aTrackDog ,其原理就是使用上面的方式。
关于得到版本号,使用:

  1. int curVersion = getPackageManager().getPackageInfo("your.app.id", 0).versionCode;
复制代码

程序版本号的是放在AndroidManifest.xml文件中:

  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2.         package="linhai.com.hello" android:versionCode="2" android:versionName="2.0.1">
复制代码

主点是关于:getPackageManager()在这个下面有很多方法,你可以通过它得,得到当前终端安装的程序等。关于安装包的函数是:getPackageManager().installPackage(packageURI)

动手试验:
在dos状态下运行:
1.JPG


查看logcat下的信息,大致和刚才相同,分析流程:

  1. 06-06 12:18:58.827: INFO/jdwp(8368): received file descriptor 20 from ADB
  2. 06-06 12:19:02.546: DEBUG/PackageParser(582): Scanning package: /data/app/vmdl12465.tmp
  3. 06-06 12:19:07.738: INFO/PackageManager(582): /data/app/vmdl12465.tmp changed; unpacking
  4. 06-06 12:19:07.978: DEBUG/installd(555): DexInv: --- BEGIN '/data/app/vmdl12465.tmp' ---
  5. 06-06 12:19:09.617: DEBUG/dalvikvm(8378): DexOpt: load 254ms, verify 564ms, opt 3ms
  6. 06-06 12:19:09.697: DEBUG/installd(555): DexInv: --- END '/data/app/vmdl12465.tmp' (success) ---
  7. 06-06 12:19:11.907: INFO/installd(555): move /data/dalvik-cache/data@app@vmdl12465.tmp@classes.dex -> /data/dalvik-cache/data@app@com.example.android.snake.apk@classes.dex
  8. 06-06 12:19:11.956: DEBUG/PackageManager(582): New package installed in /data/app/com.example.android.snake.apk
  9. 06-06 12:19:14.746: DEBUG/dalvikvm(8368): VM cleaning up
  10. 06-06 12:19:14.857: DEBUG/dalvikvm(8368): LinearAlloc 0x0 used 628420 of 4194304 (14%)
  11. 06-06 12:19:15.897: DEBUG/dalvikvm(582): GC freed 17704 objects / 903984 bytes in 615ms
  12. 06-06 12:19:15.936: DEBUG/HomeLoaders(625): application intent received: android.intent.action.PACKAGE_ADDED, replacing=false
  13. 06-06 12:19:15.936: DEBUG/HomeLoaders(625):   --> package:com.example.android.snake
  14. 06-06 12:19:15.936: DEBUG/HomeLoaders(625):   --> add package
复制代码

1。接收数据,保存到临时文件中/data/app/vmdl12465.tmp
2。解压此文件,注意路径/data/dalvik-cache/data@app@vmdl12465.tmp @classes.dex
它是在data下的dalvik-cache下
3.安装文件[这个步骤还包括查找程序是否已经安装等]
4.使用GC清理内存

查看DDMS中的结构
2.JPG


看到此文件结构,应该可以想起linux下的文件系统 和它的权限管理,也就可以理解,为什么我们的程序无法在data下创建文件之类的问题了。

关于aTrackDog程序相关信息:http://atrackdog.a0soft.com/intro.php

分享到:
评论

相关推荐

    编译时程序小版本自动递增

    使用c语言分析*.rc文件,达到文件版本号自动加1功能 autoversion.exe 参数为 *.rc文件(请使用绝对路径),有疑问或者需要源码可以留言

    计算机毕业设计-微信小程序农场管理系统(小程序)--+论文+项目源代码.rar

    微信小程序农场管理系统是一款专为现代农业设计的智能管理工具,通过微信小程序实现远程监控、数据分析与自动化管理。系统具备以下核心功能: 1. 实时监控:利用物联网技术,用户可通过小程序随时查看农场环境参数...

    毕设之电器维修系统小程序(源码+部署说明+SpringBoot+微信小程序+vue).zip

    该系统使用了SpringBoot作为后端框架,SpringBoot是一种快速开发框架,可以简化Java应用程序的开发过程,提供了一系列默认配置和自动装配的功能,使得开发者能够更加专注于业务逻辑的实现。 微信小程序是一种新型的...

    新项目基于机器学习的中文文本情感分析系统python源码(积极和消极)+详细使用说明+数据集+模型(保运行).zip

    新项目基于机器学习的中文文本情感分析系统python源码(积极和消极)+详细使用说明+数据集+模型(保运行).zip 【项目说明】 1、数据集已经制作好,可自行训练,样本含积极评价和负面评价。 2、项目含有项目使用说明,照...

    南方专业起名程序V7.12PronameSetup

    专业特性体现于程序自动 结合八字起名和分析姓名,名字有姓名学字义解释,多种姓名学知识查询等。娱乐特性体在姓名分析中有八字简单的分析,有名字打分等。此程序尤其适合姓名 学研究人员和从业人员。 南方专业...

    DirectX修复工具 V3.3增强 绿色版

    本程序有自动记录日志功能,可以记录每一次检测修复结果,方便在出现问题时,及时分析和查找原因,以便找到解决办法。 程序的“选项”对话框中包含了4项高级功能。点击其中的“注册系统文件夹中所有dll文件”按钮...

    网页标签分析器,用与自动填表功能的

    用于分析页面标签,实现网页外挂或者自动填表功能,这是一个dll程序集,可以在c#里添加引用,然后调用里面的方法,傻瓜式的运用,十分方便。

    小程序运营管理系统源码.zip

    无需代码编程,无需技术基础,简单的操作页面,清晰的模块分划,详尽的功能组件,让您短时间即可轻松玩转小程序。 垂直研发,深度挖掘行业解决方案 深入行业了解不同行业的痛点和需求,致力于解决实际问题,给客户...

    贼狗自动链(仿百度) v1.1.rar

    本程序采用了蜘蛛技术,自动识别网页编码,自动分析网页标题,自动处理html代码,保留有用的文字信息,像百度搜索面页那样. 以后每次有新的点击,自动链系统自动把最新点入的网站排在第一位. 贼狗1.1增加了后台广告...

    计算机程序设计的要点与规范分析-.docx

    计算机程序设计的要点与规范分析-全文共3页,当前为第1页。计算机程序设计的要点与规范分析-全文共3页,当前为第1页。计算机程序设计的要点与标准分析 计算机程序设计的要点与规范分析-全文共3页,当前为第1页。 ...

    j2ee实验-实现用户登录功能-servlet+jsp+mysql.zip

    在登录页面中输入正确的用户名... ...登录错误则自动跳转回到登录页面,并在登录页面中提示"登录错误"。 数据库字段有用户信息,内容为Maven工程、数据库脚本文件(logindb.sql)以及针对本程序的使用说明简述(readme.txt)。

    基于JavaWeb数据分析的关键词分析系统源码+项目使用说明.zip

    2) PDF文件转文本并分析所属公司 3) 指定关键词的类型指标分类统计 4) 统计结果的报表生成 5)向用户发送报表邮件 一、添加关心的公司 在分析前首先要做的工作就是添加需要分析统计的公司: 1. ...

    DIrectX老版本

     程序有自动更新c++功能。由于绝大多数软件运行时需要c++的支持,并且c++的异常也会导致0xc000007b错误,因此程序在检测修复的同时,也会根据需要更新系统中的c++组件。自V3.2版本开始使用了全新的c++扩展包,可以...

    基于ARIMA自回归模型对法国香槟的月销售额预测python实现完整源码+数据+详细注释.zip

    基于ARIMA自回归模型对法国香槟的月销售额预测python实现完整源码+数据+详细注释 包含 1.如何训练Embidding层 2.在Embidding层使用已训练好的词向量_glove 3.数据的初步 可视化分析;4.手动配置ARIMA参数;5.手动...

    HkeW3mModifier2.05

    [+]新增拖放添加 打开地图可以直接吧文件拖到程序上添加 由于技术不够 本来想写拖放解压的看样子不行了 1.8版更新 [+]新增双击列表运行文件的功能 [+]新增解压列表文件功能 [+]新增筛选结果功能 可以保留匹配项 也...

    高分毕业设计-基于uniapp+vue+微信小程序+安卓app实现的电影院订票小程序H5网站设计源代码+文档说明

    下面将进行后台管理系统上的功能分析。 1.首页 (1)访问后台管理系统的首页; 2.个人中心 (1)查看自己的个人信息; (2)可以修改密码; 3.用户管理 (1)可以根据学号、姓名、性别查找相关用户; (2)可以对...

    超级巡警病毒分析 File Format Identifier(自动查壳脱壳) v1.53 汉化版

    ★增加使用VMUnpacker脱壳引擎进行脱壳的功能,对识别出来的壳可直接点击Unpack按钮脱掉,方便分析加壳木马,本版本脱壳引擎脱壳能力等同于VMUnpacker V1.4 。 ★增加对附加数据的处理,可将附加数据直接删除或者...

    毕设之基于微信小程序的仓储管理系统_ri--(源码+部署说明+SpringBoot+微信小程序+vue).zip

    该系统旨在通过数字化手段优化库存管理流程,提高仓库作业效率,并为管理人员提供实时库存数据分析功能。 技术栈概览: 1. 微信小程序:作为客户端应用,提供用户交互界面,便于用户在移动设备上进行操作。 2. ...

    基于Python实现的Word助手的程序

    基于Python实现的Word助手程序是一个功能强大的文档处理工具,旨在提高用户在Word文档编辑、管理和自动化处理方面的效率。该程序利用Python语言的强大功能和丰富的库资源,为用户提供了一套高效、便捷的Word文档操作...

Global site tag (gtag.js) - Google Analytics