`
jaymsimusic
  • 浏览: 92646 次
  • 性别: 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:


public class hello extends Activity  { 
        /** Called when the activity is first created. */ 
        private Handler mHandler; 
          
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
         
        mHandler = new Handler(); 

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

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

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

            /* Start Update */ 
         //   checkUpdate.start(); 
        } 
    } 

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

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

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

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

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

    /* This Runnable creates a Dialog and asks the user to open the Market */ 
    private Runnable showUpdate = new Runnable(){ 
           public void run(){ 
            new AlertDialog.Builder(hello.this) 
            .setIcon(R.drawable.ok) 
            .setTitle("Update Available") 
            .setMessage("An update for is available!\n\nOpen Android Market and see the details?") 
            .setPositiveButton("Yes", new DialogInterface.OnClickListener() { 
                    public void onClick(DialogInterface dialog, int whichButton) { 
                            /* User clicked OK so do some stuff */ 
                            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market ://search?q=pname:your.app.id")); 
                            startActivity(intent); 
                    } 
            }) 
            .setNegativeButton("No", new DialogInterface.OnClickListener() { 
                    public void onClick(DialogInterface dialog, int whichButton) { 
                            /* User clicked Cancel */ 
                    } 
            }) 
            .show(); 
           } 
    }; 
   
} 



分为三个部分:

置于onCreate()方法中的程序用于判断当前时间是否需要检查更新(如果距离上次更新时间大于1天,将启动检查更新)
当以上条件满足时,启动checkUpdate来检查当前程序是否为最新版本。
如果确定版本已过期,那么将登录market,并直接指向当前程序页面。
*******************************************************************************************
向上言:
     本人在论坛 曾经发过一关于此问题的求助 帖,虽然大至的思路和上文差不多,关键点是在于程序如何更新,现在看到它这里指出的更新方法居然是登录market。不过以后发布的程序都是在market中,问题就不存在。

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

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

[2009-06-06 19:53:50 - Hello] Android Launch! 
[2009-06-06 19:53:50 - Hello] adb is running normally. 
[2009-06-06 19:53:50 - Hello] Performing linhai.com.hello.hello activity launch 
[2009-06-06 19:53:50 - Hello] Automatic Target Mode: using existing emulator 'emulator-5554' running compatible AVD 'avd' 
[2009-06-06 19:53:50 - Hello] WARNING: Application does not specify an API level requirement! 
[2009-06-06 19:53:50 - Hello] Device API version is 3 (Android 1.5) 
[2009-06-06 19:53:50 - Hello] Uploading Hello.apk onto device 'emulator-5554' 
[2009-06-06 19:53:50 - Hello] Installing Hello.apk... 
[2009-06-06 19:54:05 - Hello] Application already exists. Attempting to re-install instead... 
[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

06-06 11:54:02.567: DEBUG/PackageParser(582): Scanning package: /data/app/vmdl12464.tmp 
06-06 11:54:08.048: INFO/PackageManager(582): Removing non-system package:linhai.com.hello 
06-06 11:54:08.187: DEBUG/PackageManager(582): Removing package linhai.com.hello 
06-06 11:54:08.286: DEBUG/PackageManager(582):   Activities: linhai.com.hello.hello 
06-06 11:54:11.136: DEBUG/PackageManager(582): Scanning package linhai.com.hello 
06-06 11:54:11.301: INFO/PackageManager(582): /data/app/vmdl12464.tmp changed; unpacking 
06-06 11:54:11.626: DEBUG/installd(555): DexInv: --- BEGIN '/data/app/vmdl12464.tmp' --- 
06-06 11:54:12.987: DEBUG/dalvikvm(7756): DexOpt: load 224ms, verify 265ms, opt 1ms 
06-06 11:54:13.047: DEBUG/installd(555): DexInv: --- END '/data/app/vmdl12464.tmp' (success) --- 
06-06 11:54:13.057: DEBUG/PackageManager(582):   Activities: linhai.com.hello.hello 
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 
06-06 11:54:15.737: DEBUG/PackageManager(582): New package installed in /data/app/linhai.com.hello.apk 


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

int curVersion = getPackageManager().getPackageInfo("your.app.id", 0).versionCode; 

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

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

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

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

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

06-06 12:18:58.827: INFO/jdwp(8368): received file descriptor 20 from ADB 
06-06 12:19:02.546: DEBUG/PackageParser(582): Scanning package: /data/app/vmdl12465.tmp 
06-06 12:19:07.738: INFO/PackageManager(582): /data/app/vmdl12465.tmp changed; unpacking 
06-06 12:19:07.978: DEBUG/installd(555): DexInv: --- BEGIN '/data/app/vmdl12465.tmp' --- 
06-06 12:19:09.617: DEBUG/dalvikvm(8378): DexOpt: load 254ms, verify 564ms, opt 3ms 
06-06 12:19:09.697: DEBUG/installd(555): DexInv: --- END '/data/app/vmdl12465.tmp' (success) --- 
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 
06-06 12:19:11.956: DEBUG/PackageManager(582): New package installed in /data/app/com.example.android.snake.apk 
06-06 12:19:14.746: DEBUG/dalvikvm(8368): VM cleaning up 
06-06 12:19:14.857: DEBUG/dalvikvm(8368): LinearAlloc 0x0 used 628420 of 4194304 (14%) 
06-06 12:19:15.897: DEBUG/dalvikvm(582): GC freed 17704 objects / 903984 bytes in 615ms 
06-06 12:19:15.936: DEBUG/HomeLoaders(625): application intent received: android.intent.action.PACKAGE_ADDED, replacing=false 
06-06 12:19:15.936: DEBUG/HomeLoaders(625):   --> package:com.example.android.snake 
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中的结构

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


分享到:
评论

相关推荐

    DotNet,Socket聊天室程序,添加自动客户端自动应答功能

    DotNet,Socket聊天室程序,添加自动客户端自动应答功能

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

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

    淘宝客程序全自动采集版源码 淘宝客自动采集软件

    淘宝客程序API自动更新自动采集版 sk-taokeapi-v6.0 无需人工操作,配置淘点金和爱淘宝的爱搭配。 适用版本:sk-taokeapi-v6.0 安装方法: 解压之后把upload文件夹里面的文件 通过ftp软件上传至网上服务器空间的根...

    C# Winform WPF 自动更新(基于FTP)

    添加了本地黑名单文件夹功能 ========== 2023.12.30 进行了大幅度的优化,同时改动了一部分功能,具体更新内容参考帖子 ========== 2024.1.5 优化了部分代码 ========== 2024.1.13 优化了部分代码 有疑问欢迎私信我

    VB给程序添加随系统启动(开机自动运行)功能.rar

    VB给程序添加随系统启动(开机自动运行)功能,跟随WINDOWS启动的控件,不多介绍了,相信大多数搞VB的都知道是什么意思,把你的程序添加到开机启动列表里,电脑一启动,就自动打开你的程序,或最小化的托盘图标处。

    C# 为光盘添加AutoRun.ini自动运行功能

    C# 为光盘添加AutoRun.ini自动运行功能 C#为光盘添加自动运行功能,将添加一个AutoRun.ini的文件在程序目录中,高手请跳过,这个是为C#入门者准备的简单实例,功能与开机启动有些差别。

    vc 版本号自动增加

    VC自动更新版本号功能,可以在vc编译器里的pre build 里调用 计算检查和,可以在vc 编译器“生成后事件”调用。 注意,自动更新版本号时,如果增量编译,有时vc编译器并没有马上感应到有更新,未必将最新的rc文件...

    WinForm AutoUpdate自动更新源码

    WinForm AutoUpdate自动更新源码 - 代码已经全部验证测试并且用于项目。 - 升级程序有失败重试,失败回滚功能。

    .Net小型软件自动更新库(SimpAutoUpdater)v2.3.9

    本类库 工具用于快速实现一个简单的自动更新程序,旨在快速简单地为现有的.Net应用程序添加上比较简单的自动更新功能。 在发布应用程序时,我们经常会需要给自己的程序加上自动升级功能。.Net Framework自带的Click...

    MFC扫雷程序,完美复现WIN7扫雷,添加透视及自动扫雷功能

    本人在疫情隔离情况下,闲来无事开发此程序,在正常的扫雷功能下,为了提高游戏的成功率,还具备以下功能: 1. 首次点击后在生成雷的分布,在确保第一次点击不会是雷的基础上有三种模式设置(可在“游戏”-&gt;“选项...

    通用自动升级辅助程序

    &lt;br/&gt;具体说明: ftp路径是系统在服务器中的位置,自动更新文件下面的所有程序,如果稳定后不需要更新,则只要在服务器文件目录下面增加一个文件名为:neednotupdate.dh的文件就可以了(大小写区分),避免再...

    update-electron-app::evergreen_tree:一个插件模块,可为Electron应用程序添加自动更新功能

    更新电子应用一个插件模块,为Electron应用程序添加了自动更新功能由免费和开放源代码的服务提供支持。要求在使用此模块之前,请确保您的Electron应用程序满足以下条件: 您的应用程序可在macOS或Windows上运行您的...

    FTP远程文件同步更新程序

    FTP远程文件同步更新程序 ...架构软件轻松架构FTP服务器,从而达到使用本程序自动定时向FTP服务器上传更新的文件的功能。 ---------------------------------------------------------------------------------------

    企业微信群里自动添加客户高级版

    在找企业微信添加客户的看过来,给大家推荐一款可以免费试用的软件。 企业微信群里自动添加客户高级版,电脑上打开...程序全面升级,界面简单,直观,提示语丰富清晰,不绑定电脑,随处可用,自动升级最新程序 维护省心

    微信小程序前端自动切片生成布局软件

    微信小程序自动切片生成布局软件是一款根据效果图像画画一样来设计微信小程序,自动生成导出前端页面的快速开发工具。可以很方便、快速地生成小程序的wxml,wcss,js文件。可以大大提高您的工作效率,减少前端布局的...

    网商营销联盟数据库自动赚钱机器V1.0版程序源码

    网商营销联盟-数据库自动赚钱机器V1.0版程序源码免费下载 程序部分功能: 病毒式自动流量功能 序列邮件自动营销功能 会员中心自动营销功能 无限二级域名级推广功能 佣金计算功能 多级流量自动放大功能 联盟行销功能...

    VB添加开机启动,开机自动运行功能.rar

    VB添加开机启动,开机自动运行功能,通过修改注册表的方法,让程序随windows电脑系统自动启动运行,VB6.0设置注册表随WINDOWS自动启动的功能,用到了一个随WINDOWS自动启动/取消启动模块AutoRun.bas,你可将此模块...

    2019年最新版本网址铺吧网址导航源码程序按来路自动排行源码程序下载.rar

    2019年最新版本网址铺吧网址导航源码程序按来路自动排行源码程序下载。简介:【系统开发环境】 演示地址www.wzp8.com 1. 系统环境:MS WINDOWS 2003 +IIS 6.0 2. 数 据 库:MS Access2003 3. 测试浏览器:腾讯TT...

    小程序源码:社群微群人脉系统小程序版本源码下载带流量主功能实现广告效益

    现在因为小编在实现新版本的功能添加与更新 所以小编就把这一款开源分享给大家吧! 分享出来考虑到大家服务器等等效益所以小编就把后台给砍掉了 所以大家就直接前端上传到微信开发者工具即可使用 本款小程序群...

    易语言助手(ET助手)v2.14中文安装版模块自动加载功能

    易语言助手可以添加你想自动加载的模块到... 2、自动加载功能 可以添加你想自动加载的模块到自动加载分类上,当易语言启动时,就自动加载到易语言里。(目前只支持双击易语言主程序新建空程序时才能自动加载) 3、自定

Global site tag (gtag.js) - Google Analytics