android5.1添加android長按power鍵重啓功能

當用戶長按power鍵的時候,系統會在PhoneWindowManager中調用html

mGlobalActions.showDialog,來顯示關機、飛行、重啓等界面選項。java

而咱們須要在GlobalActions.Java中建立一個重啓的選項。下面咱們從GlobalActions中的createDialog節選一段代碼:android

[java] view plain copygit

  1. mItems = new ArrayList<Action>();  
  2. String[] defaultActions = mContext.getResources().getStringArray(  
  3.         com.android.internal.R.array.config_globalActionsList);//讀取配置文件中config_globalActionsList內容,下面詳細介紹  
  4.   
  5. ArraySet<String> addedKeys = new ArraySet<String>();  
  6. for (int i = 0; i < defaultActions.length; i++) {  
  7.     String actionKey = defaultActions[i];  
  8.     if (addedKeys.contains(actionKey)) {  
  9.         // If we already have added this, don't add it again.  
  10.         continue;  
  11.     }  
  12.     if (GLOBAL_ACTION_KEY_POWER.equals(actionKey)) {  
  13.         mItems.add(new PowerAction());  
  14.     } else if (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) {  
  15.         mItems.add(mAirplaneModeOn);  
  16.     else if (GLOBAL_ACTION_KEY_REBOOT.equals(actionKey)) {//咱們本身添加了一個重啓功能,在config文件中找到reboot這一項就添加這個reboot  
  17.         mItems.add(new RebootAction());  
  18.     } else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)) {  
  19.         if (Settings.Global.getInt(mContext.getContentResolver(),  
  20.                 Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserOwner()) {  
  21.             mItems.add(getBugReportAction());  
  22.         }  
  23.     } else if (GLOBAL_ACTION_KEY_SILENT.equals(actionKey)) {  
  24.         if (mShowSilentToggle) {  
  25.             mItems.add(mSilentModeAction);  
  26.         }  
  27.     } else if (GLOBAL_ACTION_KEY_USERS.equals(actionKey)) {  
  28.         if (SystemProperties.getBoolean("fw.power_user_switcher", false)) {  
  29.             addUsersToMenu(mItems);  
  30.         }  
  31.     } else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {  
  32.         mItems.add(getSettingsAction());  
  33.     } else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey)) {  
  34.         mItems.add(getLockdownAction());  
  35.     } else {  
  36.         Log.e(TAG, "Invalid global action key " + actionKey);  
  37.     }  
  38.     // Add here so we don't add more than one.  
  39.     addedKeys.add(actionKey);  
  40. }  

咱們本身還須要新建一個RebootAction,咱們看下代碼:app

[java] view plain copyasync

  1. private final class RebootAction extends SinglePressAction {  
  2.     private RebootAction() {  
  3.         super(com.android.internal.R.drawable.ic_lock_restart,//界面圖片和內容  
  4.                 R.string.global_action_restart);  
  5.     }  
  6.   
  7.     public void onPress() {  
  8.         mWindowManagerFuncs.reboot(true);//長按重啓  
  9.     }  
  10.   
  11.     public boolean showDuringKeyguard() {  
  12.         return true;  
  13.     }  
  14.   
  15.     public boolean showBeforeProvisioning() {  
  16.         return true;  
  17.     }  
  18. }  

還有須要在資源文件中添加一些內容:ide

須要在core/res/res/values-zh-rCN/strings.xml中添加以下:函數

[html] view plain copyui

  1. <string name="global_action_restart">"從新啓動"</string>  
  2. <string name="restart_confirm_question">"您要從新啓動手機嗎?"</string>  
  3. <string name="restart_confirm">"您的手機會從新啓動。"</string>  
  4. <string name="restart">"從新啓動"</string>  

在core/res/res/values/strings.xml中this

[html] view plain copy

  1. <string name="global_action_restart">Restart</string>  
  2. <string name="restart_confirm_question">"Would you like to restart?"</string>  
  3. <string name="restart_confirm">"Your phone will restart."</string>  
  4. <string name="restart">"Restart"</string>  

在core/res/res/values/symbols.xml中

[html] view plain copy

  1. <java-symbol type="string" name="global_action_restart"/>  
  2. <java-symbol type="string" name="restart_confirm_question"/>  
  3. <java-symbol type="string" name="restart_confirm"/>  
  4. <java-symbol type="string" name="restart"/>  
  5. <java-symbol type="drawable" name="ic_lock_restart" />  

還須要添加一個圖標的圖片

[html] view plain copy

  1. diff --git a/core/res/res/drawable-hdpi/ic_lock_restart.png b/core/res/res/drawable-hdpi/ic_lock_restart.png  
  2.   
  3. diff --git a/core/res/res/drawable-ldpi/ic_lock_restart.png b/core/res/res/drawable-ldpi/ic_lock_restart.png  
  4.   
  5. diff --git a/core/res/res/drawable-mdpi/ic_lock_restart.png b/core/res/res/drawable-mdpi/ic_lock_restart.png  
  6.   
  7. diff --git a/core/res/res/drawable-xhdpi/ic_lock_restart.png b/core/res/res/drawable-xhdpi/ic_lock_restart.png  

最後咱們須要在core/res/res/values/config.xml中增長几個選項來打開重啓等功能

[html] view plain copy

  1. <string-array translatable="false" name="config_globalActionsList">  
  2.     <item>power</item>  
  3.     <item>bugreport</item>  
  4.     <item>users</item>  
  5.     <item>airplane</item>//飛行模式  
  6.     <item>reboot</item>//新增重啓功能  
  7. </string-array>  

而上面再GlobalActions中添加的reboot,須要在WindowManagerPolicy新增接口

[java] view plain copy

  1. public void shutdown(boolean confirm);  
  2. public void rebootSafeMode(boolean confirm);  
  3. public void reboot(boolean confirm);//新增的接口  

而且最總在WindowManagerService中實現:

[java] view plain copy

  1. @Override  
  2. public void reboot(boolean confirm) {  
  3.     Log.d(TAG,"reboot confirm:" + confirm);  
  4.     ShutdownThread.reboot(mContext, null, confirm);  
  5. }  

最後調用ShutdownThread的reboot函數。

[java] view plain copy

  1. public static void reboot(final Context context, String reason, boolean confirm) {  
  2.     mReboot = true;//這個參數最後決定是重啓仍是關機  
  3.     mRebootSafeMode = false;  
  4.     mRebootReason = reason;  
  5.     shutdownInner(context, confirm);  
  6. }  

下面主要看下ShutdownThread的shutdownInner這個函數,主要是建立彈出框,以及開啓線程執行關機或重啓。

[java] view plain copy

  1. static void shutdownInner(final Context context, boolean confirm) {  
  2.     synchronized (sIsStartedGuard) {  
  3.         if (sIsStarted) {  
  4.             Log.d(TAG, "Request to shutdown already running, returning.");  
  5.             return;  
  6.         }  
  7.     }  
  8.   
  9.     final int longPressBehavior = context.getResources().getInteger(  
  10.                     com.android.internal.R.integer.config_longPressOnPowerBehavior);  
  11.     final int resourceId = mRebootSafeMode  
  12.             ? com.android.internal.R.string.reboot_safemode_confirm  
  13.             : (longPressBehavior == 2  
  14.                     ? com.android.internal.R.string.shutdown_confirm_question  
  15.                     : com.android.internal.R.string.shutdown_confirm);  
  16.   
  17.     Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior);  
  18.   
  19.     final int resourceIdMsg;  
  20.     final int resourceIdTitle;  
  21.     if(mReboot){//這段是咱們添加的,根據不一樣選項建立不一樣的界面  
  22.         resourceIdTitle = com.android.internal.R.string.restart;  
  23.         resourceIdMsg = longPressBehavior == 2  
  24.                  ? com.android.internal.R.string.restart_confirm_question  
  25.                  : com.android.internal.R.string.restart_confirm;  
  26.     }  
  27.     else if(mRebootSafeMode){  
  28.         resourceIdTitle = com.android.internal.R.string.reboot_safemode_title;  
  29.         resourceIdMsg = com.android.internal.R.string.reboot_safemode_confirm;  
  30.     }  
  31.     else {  
  32.         resourceIdTitle = com.android.internal.R.string.power_off;  
  33.         resourceIdMsg = longPressBehavior == 2  
  34.                 ? com.android.internal.R.string.shutdown_confirm_question  
  35.                 : com.android.internal.R.string.shutdown_confirm;  
  36.     }  
  37.   
  38.     if (confirm) {//這個參數決定是否須要彈出對話框  
  39.         final CloseDialogReceiver closer = new CloseDialogReceiver(context);  
  40.         if (sConfirmDialog != null) {  
  41.             sConfirmDialog.dismiss();  
  42.         }  
  43.         sConfirmDialog = new AlertDialog.Builder(context)//這邊彈出一個對話框也將其進行了修改,主要是顯示  
  44.                 .setTitle(resourceIdTitle)  
  45.                 .setMessage(resourceIdMsg)  
  46.                 .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {  
  47.                     public void onClick(DialogInterface dialog, int which) {  
  48.                         beginShutdownSequence(context);//當確認了調用beginShutdownSequence函數,執行關機或重啓。  
  49.                     }  
  50.                 })  
  51.                 .setNegativeButton(com.android.internal.R.string.no,  new DialogInterface.OnClickListener() {  
  52.                     public void onClick(DialogInterface dialog, int which) {  
  53.                         //set the mReboot to default value for next time.  
  54.                         mReboot = false;//不確認就直接結束了,不調用beginShutdownSequence  
  55.                     }  
  56.                  })  
  57.                 .create();  
  58.         closer.dialog = sConfirmDialog;  
  59.         sConfirmDialog.setOnDismissListener(closer);  
  60.         sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);  
  61.         sConfirmDialog.show();  
  62.     } else {//當不須要確認框彈出,直接調用beginShutdownSequence函數,執行關機或重啓。  
  63.         beginShutdownSequence(context);  
  64.     }  
  65. }  

beginShutdownSequence最後會調用sInstance.start();開啓線程

所以會到run接口,而run接口最後又會調用rebootOrShutdown,根據reboot是重啓仍是關機。

  1. public static void rebootOrShutdown(boolean reboot, String reason) {  
  2.     if (reboot) {  
  3.         Log.i(TAG, "Rebooting, reason: " + reason);  
  4.         try {  
  5.             PowerManagerService.lowLevelReboot(reason);//重啓  
  6.         } catch (Exception e) {  
  7.             Log.e(TAG, "Reboot failed, will attempt shutdown instead", e);  
  8.         }  
  9.     } else if (SHUTDOWN_VIBRATE_MS > 0) {  
  10.         // vibrate before shutting down  
  11.         Vibrator vibrator = new SystemVibrator();  
  12.         try {  
  13.             vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES);  
  14.         } catch (Exception e) {  
  15.             // Failure to vibrate shouldn't interrupt shutdown.  Just log it.  
  16.             Log.w(TAG, "Failed to vibrate during shutdown.", e);  
  17.         }  
  18.   
  19.         // vibrator is asynchronous so we need to wait to avoid shutting down too soon.  
  20.         try {  
  21.             Thread.sleep(SHUTDOWN_VIBRATE_MS);  
  22.         } catch (InterruptedException unused) {  
  23.         }  
  24.     }  
  25.   
  26.     // Shutdown power  
  27.     Log.i(TAG, "Performing low-level shutdown...");  
  28.     PowerManagerService.lowLevelShutdown();//關機  
  29. }  

這樣整個添加劇啓功能就結束了。

相關文章
相關標籤/搜索