按計劃每周更新一篇技術博文,第二篇:《為Android系統定製重啟功能》
一、Android系統重啟的實現方式
1、廣播方式之前的博文介紹過這種方式《使用廣播實現的Android關機及重啟》,注意應用要在源碼中編譯,並且應用需要系統許可權。
2、通過init.rc啟動系統服務來運行sh檔案
a.重啟shell檔案(system_reboot.sh),放在system/etc/目錄下
#!/system/bin/sh reboot
b.init.rc中加入一個Service的定義
service system_reboot /system/etc/system_reboot.sh oneshot disabled
c.啟動系統服務
SystemProperties.set("ctl.start", "system_reboot");
3、直接代碼中執行命令列需要取得root許可權Process proc = Runtime.getRuntime().exec(cmd);
以上三種方法可以實現重啟,但現在需要實現長按關機鍵提示對話方塊中有重啟選項,這就設計修改系統源碼,感覺修改源碼,是個很難的工作,其實找到關機提示框的代碼位置,一切都變得很簡單。
二、修改源碼定製重啟功能1、跟蹤長按Power鍵相關代碼 首先要瞭解長按電源鍵彈出對話方塊的相關源碼位置,通過跟蹤找到PhoneWindowManager.java中有截斷長按電源鍵的方法,繼續跟蹤代碼找到Runnable mPowerLongPress =
new Runnable(),在該runnable裡邊調用showGlobalActionsDialog()方法便是顯示長按power鍵彈出的關機提示對話方塊,如果你的機器是原生態的,預設提示“飛航模式”,“靜音”和“關機”選項。 showGlobalActionsDialog建立關機對話方塊的代碼在GlobalActions.java裡邊,主要代碼如下:
private AlertDialog createDialog() {……mItems = new ArrayList<Action>(); // first: power off mItems.add( new SinglePressAction( com.android.internal.R.drawable.ic_lock_power_off, R.string.global_action_power_off) { public void onPress() { // shutdown by making sure radio and power are handled accordingly. ShutdownThread.shutdown(mContext, true); } public boolean showDuringKeyguard() { return true; } public boolean showBeforeProvisioning() { return true; } }); // next: airplane mode mItems.add(mAirplaneModeOn); // last: silent mode if (SHOW_SILENT_TOGGLE) { mItems.add(mSilentModeAction); }……}
2、重啟方法 跟蹤源碼到此處,需要加入重啟部分的源碼也是往AlertDialog 添加多一項,顯示部分的代碼直接造這power
off即可,需要加入重啟邏輯的代碼直接修改回調方法onPress裡邊(上邊代碼粗體部分),一開始,我嘗試了前文中提示的三種方法中的方法一和方法三均行不通,後來也沒再進一步排查原因,估計許可權問題。 本打算使用方法二再嘗試一下,突然想到為何不去看看關機的邏輯代碼ShutdownThread.shutdown(),開啟ShutdownThread.java,很快就發現源碼裡邊也有reboot的實現方法,如下:
/** * Request a clean shutdown, waiting for subsystems to clean up their * state etc. Must be called from a Looper thread in which its UI * is shown. * * @param context Context used to display the shutdown progress dialog. * @param reason code to pass to the kernel (e.g. "recovery"), or null. * @param confirm true if user confirmation is needed before shutting down. */ public static void reboot(final Context context, String reason, boolean confirm){ …… }
該方法的使用直接看注釋知道,reboot方法的後兩個參數解釋如下: reason 如果值為是null,正常重啟;如果是recovery,系統重啟進入recovery
mode confirm
true顯示關機提示框,需要使用者【確認】;false不顯示提示框,直接關機 3、代碼修改a.在關機提示框中加入重啟選項 弄清楚關機相關的源碼,直接在GlobalActions.java的createDialog方法中加入如下代碼即可:
... // next: reboot global_action_reboot mItems.add( new SinglePressAction( com.android.internal.R.drawable.ic_lock_power_off, R.string.global_action_reboot) { public void onPress() { // reboot ShutdownThread.reboot(mContext,null,false); } public boolean showDuringKeyguard() { return true; } public boolean showBeforeProvisioning() { return true; } });...
b.修改重啟提示框,以區分關機提示框 因為提示框預設是“關機”,在ShutdownThread.java的beginShutdownSequence(context)方法中代碼修改如下:
/*///修改前:…… pd.setTitle(context.getText(com.android.internal.R.string.power_off)); pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));……/*///修改後:……if(mReboot){ // reboot progress pd.setTitle(context.getText(com.android.internal.R.string.global_action_reboot)); pd.setMessage(context.getText(com.android.internal.R.string.reboot_progress)); }else{ // shutdown progress pd.setTitle(context.getText(com.android.internal.R.string.power_off)); pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress)); }……//*/
重啟功能實現了,但是不能到此結束,定製Android系統的重啟功能,添加選項和修改重啟提示框時加入了“重啟”和“正在重啟”的字串,所以會涉及到在系統資源檔中添加新的字串,源碼中資源檔涉及到的多國語言直接忽略,我只在values/strings.xml和values-zh-rCN/strings.xml兩個檔案中加入對應的字串: <string name="global_action_reboot">重啟</string> <string name="reboot_progress">"正在重啟..."</string>
c.最後編譯因為修改涉及到系統資源檔又涉及到policy.jar包,經過多次嘗試,正確的編譯順序如下:步驟1.編譯frameworks/base/res,在out/target/product/X裝置名稱X/system/framework/目錄下產生framework-res.apk步驟2.編譯frameworks/base/,在o同樣目錄下產生framework.jar包(不能忽略,不然步驟3編譯報錯)步驟3.編譯frameworks/base/policy,在同樣目錄下產生policy.jar包
附錄:本例源碼以Android 4.0.4為準(2.3一樣),關機相關的源碼路徑:ics/frameworks/base/policy/src/com/android/internal/policy/impl/目錄下:PhoneWindowManager.javaGlobalActions.java
ics/frameworks/base/core/java/com/android/internal/app/目錄下:ShutdownThread.java
PS:4.1.1 關機相關方法位置有些變化源碼已經把關機的介面整合到:public class
WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs{...}中不過可以直接使用:import com.android.server.pm.ShutdownThread;
ShutdownThread.shutdown(mContext, true);
ShutdownThread.rebootSafeMode(mContext, true);
檔案路徑:Android4.1.1/jb/frameworks/base/services/java/com/android/server/pm/
ShutdownThread.java
Android4.1.1/jb/frameworks/base/services/java/com/android/server/wm
WindowManagerService.java
...
參考引用:1、Android應用程式獲得root許可權