在Android上长按关机键,会显示关机对话框,如下图所示。
分析一下详细的过程吧。
1 )在PWM中,调用
privatevoidinterceptpowerkeydown (布尔型握手) {
mPowerKeyHandled=handled;
if (! handled ) {
mhandler.post delayed (mpowerlongpress,view configuration.getglobalactionkeytimeout ();
}
进入mPowerLongPress
privatefinalrunnablempowerlongpress=new runnable {
@Override
公共语音运行(}
//Thecontextisn'tread
mlongpressonpowerbehavior0{
mlongpressonpowerbehavior=m context.get resources (
com.Android.internal.r.integer.config _ longpressonpowerbehavior;
}
.
交换机(resolved behavior ) {
case long _ press _ power _ nothing :
布雷克;
case long _ press _ power _ global _ actions :
mPowerKeyHandled=true;
if (! performhapticfeedbacklw(null,hapticfeedbackconstants.long _ press,false ) }
performauditoryfeedbackforaccessibilityifneed (;
}
sendclosesystemwindows (system _ dialog _ reason _ global _ actions;
showGlobalActionsDialog (;
布雷克;
.
}
}
(; 调用showGlobalActionsDialog
voidshowGlobalActionsDialog (
if(mglobalactions==null ) {
mglobalactions=newglobalactions (m context,mWindowManagerFuncs );
}
finalbooleankeyguardshowing=keyguardisshowingtq (;
mglobalactions.showdialog (keyguardshowing,isDeviceProvisioned );
密钥签名(if )
//sinceittooktwosecondsoflongpresstobringthisup,
//pokethewakelocksotheyhavesometimetoseethedialog。
mKeyguardMediator.userActivity (;
}
}
分两个阶段进行。 首先创建全局操作,然后在showDialog中出现。 主要功能是在showDialog上完成的。
公共语音密码(booleankeyguardshowing,booleanisDeviceProvisioned ) )。
mkeyguardshowing=keyguardshowing;
mdeviceprovisioned=isdeviceprovisioned;
if(mdialog )!=null ) {
mDialog.dismiss (;
mDialog=null;
//Showdelayed,sothatthedismissofthepreviousdialogcompletes
mhandler.sendemptymessage (message _ show;
}else{
handleShow (;
}
}
然后调用handleShow
privatevoidhandleShow (
awakenIfNecessary (;
mDialog=creat
eDialog();prepareDialog();
WindowManager.LayoutParams attrs = mDialog.getWindow().getAttributes();
attrs.setTitle("GlobalActions");
mDialog.getWindow().setAttributes(attrs);
mDialog.show();
mDialog.getWindow().getDecorView().setSystemUiVisibility(View.STATUS_BAR_DISABLE_EXPAND);
} 在createDialog中主要是准备Dialog显示的数据,最关键的是mItems, 这代表关机时候显示的每一项,每一项实际是一个action,里面定义了如何创建Diaolg以及点击时的响应,
以添加飞行模式为例,
// last: silent mode
if(SHOW_SILENT_TOGGLE) {
mItems.add(mSilentModeAction);
}
Action接口的实现:
Implemented By
GlobalActions.SilentModeTriStateAction
GlobalActions.SinglePressAction
GlobalActions.ToggleAction
每一项的动作对应的View添加进MyAdapter,通过ListView来管理
privateMyAdapter mAdapter; 在创建Item的时候,
publicView getView(intposition, View convertView, ViewGroup parent) {
Action action = getItem(position);
returnaction.create(mContext, convertView, parent, LayoutInflater.from(mContext));
}
会分别调用每一个Action的onCreate来创建每一个Item View,每种Item View对应的实现了Action的接口,从而定义不同的点击动作
以来电模式的选择为例,
createItem:
publicView create(Context context, View convertView, ViewGroup parent,
LayoutInflater inflater) {
View v = inflater.inflate(R.layout.global_actions_silent_mode, parent, false);
intselectedIndex = ringerModeToIndex(mAudioManager.getRingerMode());
for(inti =0; i <3; i++) {
View itemView = v.findViewById(ITEM_IDS[i]);
itemView.setSelected(selectedIndex == i);
// Set up click handler
itemView.setTag(i);
itemView.setOnClickListener(this);
}
returnv;
}
item 响应事件:
publicvoidonClick(View v) {
if(!(v.getTag()instanceofInteger))return;
intindex = (Integer) v.getTag();
mAudioManager.setRingerMode(indexToRingerMode(index));
mHandler.sendEmptyMessageDelayed(MESSAGE_DISMISS, DIALOG_DISMISS_DELAY);
}
当点击了震动后,会调用AudioManager的setRingMode,经过AudioService处理后,会发出RINGER_MODE_CHAGNED_ACTION的广播,然后GlobalActions会接收到广播:
privateBroadcastReceiver mRingerModeReceiver =newBroadcastReceiver() {
@Override
publicvoidonReceive(Context context, Intent intent) {
if(intent.getAction().equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
mHandler.sendEmptyMessage(MESSAGE_REFRESH);
}
}
};
privateHandler mHandler =newHandler() {
publicvoidhandleMessage(Message msg) {
switch(msg.what) {
caseMESSAGE_DISMISS:
if(mDialog !=null) {
mDialog.dismiss();
}
break;
caseMESSAGE_REFRESH:
refreshSilentMode();
mAdapter.notifyDataSetChanged();
break;
caseMESSAGE_SHOW:
handleShow();
break;
}
}
};
最终会在Handler中更新图片,然后响应刚才的dismiss事件mHandler.sendEmptyMessageDelayed(MESSAGE_DISMISS, DIALOG_DISMISS_DELAY);让对话框消失
Android通过这样的方式,让程序的扩展性得到了很大的提升,这是值得借鉴的地方