[置頂]android源碼定製之初探--定製android關機界面

 

LouisWang

轉載請註明出處:http://blog.csdn.net/louiswangbing/article/details/6688240

上一篇文章中講到android源碼定製要點,說了個大概的方法和方向,現在,就來實戰一下。

在Android系統中,長按Power鍵默認會彈出對話框讓你選擇“飛行模式”,“靜音”,“關機”等功能。如下圖所示:


但這些功能都對Android-x86和其他終端產品就沒什麼必要了。本文就簡單介紹下如何定製關機界面。

我的目標是長按Power鍵,將會關機,彈出“設備將要關機”選擇對話框。如果可以選擇“是”關機,和“否”返回系統。 

按照android源碼定製要點中提到的,首先你要對整個系統有全面的瞭解,找到彈出原來這個選擇框的代碼,它在這裏:

  1. <pre name="code" class="java">frameworks\policies\base\phone\com\android\internal\policy\impl\PhoneWindowManager.java    


顯示對話框調用的代碼如下:

  1. Runnable mPowerLongPress = new Runnable() {    
  2.     public void run() {    
  3.         mShouldTurnOffOnKeyUp = false;    
  4.         performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);    
  5.         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);    
  6.         showGlobalActionsDialog();    
  7.     }    
  8. };    

調用showGlobalActionsDialog方法之後將會聚到有“飛行模式”、“靜音”、“關機”等選項的對話框。

找到這裏,我們就知道該做什麼了!幹掉它,換成我們想要的關機代碼,就大功告成了!既然這樣,事不宜遲,讓我們趕快到showGloabalActionDialog方法中看看關機的部分在哪裏!

showGlobalActionsDialog的實現部分在這裏:

  1. frameworks\policies\base\phone\com\android\internal\policy\impl\GlobalAction.java  

我們進去看看:

  1. public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) {  
  2.     mKeyguardShowing = keyguardShowing;  
  3.     mDeviceProvisioned = isDeviceProvisioned;  
  4.     if (mDialog == null) {  
  5.         mStatusBar = (StatusBarManager)mContext.getSystemService(Context.STATUS_BAR_SERVICE);  
  6.         mDialog = createDialog();  
  7.     }  
  8.     prepareDialog();  
  9.   
  10.     mStatusBar.disable(StatusBarManager.DISABLE_EXPAND);  
  11.     mDialog.show();  
  12. }  

我們可以很清楚的看到,這裏新建了一個mDialog,然後prepare接着就show了它,那麼,這個mDialog就是關鍵了,看看它是怎麼被createDialog創建出來的吧,仍然在這個文件中:

  1. /** 
  2.  * Create the global actions dialog. 
  3.  * @return A new dialog. 
  4.  */  
  5. private AlertDialog createDialog() {  
  6.     mSilentModeToggle = new ToggleAction(  
  7.             R.drawable.ic_lock_silent_mode,  
  8.             R.drawable.ic_lock_silent_mode_off,  
  9.             R.string.global_action_toggle_silent_mode,  
  10.             R.string.global_action_silent_mode_on_status,  
  11.             R.string.global_action_silent_mode_off_status) {  
  12.   
  13.         void willCreate() {  
  14.             // XXX: FIXME: switch to ic_lock_vibrate_mode when available   
  15.             mEnabledIconResId = (Settings.System.getInt(mContext.getContentResolver(),  
  16.                     Settings.System.VIBRATE_IN_SILENT, 1) == 1)  
  17.                 ? R.drawable.ic_lock_silent_mode_vibrate  
  18.                 : R.drawable.ic_lock_silent_mode;  
  19.         }  
  20.   
  21.         void onToggle(boolean on) {  
  22.             if (on) {  
  23.                 mAudioManager.setRingerMode((Settings.System.getInt(mContext.getContentResolver(),  
  24.                     Settings.System.VIBRATE_IN_SILENT, 1) == 1)  
  25.                     ? AudioManager.RINGER_MODE_VIBRATE  
  26.                     : AudioManager.RINGER_MODE_SILENT);  
  27.             } else {  
  28.                 mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);  
  29.             }  
  30.         }  
  31.   
  32.         public boolean showDuringKeyguard() {  
  33.             return true;  
  34.         }  
  35.   
  36.         public boolean showBeforeProvisioning() {  
  37.             return false;  
  38.         }  
  39.     };  
  40.   
  41.     mAirplaneModeOn = new ToggleAction(  
  42.             R.drawable.ic_lock_airplane_mode,  
  43.             R.drawable.ic_lock_airplane_mode_off,  
  44.             R.string.global_actions_toggle_airplane_mode,  
  45.             R.string.global_actions_airplane_mode_on_status,  
  46.             R.string.global_actions_airplane_mode_off_status) {  
  47.   
  48.         void onToggle(boolean on) {  
  49.             if (Boolean.parseBoolean(  
  50.                     SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {  
  51.                 mIsWaitingForEcmExit = true;  
  52.                 // Launch ECM exit dialog   
  53.                 Intent ecmDialogIntent =  
  54.                         new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null);  
  55.                 ecmDialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  56.                 mContext.startActivity(ecmDialogIntent);  
  57.             } else {  
  58.                 changeAirplaneModeSystemSetting(on);  
  59.             }  
  60.         }  
  61.   
  62.         @Override  
  63.         protected void changeStateFromPress(boolean buttonOn) {  
  64.             // In ECM mode airplane state cannot be changed   
  65.             if (!(Boolean.parseBoolean(  
  66.                     SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)))) {  
  67.                 mState = buttonOn ? State.TurningOn : State.TurningOff;  
  68.                 mAirplaneState = mState;  
  69.             }  
  70.         }  
  71.   
  72.         public boolean showDuringKeyguard() {  
  73.             return true;  
  74.         }  
  75.   
  76.         public boolean showBeforeProvisioning() {  
  77.             return false;  
  78.         }  
  79.     };  
  80.   
  81.     <span style="color:#ff0000;">mItems = Lists.newArrayList(  
  82.             // silent mode   
  83.             mSilentModeToggle,  
  84.             // next: airplane mode   
  85.             mAirplaneModeOn,  
  86.             // last: power off   
  87.             new SinglePressAction(  
  88.                     com.android.internal.R.drawable.ic_lock_power_off,  
  89.                     R.string.global_action_power_off) {  
  90.   
  91.                 </span><span style="color:#3333ff;"><u>public void onPress() {  
  92.                     // shutdown by making sure radio and power are handled accordingly.   
  93.                     ShutdownThread.shutdown(mContext, true);  
  94.                 }</u></span><span style="color:#ff0000;">  
  95.   
  96.                 public boolean showDuringKeyguard() {  
  97.                     return true;  
  98.                 }  
  99.   
  100.                 public boolean showBeforeProvisioning() {  
  101.                     return true;  
  102.                 }</span>  
  103.             });  
  104.   
  105.     mAdapter = new MyAdapter();  
  106.   
  107.     final AlertDialog.Builder ab = new AlertDialog.Builder(mContext);  
  108.   
  109.     ab.setAdapter(mAdapter, this)  
  110.             .setInverseBackgroundForced(true)  
  111.             .setTitle(R.string.global_actions);  
  112.   
  113.     final AlertDialog dialog = ab.create();  
  114.     dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);  
  115.     if (!mContext.getResources().getBoolean(  
  116.             com.android.internal.R.bool.config_sf_slowBlur)) {  
  117.         dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,  
  118.                 WindowManager.LayoutParams.FLAG_BLUR_BEHIND);  
  119.     }  
  120.   
  121.     dialog.setOnDismissListener(this);  
  122.   
  123.     return dialog;  
  124. }  

看看我們發現了什麼!!藍色的部分就是關機調用的函數了!!shutdown方法的第二個參數標識是否彈出詢問對話框。你可以選擇需要(true)或者不需要(false)。這裏我保守一點,還是選個true吧,萬一不小心按到關機鍵呢,呵呵。。。

也就是說,只要我們用

  1. <span style="color:#3333ff;">ShutdownThread.shutdown(mContext, true);</span>  

替換掉前面的

  1. showGlobalActionsDialog();    

就可以大功告成了!還等什麼!我們修改

  1. frameworks\policies\base\phone\com\android\internal\policy\impl\PhoneWindowManager.java    

的源代碼如下:

  1. Runnable mPowerLongPress = new Runnable() {  
  2.     public void run() {  
  3.         mShouldTurnOffOnKeyUp = false;  
  4.         performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);  
  5.         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);  
  6.         //showGlobalActionsDialog();   
  7.         ShutdownThread.shutdown(mContext, true);   
  8.     }  
  9. };  

好了,大功告成了!!

是不是就這樣完了呢?發現編譯不過。。。

細節很重要!!

原來ShutdownThread.shutdown(mContext, true)的引用包沒加進來!!幸好有gcc。。。

  1. import com.android.internal.app.ShutdownThread;  

將上面這個包加到
  1. frameworks\policies\base\phone\com\android\internal\policy\impl\PhoneWindowManager.java    

中,再次編譯,通過,YES!

看看我們的戰果吧:


是不是感覺到源碼定製的快感和成就感了呢?

這僅僅只是個開始,好戲還在後頭呢!!哈哈


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章