編輯:關於Android編程
昨天開會討論IP網絡升級時,需要一個後台服務做升級檢測及下載數據,最後在定義下載的數據存放位置及如何做開機標志時,突然發現一個很好用的上層java類對象。
frameworks\base\core\java\android\os\RecoverySystem.java
那麼這個類做了什麼事情呢?又是如何做到的。
RecoverySystem類,可以幫助我們調用系統還原等操作:
android.os.RecoverySystem,提供了如下靜態方法
static void installPackage(Context context, File packageFile) //重啟設備,安裝一個更新包
static void rebootWipeUserData(Context context) //重啟設備,清除用戶數據分區類似恢復出廠設置
static String handleAftermath() 提供清除recover中相關文件,在開機廣播中被調用
static void verifyPackage(File packageFile, RecoverySystem.ProgressListener listener, File deviceCertsZipFile) //驗證加密簽名的系統更新包在安裝前,其中第二個數接口的具體定義為 android.os.RecoverySystem.ProgressListener 其中只有一個回調方法 abstract void onProgress(int progress) 來顯示效驗的進度。
下面具體看一下代碼中是如何實現:
1、安裝更新包:
/**
* Reboots the device in order to install the given update
* package.
* Requires the {@link android.Manifest.permission#REBOOT} permission.
*
* @param context the Context to use
* @param packageFile the update package to install. Must be on
* a partition mountable by recovery. (The set of partitions
* known to recovery may vary from device to device. Generally,
* /cache and /data are safe.)
*
* @throws IOException if writing the recovery command file
* fails, or if the reboot itself fails.
*/
public static void installPackage(Context context, File packageFile)
throws IOException {
String filename = packageFile.getCanonicalPath();
Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
String arg = "--update_package=" + filename;
bootCommand(context, arg); // 都是調用了這個函數
}
/**
* Reboot into the recovery system with the supplied argument.
* @param arg to pass to the recovery utility.
* @throws IOException if something goes wrong.
*/
private static void bootCommand(Context context, String arg) throws IOException {
RECOVERY_DIR.mkdirs(); // In case we need it
COMMAND_FILE.delete(); // In case it's not writable
LOG_FILE.delete();
FileWriter command = new FileWriter(COMMAND_FILE); // 寫命令寫入到recover中
try {
command.write(arg);
command.write("\n");
} finally {
command.close();
}
// Having written the command file, go ahead and reboot 系統重啟
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
pm.reboot("recovery");
throw new IOException("Reboot failed (no permissions?)");
}
/**
* Reboots the device in order to install the given update
* package.
* Requires the {@link android.Manifest.permission#REBOOT} permission.
*
* @param context the Context to use
* @param packageFile the update package to install. Must be on
* a partition mountable by recovery. (The set of partitions
* known to recovery may vary from device to device. Generally,
* /cache and /data are safe.)
*
* @throws IOException if writing the recovery command file
* fails, or if the reboot itself fails.
*/
public static void installPackage(Context context, File packageFile)
throws IOException {
String filename = packageFile.getCanonicalPath();
Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
String arg = "--update_package=" + filename;
bootCommand(context, arg); // 都是調用了這個函數
}
/**
* Reboot into the recovery system with the supplied argument.
* @param arg to pass to the recovery utility.
* @throws IOException if something goes wrong.
*/
private static void bootCommand(Context context, String arg) throws IOException {
RECOVERY_DIR.mkdirs(); // In case we need it
COMMAND_FILE.delete(); // In case it's not writable
LOG_FILE.delete();
FileWriter command = new FileWriter(COMMAND_FILE); // 寫命令寫入到recover中
try {
command.write(arg);
command.write("\n");
} finally {
command.close();
}
// Having written the command file, go ahead and reboot 系統重啟
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
pm.reboot("recovery");
throw new IOException("Reboot failed (no permissions?)");
}
2、出廠恢復
/**
* Reboots the device and wipes the user data partition. This is
* sometimes called a "factory reset", which is something of a
* misnomer because the system partition is not restored to its
* factory state.
* Requires the {@link android.Manifest.permission#REBOOT} permission.
*
* @param context the Context to use
*
* @throws IOException if writing the recovery command file
* fails, or if the reboot itself fails.
*/
public static void rebootWipeUserData(Context context) throws IOException {
final ConditionVariable condition = new ConditionVariable();
Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION");
context.sendOrderedBroadcast(intent, android.Manifest.permission.MASTER_CLEAR,
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
condition.open();
}
}, null, 0, null, null);
// Block until the ordered broadcast has completed.
condition.block();
bootCommand(context, "--wipe_data");
}
/**
* Reboot into the recovery system to wipe the /cache partition.
* @throws IOException if something goes wrong.
*/
public static void rebootWipeCache(Context context) throws IOException {
bootCommand(context, "--wipe_cache");
}
/**
* Reboots the device and wipes the user data partition. This is
* sometimes called a "factory reset", which is something of a
* misnomer because the system partition is not restored to its
* factory state.
* Requires the {@link android.Manifest.permission#REBOOT} permission.
*
* @param context the Context to use
*
* @throws IOException if writing the recovery command file
* fails, or if the reboot itself fails.
*/
public static void rebootWipeUserData(Context context) throws IOException {
final ConditionVariable condition = new ConditionVariable();
Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION");
context.sendOrderedBroadcast(intent, android.Manifest.permission.MASTER_CLEAR,
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
condition.open();
}
}, null, 0, null, null);
// Block until the ordered broadcast has completed.
condition.block();
bootCommand(context, "--wipe_data");
}
/**
* Reboot into the recovery system to wipe the /cache partition.
* @throws IOException if something goes wrong.
*/
public static void rebootWipeCache(Context context) throws IOException {
bootCommand(context, "--wipe_cache");
}
3、驗證簽名
public static void verifyPackage(File packageFile,
ProgressListener listener,
File deviceCertsZipFile) 請自行閱讀源碼
後面說一下重啟 reboot 命令如何執行的:
無論是 factory reset 工廠恢復還是 安裝更新包都會調用到reboot函數,調用 pm.reboot("recovery");
通到jni就是: android_os_Power.cpp
shutdown 調用 android_reboot(ANDROID_RB_POWEROFF, 0, 0);
reboot 調用 android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars);
最終都是調用到下面函數:
int reboot (int mode)
{
return __reboot( LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, mode, NULL );
}
=====linux kernel 內核流程=====
/bionic/libc/arch-arm/syscalls/__reboot.S
這個文件由gensyscalls.py自動產生,調用系統調用 __NR_reboot
bionic/libc/include/sys/linux-syscalls.h
#define __NR_reboot (__NR_SYSCALL_BASE+88)
/arch/arm/kernel/calls.S
__NR_reboot?就是系統函數sys_reboot
sys_reboot定義在./include/linux/syscalls.h,實現在./kernel/sys.c?sys_reboot會調用kernel_restart
最終kernel_restart調用每一個架構特定的machine_restart,即machine_restart執行每個架構特定的函數
Android greenDAO數據庫配置教程
一、環境配置1、在Android Studio中,在.src/main目錄下新建一個java-gen文件夾,和java文件夾同級。用於存放greenDAO生成的DaoMa
笑談Android圖表------MPAndroidCharts
MPAndroidChart是一款基於Android的開源圖表庫,MPAndroidChart不僅可以在Android設備上繪制各種統計圖表,而且可以對圖表進行拖動和縮放
Android學習筆記四之Activity
1、什麼是ActivityActivity是Android四大組件之一,用於顯示View。Activity是一個應用程序組件,提供一個用戶交互的接口,其本身是沒有界面的,
android小技巧:在activity中實現與綁定的fragment的回調
看到標題你可能會想是一個多麼高大上的技巧呢?其實很一般就是自定義回調函數. 首先我們知道activity之間的數據傳遞有幾種方式: 一是startActivityForR