Android长按关机键,会弹出关机的对话框,如下图:
现在分析一下详细的流程:
1) PWM中,会调用
private void interceptPowerKeyDown(boolean handled) { mPowerKeyHandled = handled; if (!handled) { mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout()); } }从而进入mPowerLongPress
private final Runnable mPowerLongPress = new Runnable() { @Override public void run() { // The context isn't read if (mLongPressOnPowerBehavior < 0) { mLongPressOnPowerBehavior = mContext.getResources().getInteger( com.android.internal.R.integer.config_longPressOnPowerBehavior); } ... switch (resolvedBehavior) { case LONG_PRESS_POWER_NOTHING: break; case LONG_PRESS_POWER_GLOBAL_ACTIONS: mPowerKeyHandled = true; if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) { performAuditoryFeedbackForAccessibilityIfNeed(); } sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); showGlobalActionsDialog(); break; ... } } };调用showGlobalActionsDialog
void showGlobalActionsDialog() { if (mGlobalActions == null) { mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs); } final boolean keyguardShowing = keyguardIsShowingTq(); mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned()); if (keyguardShowing) { // since it took two seconds of long press to bring this up, // poke the wake lock so they have some time to see the dialog. mKeyguardMediator.userActivity(); } }
public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) { mKeyguardShowing = keyguardShowing; mDeviceProvisioned = isDeviceProvisioned; if (mDialog != null) { mDialog.dismiss(); mDialog = null; // Show delayed, so that the dismiss of the previous dialog completes mHandler.sendEmptyMessage(MESSAGE_SHOW); } else { handleShow(); } }
然后调用handleShow
private void handleShow() { awakenIfNecessary(); mDialog = createDialog(); 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
private MyAdapter mAdapter;在创建Item的时候,
public View getView(int position, View convertView, ViewGroup parent) { Action action = getItem(position); return action.create(mContext, convertView, parent, LayoutInflater.from(mContext)); }
会分别调用每一个Action的onCreate来创建每一个Item View,每种Item View对应的实现了Action的接口,从而定义不同的点击动作
以来电模式的选择为例,
createItem:
public View create(Context context, View convertView, ViewGroup parent, LayoutInflater inflater) { View v = inflater.inflate(R.layout.global_actions_silent_mode, parent, false); int selectedIndex = ringerModeToIndex(mAudioManager.getRingerMode()); for (int i = 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); } return v; }
public void onClick(View v) { if (!(v.getTag() instanceof Integer)) return; int index = (Integer) v.getTag(); mAudioManager.setRingerMode(indexToRingerMode(index)); mHandler.sendEmptyMessageDelayed(MESSAGE_DISMISS, DIALOG_DISMISS_DELAY); }
当点击了震动后,会调用AudioManager的setRingMode,经过AudioService处理后,会发出RINGER_MODE_CHAGNED_ACTION的广播,然后GlobalActions会接收到广播:
private BroadcastReceiver mRingerModeReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { mHandler.sendEmptyMessage(MESSAGE_REFRESH); } } };
private Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_DISMISS: if (mDialog != null) { mDialog.dismiss(); } break; case MESSAGE_REFRESH: refreshSilentMode(); mAdapter.notifyDataSetChanged(); break; case MESSAGE_SHOW: handleShow(); break; } } };
Android通过这样的方式,让程序的扩展性得到了很大的提升,这是值得借鉴的地方