Android本地升级原理及流程(一,上层)

1.首先,我们了解一下进入进入系统更新的操作步骤;设置-->关于手机-->系统更新

①设置界面进入系统更新的设置界面为设置模块下DeviceInfoSettings.java类,所对应preference为Device_info_settings.xml中如下:

<com.android.settings.XXUpdatePreference android:key="system_update_settings"

android:title="@string/system_update_settings_list_item_title"

android:summary="@string/system_update_settings_list_item_summary">

<intent android:action="android.settings.SYSTEM_UPDATE_SETTINGS" />

</com.android.settings.XXUpdatePreference>

 ②我们在DeviceInfoSettings.java中对该preference进行监听,当用户触发点击事件时发出广播,XXX应用会接收该广播并启动XXX做出下一步处理。如下所示:

else if (preference.getKey().equals(KEY_DMSW_UPDATE)) {

// /M: for DMSW to broadcast @{

Intent i = new Intent();

i.setAction("com.mediatek.DMSWUPDATE");

getActivity().sendBroadcast(i);

// /@}

}

2.一般来说,由于Android原生态的系统更新体验一般,我们手机中的系统更新应用都是厂商定制的,也就是说我们点击系统更新时一般进入的都是厂商定制的系统更新应用,这里我们先不赘述,随后的博文中会针对原生中的系统更新应用进行一个分析。

    ①这里我们跳过,只在厂商定制的应用中选择本地升级,然后进入设置警告界面SystemUpgradeChooserActivity.java(升级过程中,请不要移除电池,SIM卡和存储卡。。。。。。),然后我们通过点击确定并进入升级提醒界面(升级将在两到五分钟完成。。。。。。),部分代码如下:

case R.id.okButton:

//是否挂在SDCard

if (!hasSDCard()) {

showToast(R.string.no_sd_card);

return;

}

//更新包是否存在

if (file == null || !file.exists()) {

showToast(R.string.no_update_file);

return;

}

//进入升级提醒界面

Intent intent = new Intent(SystemUpgradeChooserActivity.this,UpdateToStart.class);

startActivity(intent);

break;

    ②此时我们通过intent进入到升级提醒界面UpdateToStart.java,这里我们点击确定开始安装更新包,详细代码如下:

buttonOkUp.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

try {

//是否挂在SDCard

if (!hasSDCard()) {

showToast(R.string.no_sd_card);

return;

}

//更新文件是否存在

File file = new File(Environment.getExternalStorageDirectory() + "/dload/update.zip");

if (file == null || !file.exists()) {

showToast(R.string.no_update_file);

return;

}

//安装更新包,这是上层系统新的关键

RecoverySystem.installPackage(getApplicationContext(), file);

}

catch (Exception e) {

//

}

}

});

3.上面我们了解了,通过调用RecoverySystem.installPackage()方法尽心安装更新包。具体方法如下:

/**

*为了安装更新包将会重启设备,此外要调用该方法需要在清单文件中增加REBOOT权限

* 参数 context 上下文

* 参数 packageFile  封装更新包路径等信息的file对象.

*/

public static void installPackage(Context context, File packageFile)

throws IOException {

String filename = packageFile.getCanonicalPath();

Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");

        //参数拼接,该参数最终会写入BCB,也就是说设备重启进入Recovery模式后,Recovery.cpp将会解析该参数,并且根据参数做出操作,它将会被传入到bootcommand(context,arg)函数中去。

  String arg = "--update_package=" + filename +

"\n--locale=" + Locale.getDefault().toString();

bootCommand(context, arg);

}

4.下面是对bootCommand进行分析。

private static void bootCommand(Context context, String arg) throws IOException {

RECOVERY_DIR.mkdirs();  // 创建/cache/recovery目录

COMMAND_FILE.delete();  // 删除command文件,进行初始化

LOG_FILE.delete();//删除log文件,进行初始化

Log.d(TAG,"Preapre to write command: " + arg +"\n");

WriteByFdSync(COMMAND_FILE,arg);//将参数写入到command文件中

Log.d(TAG,"Success to write command: " + arg +"\n");

Log.d(TAG,"Current build type is: " + Build.TYPE +"\n");

ReadInAndPrint(COMMAND_FILE);//读取command文件,并打印log

// Having written the command file, go ahead and reboot

PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);//从系统服务中获得PowerManager实例

pm.reboot("recovery");//重启

Log.d(TAG,"!!! pm.reboot failed !!!\n");

throw new IOException("Reboot failed (no permissions?)");

}

下面的方法调用流程为PowerManager:reboot("recovery")-->PowerManagerService:reboot(reason)

-->PowerManagerService:shtudownOrRebootInternal(false,confirm,reason,wait)

-->PowerManagerService:shutdownOrRebootInternal(...)

-->ShutdownThread:reboot(mContext, reason, confirm);

-->ShutdownThread:run():running()......

@Override // Binder call

public void reboot(boolean confirm, String reason, boolean wait) {

mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);

Slog.i(TAG, "reboot call pid: " + Binder.getCallingPid() + " uid: " + Binder.getCallingUid());

final long ident = Binder.clearCallingIdentity();

try {

shutdownOrRebootInternal(false, confirm, reason, wait);

} finally {

Binder.restoreCallingIdentity(ident);

}

}

private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm,

final String reason, boolean wait) {

if (mHandler == null || !mSystemReady) {

throw new IllegalStateException("Too early to call shutdown() or reboot()");

}

Runnable runnable = new Runnable() {

@Override

public void run() {

synchronized (this) {

if (shutdown) {

ShutdownThread.shutdown(mContext, confirm);

} else {

ShutdownThread.reboot(mContext, reason, confirm);

}

}

}

};

// ShutdownThread must run on a looper capable of displaying the UI.

Message msg = Message.obtain(mHandler, runnable);

msg.setAsynchronous(true);

mHandler.sendMessage(msg);

// PowerManager.reboot() is documented not to return so just wait for the inevitable.

if (wait) {

synchronized (runnable) {

while (true) {

try {

runnable.wait();

} catch (InterruptedException e) {

}

}

}

}

}

public static void reboot(final Context context, String reason, boolean confirm) {

mReboot = true;

mRebootSafeMode = false;

mRebootReason = reason;

Log.d(TAG, "reboot");

if (mSpew) {

StackTraceElement[] stack = new Throwable().getStackTrace();

for (StackTraceElement element : stack)

{

Log.d(TAG, "      |----" + element.toString());

}

}

shutdownInner(context, confirm);

}

这里在run方法下的,running方法中将重启原因写入系统属性文件中去。

。。。。。。

{

String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : "");

SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);

}

。。。。。。

    最后,重启设备。

时间: 2024-10-13 08:42:56

Android本地升级原理及流程(一,上层)的相关文章

Android差分升级原理和实现方式

增量升级概述 增量升级的原理很简单,即首先将应用的旧版本Apk与新版本Apk做差分,得到更新的部分的补丁,例如旧版本的APK有20M,新版的有21M,更新的部分则可能只有1M左右,这里需要说明的是,得到的差分包大小并不是简单的相减,因为需要包含一些上下文相关的东西,使用差分升级的好处显而易见,那么你不需要下载完整的21M文件,只需要下载更新部分就可以,而更新部分的差分包很小,可以很大程度上减少流量的损失. Apk增量升级过程 1.  在服务器上生成一个patch. 2.  下载patch到手机中

C# Xamarin For Android自动升级项目实战

一.课程介绍 "明人不说暗话,跟着阿笨一起玩Xamarin",本次分享课程阿笨将带来大家一起学习Xamarin For Android系列<C# Xamarin For Android自动升级项目实战>.如果您同样对本次分享课程感兴趣的话,那么请跟着阿笨一起学习吧. 本次分享课程适合人群如下: 1. 热爱Xamarin跨平台移动开发. 2.进一步了解和学习Xamarin For Android移动开发实战知识. 本次分享课包含实战分享知识点如下: 1.C# Android 

Android Root原理和流程分析

预备知识 android手机的内部存储设备分RAM和ROM,RAM是运行内存,掉电就会失去所有内容:ROM中的内容掉电后也不会丢失. 比如一台手机的规格参数里写着"2G RAM,16G ROM".理论上,RAM越大,系统运行越流畅.像大型的3D游戏,运行时需要约300M的内存,那么在内存2G的手机上就可以流畅的运行,在512M内存的手机上几乎跑不起来,跑起来也会卡死.我们可以在"设置-管理应用程序-正在运行"中看到手机目前剩余的RAM,一般2GRAM的手机显示可用R

Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整(原理:底层SurfaceView+上层绘制ImageView)

Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整实现(原理:底层SurfaceView+上层绘制ImageView) 分类: Android开发 Android UI2013-05-23 15:04 1600人阅读 评论(1) 收藏 举报 目录(?)[+] http://blog.csdn.net/yanzi1225627/article/details/8580034 最近一直在审视以前做过的东西,关于android摄像头预览,预览界面上呈现矩形框,在

Android在线升级相关笔记一(解析服务器版本与当前版本比较)

大概流程:Android客户端去访问服务器上的封装了版本号等信息的xml文件,对服务器上的版本和当前版本进行比较, 如果低于服务器的版本,则下载服务器上的新版软件,进行安装替换,完成升级. 一.首先用tomcat搭建服务器,用于开发测试. 下载tomcat请参考:http://blog.csdn.net/only_tan/article/details/25110625 1.在tomcat中新建自己的项目: \apache-tomcat-6.0.39\webapps 目录下新建自己的项目文件夹,

android MultiDex multidex原理原理下遇见的N个深坑(二)

android MultiDex 原理下遇见的N个深坑(二) 这是在一个论坛看到的问题,其实你不知道MultiDex到底有多坑. 不了解的可以先看上篇文章:android MultiDex multidex原理(一) 解决和遇到的其它问题,请见下一篇文章:android MultiDex 原理下超出方法数的限制问题(三) 遭遇multidex 愉快地写着Android代码的总悟君往工程里引入了一个默默无闻的jar然后Run了一下~~~~ 经过漫长的等待AndroidStudio构建失败了. 于是

Linux可插拔认证模块(PAM)的配置文件、工作原理与流程

PAM的配置文件: 我们注意到,配置文件也放在了在应用接口层中,他与PAM API配合使用,从而达到了在应用中灵活插入所需鉴别模块的目的.他的作用主要是为应用选定具体的鉴别模块,模块间的组合以及规定模块的行为.下面是一个示例配置文件: # cat /etc/pam.d/system-auth: #%PAM-1.0 # This file is auto-generated. # User changes will be destroyed the next time authconfig is

Android增量升级简单实现(附源码)

随着现在手机硬件不断的提升,分辨率提高手机的安装包也是越来越大了.当年NOKIA,MOTO时代,一个手机APP如果有1MB那都是算大的,2MB已经不得了了.虽然网络.存储都已经大大提升,但是流量还不至于廉价到APP改了一个标题要去下载一个几兆的程序安装包.今天就介绍安卓增量下载的实现.有耐心的先看原理,后面实践! 增量升级的原理 今天我们就来实现类似的应用的增量升级.其实增量升级的原理很简单,即首先将应用的旧版本Apk与新版本Apk做差分,得到更新的部分的补丁,例如旧版本的APK有5M,新版的有

android Binder机制原理

Android Binder机制原理(史上最强理解,没有之一)(转) 原文地址: http://blog.csdn.net/universus/article/details/6211589 Binder是Android系统进程间通信(IPC)方式之一.Linux已经拥有的进程间通信IPC手段包括(Internet Process Connection): 管道(Pipe).信号(Signal)和跟踪(Trace).插口(Socket).报文队列(Message).共享内存(Share Memo