Categories
Android

Android 2.2系统在线升级的移植

之前我们自己做过一个在线T卡升级的应用程序,设计思路是非常简单的,获取本地手机版本号,获取并解析服务器上json格式的最新信息,如果服务器上的版本号大于本地手机的版本号,则可以下载并md5验证升级包,然后调用系统函数升级即可。

从Android 2.2开始,Google服务框架 GoogleServicesFramework.apk 包自带的系统更新处理了android.settings.SYSTEM_UPDATE_SETTINGS这个intent。我们自己做的手机,当然不可能用Google自带的在线升级。为了不修改 GoogleServicesFramework.apk,在Settings的AndroidManifest.xml文件,把 SYSTEM_UPDATE_SETTINGS,修改为别的名字,比如 SYSTEM_UPGRADE_SETTINGS。 还需要同步修改这个文件:

Settings/res/xml/device_info_settings.xml
今天发神经病,花了一大早上的时候反编译GoogleServicesFramework里的update,看看别人如何设计的,就几个文件:
[deli@athena update]$ tree .
.
├── Download.java
├── StateWatcher.java
├── SystemUpdateActivity.java
├── SystemUpdateInstallDialog.java
├── SystemUpdateService.java
└── SystemUpdateVerifierTask.java

搞出600多行代码,才发现跟GoogleServicesFramework这个包里的其他代码非常缠绵,只好作罢。 大概思路也弄明白了,跟我们一样,也是用Downloads.ByUri 这个组件下载文件,
调用系统函数 RecoverySystem.installPackage(context, new File(filename)); 唯一的差别是没有网络连接的情况下,引导用户到设置的界面,比较人性化,很注重用户体验,我们直接跳出个对话框,没有网络连接,以后是要修改的。

默认的,installPackage 这个函数只支持文件放在 /data或/cahce 目录,但是,一般一个系统升级包有70M,一般机器不能保证有那么大的空间,我们只好把文件放在 SD card里,修改installPackage 函数,让它支持 sdcard 目录:

// from froyo, /sdcard ==> /mnt/sdcard
} else if (filename.startsWith("/mnt/sdcard/")) {
    filename = "SDCARD:" + filename.substring(12);

更新: 2011/7/23

一些网友遇到这样的 error:

FileNotFoundException: /cache/recovery/command (Permission denied)

记得在AndroidManifest.xml加上权限

<uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
<uses-permission android:name="android.permission.REBOOT" />

进阶:C2DM

使用 c2dm,给用户发push 通知消息,在状态栏提示有新版本可以更新啦。这部分的代码,可以参考大名鼎鼎的 CyanogenMod 的做法 CMUpdateNotify