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

本文介绍了一种Android应用自动更新的实现方式,包括利用SharedPreferences记录更新时间、通过网络检查新版本以及通过Market引导用户更新等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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. @Override
  5. public void onCreate(Bundle savedInstanceState) {
  6. super.onCreate(savedInstanceState);
  7. setContentView(R.layout.main);
  8. mHandler = new Handler();
  9. /* Get Last Update Time from Preferences */
  10. SharedPreferences prefs = getPreferences(0);
  11. long lastUpdateTime =prefs.getLong("lastUpdateTime", System.currentTimeMillis());
  12. int curVersion = 0;
  13. try {
  14. curVersion = getPackageManager().getPackageInfo("linhai.com.hello", 0).versionCode;
  15. } catch (NameNotFoundException e) {
  16. // TODO Auto-generated catch block
  17. e.printStackTrace();
  18. }
  19. Log.i("DEMO",String.valueOf(curVersion));
  20. /* Should Activity Check for Updates Now? */
  21. if ((lastUpdateTime + (24 * 60 * 60 * 1000)) < System.currentTimeMillis()) {
  22. /* Save current timestamp for next Check*/
  23. lastUpdateTime = System.currentTimeMillis();
  24. SharedPreferences.Editor editor = getPreferences(0).edit();
  25. editor.putLong("lastUpdateTime", lastUpdateTime);
  26. editor.commit();
  27. /* Start Update */
  28. // checkUpdate.start();
  29. }
  30. }
  31. /* This Thread checks for Updates in the Background */
  32. private Thread checkUpdate = new Thread()
  33. {
  34. public void run() {
  35. try {
  36. URL updateURL = new URL("http://my.company.com/update");
  37. URLConnection conn = updateURL.openConnection();
  38. InputStream is = conn.getInputStream();
  39. BufferedInputStream bis = new BufferedInputStream(is);
  40. ByteArrayBuffer baf = new ByteArrayBuffer(50);
  41. int current = 0;
  42. while((current = bis.read()) != -1){
  43. baf.append((byte)current);
  44. }
  45. /* Convert the Bytes read to a String. */
  46. final String s = new String(baf.toByteArray());
  47. /* Get current Version Number */
  48. int curVersion = getPackageManager().getPackageInfo("your.app.id", 0).versionCode;
  49. int newVersion = Integer.valueOf(s);
  50. /* Is a higher version than the current already out? */
  51. if (newVersion > curVersion) {
  52. /* Post a Handler for the UI to pick up and open the Dialog */
  53. mHandler.post(showUpdate);
  54. }
  55. } catch (Exception e) {
  56. }
  57. }
  58. };
  59. /* This Runnable creates a Dialog and asks the user to open the Market */
  60. private Runnable showUpdate = new Runnable(){
  61. public void run(){
  62. new AlertDialog.Builder(hello.this)
  63. .setIcon(R.drawable.ok)
  64. .setTitle("Update Available")
  65. .setMessage("An update for is available!\n\nOpen Android Market and see the details?")
  66. .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
  67. public void onClick(DialogInterface dialog, int whichButton) {
  68. /* User clicked OK so do some stuff */
  69. Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=pname:your.app.id"));
  70. startActivity(intent);
  71. }
  72. })
  73. .setNegativeButton("No", new DialogInterface.OnClickListener() {
  74. public void onClick(DialogInterface dialog, int whichButton) {
  75. /* User clicked Cancel */
  76. }
  77. })
  78. .show();
  79. }
  80. };
  81. }
复制代码


分为三个部分:
  • 置于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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值