现在的位置: 首页 > 综合 > 正文

android源码定制之初探–定制android关机界面

2013年02月02日 ⁄ 综合 ⁄ 共 7202字 ⁄ 字号 评论关闭

 转载注明出处: http://blog.csdn.net/louiswangbing/article/details/6688240 

在Android系统中,长按Power键默认会弹出对话框让你选择“飞行模式”,“静音”,“关机”等功能。如下图所示:


但这些功能都对Android-x86和其他终端产品就没什么必要了。本文就简单介绍下如何定制关机界面。

我的目标是长按Power键,将会关机,弹出“设备将要关机”选择对话框。如果可以选择“是”关机,和“否”返回系统。 

按照android源码定制要点中提到的,首先你要对整个系统有全面的了解,找到弹出原来这个选择框的代码,它在这里:

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


显示对话框调用的代码如下:

Runnable mPowerLongPress = new Runnable() {    

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

调用showGlobalActionsDialog方法之后将会聚到有“飞行模式”、“静音”、“关机”等选项的对话框。

找到这里,我们就知道该做什么了!干掉它,换成我们想要的关机代码,就大功告成了!既然这样,事不宜迟,让我们赶快到showGloabalActionDialog方法中看看关机的部分在哪里!

showGlobalActionsDialog的实现部分在这里:

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

看看我们发现了什么!!蓝色的部分就是关机调用的函数了!!shutdown方法的第二个参数标识是否弹出询问对话框。你可以选择需要(true)或者不需要(false)。这里我保守一点,还是选个true吧,万一不小心按到关机键呢,呵呵。。。

也就是说,只要我们用view
plain
copy to clipboardprint?

  1. ShutdownThread.shutdown(mContext, true);

替换掉前面的

showGlobalActionsDialog();    

就可以大功告成了!还等什么!我们修改

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

的源代码如下:

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

好了,大功告成了!!

是不是就这样完了呢?发现编译不过。。。

细节很重要!!

原来ShutdownThread.shutdown(mContext, true)的引用包没加进来!!幸好有gcc。。。

import com.android.internal.app.ShutdownThread;  

将上面这个包加到

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

中,再次编译,通过,YES!

看看我们的战果吧:


是不是感觉到源码定制的快感和成就感了呢?

这仅仅只是个开始,好戏还在后头呢!!哈哈

抱歉!评论已关闭.