转自:http://blog.chinaunix.net/uid-20729605-id-3779071.html


对于Android的的手机或者平板长期使用,感觉会出现慢的情况,所以偶尔还是需要重启一下,而长按电源键弹出的菜单又没有重启选项,所以特在此记录自己添加这个功能的过程。

首先关机的那个弹出菜单是在frameworks/base/policy/src/com/android/internal/policy/impl/GlobalActions.java这个文件中创建的:


  1. /**
  2. * Create the global actions dialog.
  3. * @return A new dialog.
  4. */
  5. privateGlobalActionsDialogcreateDialog(){
  6. // Simple toggle style if there's no vibrator, otherwise use a tri-state
  7. if(!mHasVibrator){
  8. mSilentModeAction=newSilentModeToggleAction();
  9. }else{
  10. mSilentModeAction=newSilentModeTriStateAction(mContext,mAudioManager,mHandler);
  11. }
  12. mAirplaneModeOn=newToggleAction(
  13. R.drawable.ic_lock_airplane_mode,
  14. R.drawable.ic_lock_airplane_mode_off,
  15. R.string.global_actions_toggle_airplane_mode,
  16. R.string.global_actions_airplane_mode_on_status,
  17. R.string.global_actions_airplane_mode_off_status){

  18. voidonToggle(booleanon){
  19. if(mHasTelephony&&Boolean.parseBoolean(
  20. SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))){
  21. mIsWaitingForEcmExit=true;
  22. // Launch ECM exit dialog
  23. Intent ecmDialogIntent=
  24. newIntent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS,null);
  25. ecmDialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  26. mContext.startActivity(ecmDialogIntent);
  27. }else{
  28. changeAirplaneModeSystemSetting(on);
  29. }
  30. }

  31. @Override
  32. protectedvoidchangeStateFromPress(booleanbuttonOn){
  33. if(!mHasTelephony)return;

  34. // In ECM mode airplane state cannot be changed
  35. if(!(Boolean.parseBoolean(
  36. SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)))){
  37. mState=buttonOn?State.TurningOn:State.TurningOff;
  38. mAirplaneState=mState;
  39. }
  40. }

  41. publicbooleanshowDuringKeyguard(){
  42. returntrue;
  43. }

  44. publicbooleanshowBeforeProvisioning(){
  45. returnfalse;
  46. }
  47. };
  48. onAirplaneModeChanged();

  49. mItems=newArrayList<Action>();

  50. // first: power off
  51. mItems.add(
  52. newSinglePressAction(
  53. com.android.internal.R.drawable.ic_lock_power_off,
  54. R.string.global_action_power_off){

  55. publicvoidonPress(){
  56. // shutdown by making sure radio and power are handled accordingly.
  57. mWindowManagerFuncs.shutdown(true);
  58. }

  59. publicbooleanonLongPress(){
  60. mWindowManagerFuncs.rebootSafeMode(true);
  61. returntrue;
  62. }

  63. publicbooleanshowDuringKeyguard(){
  64. returntrue;
  65. }

  66. publicbooleanshowBeforeProvisioning(){
  67. returntrue;
  68. }
  69. });
我们可以看到mItems.add函数是添加一个选项,该菜单的第一个选项就是关机选项,我们可以在此之后添加重启选项,代码如下:

  1. mItems.add(
  2. newSinglePressAction(
  3. com.android.internal.R.drawable.ic_lock_power_off,
  4. R.string.global_action_reboot){

  5. publicvoidonPress(){
  6. // reboot
  7. mWindowManagerFuncs.reboot();
  8. }

  9. publicbooleanshowDuringKeyguard(){
  10. returntrue;
  11. }

  12. publicbooleanshowBeforeProvisioning(){
  13. returntrue;
  14. }
  15. });
上面的代码中使用了mWindowManagerFuncs.reboot函数和R.string.global_action_reboot资源,因此我们需要该资源并实现reboot函数。
首先在frameworks/base/core/java/android/view/WindowManagerPolicy.java中添加reboot接口:

  1. /**
  2. * Interface for calling back in to the window manager that is private
  3. * between it and the policy.
  4. */
  5. publicinterfaceWindowManagerFuncs{

  6. ...

  7. /**
  8. * Switch the keyboard layout for the given device.
  9. * Direction should be +1 or -1 to go to the next or previous keyboard layout.
  10. */
  11. publicvoidswitchKeyboardLayout(intdeviceId,intdirection);

  12. publicvoidshutdown();
  13. publicvoidreboot();
  14. publicvoidrebootSafeMode();
  15. }
然后在frameworks/base/services/java/com/android/server/wm/WindowManagerService.java中实现该接口:

  1. // Called by window manager policy. Not exposed externally.
  2. @Override
  3. publicvoidshutdown(){
  4. ShutdownThread.shutdown(mContext,true);
  5. }

  6. // Called by window manager policy. Not exposed externally.
  7. @Override
  8. publicvoidreboot(){
  9. ShutdownThread.reboot(mContext,null,true);
  10. }

  11. // Called by window manager policy. Not exposed externally.
  12. @Override
  13. publicvoidrebootSafeMode(){
  14. ShutdownThread.rebootSafeMode(mContext,true);
  15. }
接下来,为了在按下重启选项之后,能出现”重启“之类的提示,还需要修改frameworks/base/services/java/com/android/server/pm/ShutdownThread.java中的shutdownInner函数和beginShutdownSequence函数:

  1. staticvoidshutdownInner(finalContextcontext,booleanconfirm){
  2. // ensure that only one thread is trying to power down.
  3. // any additional calls are just returned
  4. synchronized(sIsStartedGuard){
  5. if(sIsStarted){
  6. Log.d(TAG,"Request to shutdown already running, returning.");
  7. return;
  8. }
  9. }

  10. finalintlongPressBehavior=context.getResources().getInteger(
  11. com.android.internal.R.integer.config_longPressOnPowerBehavior);
  12. finalintresourceId=mRebootSafeMode
  13. ?com.android.internal.R.string.reboot_safemode_confirm
  14. :(longPressBehavior==2
  15. ?com.android.internal.R.string.shutdown_confirm_question
  16. :(mReboot?com.android.internal.R.string.reboot_confirm:
  17. com.android.internal.R.string.shutdown_confirm));

  18. Log.d(TAG,"Notifying thread to start shutdown longPressBehavior="+longPressBehavior);

  19. if(confirm){
  20. finalCloseDialogReceiver closer=newCloseDialogReceiver(context);
  21. finalAlertDialogdialog=newAlertDialog.Builder(context)
  22. .setTitle(mRebootSafeMode
  23. ?com.android.internal.R.string.reboot_safemode_title
  24. :(mReboot?com.android.internal.R.string.reboot:
  25. com.android.internal.R.string.power_off))
  26. .setMessage(resourceId)
  27. .setPositiveButton(com.android.internal.R.string.yes,newDialogInterface.OnClickListener(){
  28. publicvoidonClick(DialogInterfacedialog,intwhich){
  29. beginShutdownSequence(context);
  30. }
  31. })
  32. .setNegativeButton(com.android.internal.R.string.no,null)
  33. .create();
  34. closer.dialog=dialog;
  35. dialog.setOnDismissListener(closer);
  36. dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
  37. dialog.show();
  38. }else{
  39. beginShutdownSequence(context);
  40. }
  41. }

  42. privatestaticvoidbeginShutdownSequence(Contextcontext){
  43. synchronized(sIsStartedGuard){
  44. if(sIsStarted){
  45. Log.d(TAG,"Shutdown sequence already running, returning.");
  46. return;
  47. }
  48. sIsStarted=true;
  49. }

  50. // throw up an indeterminate system dialog to indicate radio is
  51. // shutting down.
  52. ProgressDialog pd=newProgressDialog(context);
  53. pd.setTitle(context.getText(com.android.internal.R.string.power_off));
  54. pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
  55. pd.setIndeterminate(true);
  56. pd.setCancelable(false);
  57. pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);

  58. pd.show();

  59. sInstance.mContext=context;
  60. sInstance.mPowerManager=(PowerManager)context.getSystemService(Context.POWER_SERVICE);

  61. // make sure we never fall asleep again
  62. sInstance.mCpuWakeLock=null;
  63. try{
  64. sInstance.mCpuWakeLock=sInstance.mPowerManager.newWakeLock(
  65. PowerManager.PARTIAL_WAKE_LOCK,TAG+"-cpu");
  66. sInstance.mCpuWakeLock.setReferenceCounted(false);
  67. sInstance.mCpuWakeLock.acquire();
  68. }catch(SecurityExceptione){
  69. Log.w(TAG,"No permission to acquire wake lock",e);
  70. sInstance.mCpuWakeLock=null;
  71. }

  72. // also make sure the screen stays on for better user experience
  73. sInstance.mScreenWakeLock=null;
  74. if(sInstance.mPowerManager.isScreenOn()){
  75. try{
  76. sInstance.mScreenWakeLock=sInstance.mPowerManager.newWakeLock(
  77. PowerManager.FULL_WAKE_LOCK,TAG+"-screen");
  78. sInstance.mScreenWakeLock.setReferenceCounted(false);
  79. sInstance.mScreenWakeLock.acquire();
  80. }catch(SecurityExceptione){
  81. Log.w(TAG,"No permission to acquire wake lock",e);
  82. sInstance.mScreenWakeLock=null;
  83. }
  84. }

  85. // start the thread that initiates shutdown
  86. sInstance.mHandler=newHandler(){
  87. };
  88. sInstance.start();
  89. }
至此关于代码部分的改动全部完成,接下来就需要添加使用到的资源了,就是前面用到的字符串。首先需要在frameworks/base/core/res/res/values/strings.xml中添加一下字符串:

  1. <string name="reboot">Reboot</string>
  2. <string name="reboot_progress">Reboot\u2026</string>
  3. <string name="reboot_confirm"product="tablet">Your tablet will reboot.</string>
  4. <string name="reboot_confirm"product="default">Your phone will reboot.</string>
  5. <!-- label for item that reboot in phone options dialog -->
  6. <string name="global_action_reboot">Reboot</string>
而后需要在frameworks/base/core/res/res/values/public.xml中声明这些资源,否则编译的时候会出现找不到该资源的错误。

  1. <java-symbol type="string"name="reboot"/>
  2. <java-symbol type="string"name="reboot_confirm"/>
  3. <java-symbol type="string"name="reboot_progress"/>
  4. <java-symbol type="string"name="global_action_reboot"/>
至此,全部修改完成,编译烧写即可。

更多相关文章

  1. android 资源文件命名规则 drawable mipmap一样的
  2. Android Button控件 的简单使用(button监听和onClick触发函数使用
  3. Android中String资源文件的String.format方法(java)
  4. Android http超时选项的测试
  5. Android中的Menu功能菜单-OptionsMenu[选项菜单]
  6. Android中资源管理机制详细分析
  7. Android 总结:进阶之路(资源与方法)

随机推荐

  1. Android客户端向服务器端发送数据的流程(
  2. Android动态加载学习
  3. Android studio 不能升级问题
  4. 快速理解android View的测量onMeasure()
  5. Android面试整理(2016)
  6. android中LayoutInflater的使用
  7. android sqlite的增删改查
  8. android的UI系统分析
  9. ArcGIS Runtime for Android 使用异步GP
  10. Android横竖屏切换的解决方法