在Android中我们没法通过onKeyEvent监听到home按键监听事件,而Launcher中当我们进入到all apps页面候点击home按键则需要返回到Workspace中,这又是如何做到的呢。有以下三种方式。其中前两者其它应用也可参照使用,第三种只对Launcher管用。
在我们每次点击Home按键时系统会发出action为Intent.ACTION_CLOSE_SYSTEM_DIALOGS的广播,用于关闭系统Dialog,此广播可以来监听Home按键。而我们的Launcher也是这样做的。在Launcher的onCreate中:
//home按键广播
IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
registerReceiver(mCloseSystemDialogsReceiver, filter);
此广播监听的接收者时CloseSystemDialogsIntentReceiver。可以看到,在onReceive中它关闭了系统Dalog和panel。
private class CloseSystemDialogsIntentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
closeSystemDialogs();
Log.i("Launcher","closeSystemDialogs");
}
}
在Activity中的onUserLeaveHint方法会在用户主动点击home按键时回调,此方法在onPause之前被调用,当然如果应用时被动进入后台,比如有用户来电导致当前页面因来电页面打开而进入后台,则onUserLeaveHint不会被调用。在Launcher中我们可以看见此方法被重写。
/**
* 此方法当用户点击home键或者menu键离开launcher应用时调用
*/
protected void onUserLeaveHint() {
super.onUserLeaveHint();
sPausedFromUserAction = true;
Log.i(TAG,"onUserLeaveHint");
}
当我们点击SysytemUI中的导航栏(NavigationBar)中的home按钮(KeyButtonView)时其最终会调用到PhoneWindowManager中的startDockOrHome中,在此方法中会启动符合HomeIntent的页面(其实就是Launcher页面)。
mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
mHomeIntent.addCategory(Intent.CATEGORY_HOME);
mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
在我们的Launcher中也在onNewIntent中对此intent进行了处理。
@Override
protected void onNewIntent(Intent intent) {
Log.i("Launcher","onNewIntent");
long startTime = 0;
if (DEBUG_RESUME_TIME) {
startTime = System.currentTimeMillis();
}
super.onNewIntent(intent);
// Close the menu
if (Intent.ACTION_MAIN.equals(intent.getAction())) {
// also will cancel mWaitingForResult.
closeSystemDialogs();
final boolean alreadyOnHome =
((intent.getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)
!= Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Runnable processIntent = new Runnable() {
public void run() {
if (mWorkspace == null) {
// Can be cases where mWorkspace is null, this prevents a NPE
return;
}
Folder openFolder = mWorkspace.getOpenFolder();
// In all these cases, only animate if we're already on home
mWorkspace.exitWidgetResizeMode();
if (alreadyOnHome && mState == State.WORKSPACE && !mWorkspace.isTouchActive() &&
openFolder == null) {
mWorkspace.moveToDefaultScreen(true);
}
closeFolder();
exitSpringLoadedDragMode();
// If we are already on home, then just animate back to the workspace,
// otherwise, just wait until onResume to set the state back to Workspace
if (alreadyOnHome) {
showWorkspace(true);
} else {
mOnResumeState = State.WORKSPACE;
}
final View v = getWindow().peekDecorView();
if (v != null && v.getWindowToken() != null) {
InputMethodManager imm = (InputMethodManager)getSystemService(
INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
// Reset AllApps to its initial state
if (!alreadyOnHome && mAppsCustomizeTabHost != null) {
mAppsCustomizeTabHost.reset();
}
}
};
if (alreadyOnHome && !mWorkspace.hasWindowFocus()) {
// Delay processing of the intent to allow the status bar animation to finish
// first in order to avoid janky animations.
mWorkspace.postDelayed(processIntent, 350);
} else {
// Process the intent immediately.
processIntent.run();
}
}
if (DEBUG_RESUME_TIME) {
Log.d(TAG, "Time spent in onNewIntent: " + (System.currentTimeMillis() - startTime));
}
}