android源碼探索之定制android關(guān)機(jī)界面的方法
本文實(shí)例講述了android源碼探索之定制android關(guān)機(jī)界面的方法。分享給大家供大家參考。具體如下:
在Android系統(tǒng)中,長(zhǎng)按Power鍵默認(rèn)會(huì)彈出對(duì)話框讓你選擇“飛行模式”,“靜音”,“關(guān)機(jī)”等功能。如下圖所示:

但這些功能都對(duì)Android-x86和其他終端產(chǎn)品就沒(méi)什么必要了。本文就簡(jiǎn)單介紹下如何定制關(guān)機(jī)界面。
我的目標(biāo)是長(zhǎng)按Power鍵,將會(huì)關(guān)機(jī),彈出“設(shè)備將要關(guān)機(jī)”選擇對(duì)話框。如果可以選擇“是”關(guān)機(jī),和“否”返回系統(tǒng)。
按照android源碼定制要點(diǎn)中提到的,首先你要對(duì)整個(gè)系統(tǒng)有全面的了解,找到彈出原來(lái)這個(gè)選擇框的代碼,它在這里:
<pre name="code" class="java">frameworks\policies\base\phone\com\android\internal\policy\impl\PhoneWindowManager.java
顯示對(duì)話框調(diào)用的代碼如下:
Runnable mPowerLongPress = new Runnable() {
public void run() {
mShouldTurnOffOnKeyUp = false;
performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
showGlobalActionsDialog();
}
};
調(diào)用showGlobalActionsDialog方法之后將會(huì)聚到有“飛行模式”、“靜音”、“關(guān)機(jī)”等選項(xiàng)的對(duì)話框。
找到這里,我們就知道該做什么了!干掉它,換成我們想要的關(guān)機(jī)代碼,就大功告成了!既然這樣,事不宜遲,讓我們趕快到showGloabalActionDialog方法中看看關(guān)機(jī)的部分在哪里!
showGlobalActionsDialog的實(shí)現(xiàn)部分在這里:
frameworks\policies\base\phone\com\android\internal\policy\impl\GlobalAction.java
public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) {
mKeyguardShowing = keyguardShowing;
mDeviceProvisioned = isDeviceProvisioned;
if (mDialog == null) {
mStatusBar = (StatusBarManager)mContext.getSystemService(Context.STATUS_BAR_SERVICE);
mDialog = createDialog();
}
prepareDialog();
mStatusBar.disable(StatusBarManager.DISABLE_EXPAND);
mDialog.show();
}
我們可以很清楚的看到,這里新建了一個(gè)mDialog,然后prepare接著就show了它,那么,這個(gè)mDialog就是關(guān)鍵了,看看它是怎么被createDialog創(chuàng)建出來(lái)的吧,仍然在這個(gè)文件中:
/**
* Create the global actions dialog.
* @return A new dialog.
*/
private AlertDialog createDialog() {
mSilentModeToggle = new ToggleAction(
R.drawable.ic_lock_silent_mode,
R.drawable.ic_lock_silent_mode_off,
R.string.global_action_toggle_silent_mode,
R.string.global_action_silent_mode_on_status,
R.string.global_action_silent_mode_off_status) {
void willCreate() {
// XXX: FIXME: switch to ic_lock_vibrate_mode when available
mEnabledIconResId = (Settings.System.getInt(mContext.getContentResolver(),
Settings.System.VIBRATE_IN_SILENT, 1) == 1)
? R.drawable.ic_lock_silent_mode_vibrate
: R.drawable.ic_lock_silent_mode;
}
void onToggle(boolean on) {
if (on) {
mAudioManager.setRingerMode((Settings.System.getInt(mContext.getContentResolver(),
Settings.System.VIBRATE_IN_SILENT, 1) == 1)
? AudioManager.RINGER_MODE_VIBRATE
: AudioManager.RINGER_MODE_SILENT);
} else {
mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
}
}
public boolean showDuringKeyguard() {
return true;
}
public boolean showBeforeProvisioning() {
return false;
}
};
mAirplaneModeOn = new ToggleAction(
R.drawable.ic_lock_airplane_mode,
R.drawable.ic_lock_airplane_mode_off,
R.string.global_actions_toggle_airplane_mode,
R.string.global_actions_airplane_mode_on_status,
R.string.global_actions_airplane_mode_off_status) {
void onToggle(boolean on) {
if (Boolean.parseBoolean(
SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
mIsWaitingForEcmExit = true;
// Launch ECM exit dialog
Intent ecmDialogIntent =
new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null);
ecmDialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(ecmDialogIntent);
} else {
changeAirplaneModeSystemSetting(on);
}
}
@Override
protected void changeStateFromPress(boolean buttonOn) {
// In ECM mode airplane state cannot be changed
if (!(Boolean.parseBoolean(
SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)))) {
mState = buttonOn ? State.TurningOn : State.TurningOff;
mAirplaneState = mState;
}
}
public boolean showDuringKeyguard() {
return true;
}
public boolean showBeforeProvisioning() {
return false;
}
};
<span style="color:#ff0000;">mItems = Lists.newArrayList(
// silent mode
mSilentModeToggle,
// next: airplane mode
mAirplaneModeOn,
// last: power off
new SinglePressAction(
com.android.internal.R.drawable.ic_lock_power_off,
R.string.global_action_power_off) {
</span><span style="color:#3333ff;"><u>public void onPress() {
// shutdown by making sure radio and power are handled accordingly.
ShutdownThread.shutdown(mContext, true);
}</u></span><span style="color:#ff0000;">
public boolean showDuringKeyguard() {
return true;
}
public boolean showBeforeProvisioning() {
return true;
}</span>
});
mAdapter = new MyAdapter();
final AlertDialog.Builder ab = new AlertDialog.Builder(mContext);
ab.setAdapter(mAdapter, this)
.setInverseBackgroundForced(true)
.setTitle(R.string.global_actions);
final AlertDialog dialog = ab.create();
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
if (!mContext.getResources().getBoolean(
com.android.internal.R.bool.config_sf_slowBlur)) {
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
}
dialog.setOnDismissListener(this);
return dialog;
}
看看我們發(fā)現(xiàn)了什么!!藍(lán)色的部分就是關(guān)機(jī)調(diào)用的函數(shù)了?。hutdown方法的第二個(gè)參數(shù)標(biāo)識(shí)是否彈出詢問(wèn)對(duì)話框。你可以選擇需要(true)或者不需要(false)。這里我保守一點(diǎn),還是選個(gè)true吧,萬(wàn)一不小心按到關(guān)機(jī)鍵呢,呵呵。。。
也就是說(shuō),只要我們用
替換掉前面的
就可以大功告成了!還等什么!我們修改
frameworks\policies\base\phone\com\android\internal\policy\impl\PhoneWindowManager.java
的源代碼如下:
Runnable mPowerLongPress = new Runnable() {
public void run() {
mShouldTurnOffOnKeyUp = false;
performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
//showGlobalActionsDialog();
ShutdownThread.shutdown(mContext, true);
}
};
好了,大功告成了??!
是不是就這樣完了呢?發(fā)現(xiàn)編譯不過(guò)。。。
細(xì)節(jié)很重要??!
原來(lái)ShutdownThread.shutdown(mContext, true)的引用包沒(méi)加進(jìn)來(lái)??!幸好有g(shù)cc。。。
將上面這個(gè)包加到
frameworks\policies\base\phone\com\android\internal\policy\impl\PhoneWindowManager.java
中,再次編譯,通過(guò),YES!
看看我們的戰(zhàn)果吧:

是不是感覺(jué)到源碼定制的快感和成就感了呢?
這僅僅只是個(gè)開(kāi)始,好戲還在后頭呢?。」?/p>
希望本文所述對(duì)大家的Android程序設(shè)計(jì)有所幫助。
- Android ListView的Item點(diǎn)擊效果的定制
- Android快速開(kāi)發(fā)之定制BaseTemplate
- Android實(shí)現(xiàn)定制返回按鈕動(dòng)畫效果的方法
- Android定制自己的EditText輕松改變底線顏色
- Android 組件樣式定制方法詳解
- Android實(shí)現(xiàn)定制桌面的方法
- Android實(shí)現(xiàn)的狀態(tài)欄定制和修改方法
- Android 如何定制vibrator的各種震動(dòng)模式M 具體方法
- Android定制RadioButton樣式三種實(shí)現(xiàn)方法
- 詳解android系統(tǒng)的定制
相關(guān)文章
Android自定義View實(shí)現(xiàn)水面上漲效果
這篇文章給大家介紹了利用Android自定義View實(shí)現(xiàn)水面上漲效果,對(duì)大家日常開(kāi)發(fā)很有幫助,有需要的朋友們可以參考借鑒。2016-09-09
Android框架Volley使用:ImageRequest請(qǐng)求實(shí)現(xiàn)圖片加載
這篇文章主要介紹了Android框架Volley使用:ImageRequest請(qǐng)求實(shí)現(xiàn)圖片加載的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-05-05
Android實(shí)現(xiàn)創(chuàng)意LoadingView動(dòng)畫效果
這篇文章主要介紹了Android實(shí)現(xiàn)創(chuàng)意LoadingView動(dòng)畫效果的相關(guān)資料,需要的朋友可以參考下2016-02-02
Android 開(kāi)發(fā)使用PopupWindow實(shí)現(xiàn)加載等待界面功能示例
這篇文章主要介紹了Android 開(kāi)發(fā)使用PopupWindow實(shí)現(xiàn)加載等待界面功能,結(jié)合實(shí)例形式分析了Android使用PopupWindow組件實(shí)現(xiàn)加載等待界面功能相關(guān)布局與功能實(shí)現(xiàn)技巧,需要的朋友可以參考下2020-05-05
android實(shí)現(xiàn)點(diǎn)擊圖片全屏展示效果
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)點(diǎn)擊圖片全屏展示效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08
Android 判斷ip地址合法實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 判斷ip地址合法實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2017-06-06
Android9.0上針對(duì)Toast的特殊處理圖文詳解
這篇文章主要給大家介紹了關(guān)于Android9.0上針對(duì)Toast的特殊處理的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Android自定義View實(shí)現(xiàn)圓形環(huán)繞效果
這篇文章主要為大家詳細(xì)介紹了Android自定義View實(shí)現(xiàn)圓形環(huán)繞效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01

