歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android Home鍵詳解

Android Home鍵詳解

日期:2017/3/1 10:40:06   编辑:Linux編程
當我們從Home點擊ShortCut圖標啟動一個應用程序後,這個應用程序打開了很多個Activity,假設順序為A,B,C,然後我們按Home鍵,再次從桌面用圖標啟動這個應用程序,我們會發現顯示的是剛才的C,而不是A。這裡我們普遍的想法是按Home鍵是讓程序退到後台,然後讓桌面顯示出來。那麼我們就來看看Home鍵到底是怎麼回事。

在Framework中我們找到源碼,我們首先在interceptKeyBeforeDispatching這個方法中找到Home按鍵代碼如下

[java]

  1. // If the HOME button is currently being held, then we do special
  2. // chording with it.
  3. if (mHomePressed) {
  4. // If we have released the home key, and didn't do anything else
  5. // while it was pressed, then it is time to go home!
  6. if (keyCode == KeyEvent.KEYCODE_HOME) {
  7. if (!down) {
  8. mHomePressed = false;
  9. if (!canceled) {
  10. // If an incoming call is ringing, HOME is totally disabled.
  11. // (The user is already on the InCallScreen at this point,
  12. // and his ONLY options are to answer or reject the call.)
  13. boolean incomingRinging = false;
  14. try {
  15. ITelephony phoneServ = getPhoneInterface();
  16. if (phoneServ != null) {
  17. incomingRinging = phoneServ.isRinging();
  18. } else {
  19. Log.w(TAG, "Unable to find ITelephony interface");
  20. }
  21. } catch (RemoteException ex) {
  22. Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
  23. }
  24. if (incomingRinging) {
  25. Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
  26. } else {
  27. launchHomeFromHotKey();
  28. }
  29. } else {
  30. Log.i(TAG, "Ignoring HOME; event canceled.");
  31. }
  32. }
  33. }
  34. return true;
  35. }
這裡就是按Home鍵時執行的方法我們找到 [java]
  1. launchHomeFromHotKey();
  2. /**
  3. * A home key -> launch home action was detected. Take the appropriate action
  4. * given the situation with the keyguard.
  5. */
  6. void launchHomeFromHotKey() {
  7. if (mKeyguardMediator.isShowingAndNotHidden()) {
  8. // don't launch home if keyguard showing
  9. } else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
  10. // when in keyguard restricted mode, must first verify unlock
  11. // before launching home
  12. mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {
  13. public void onKeyguardExitResult(boolean success) {
  14. if (success) {
  15. try {
  16. ActivityManagerNative.getDefault().stopAppSwitches();
  17. } catch (RemoteException e) {
  18. }
  19. sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
  20. startDockOrHome();
  21. }
  22. }
  23. });
  24. } else {
  25. // no keyguard stuff to worry about, just launch home!
  26. try {
  27. ActivityManagerNative.getDefault().stopAppSwitches();
  28. } catch (RemoteException e) {
  29. }
  30. sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
  31. startDockOrHome();
  32. }
  33. }
再進入startDockOrHome();

[java]
  1. void startDockOrHome() {
  2. Intent dock = createHomeDockIntent();
  3. if (dock != null) {
  4. try {
  5. mContext.startActivity(dock);
  6. return;
  7. } catch (ActivityNotFoundException e) {
  8. }
  9. }
  10. mContext.startActivity(mHomeIntent);
  11. }
這裡我們發現,源碼中做了車載模式和普通模式Home的區別,在Android2.3原生系統中有車載模式這個應用程式,打開後按Home鍵我們返回的是車載模式的桌面,而普通情況下按Home返回正常桌面,再來看看mContext.startActivity(mHomeIntent)這個方法,我們發現,Home鍵也是打開一個activity,不同的是下面的代碼

[java]

  1. mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
  2. mHomeIntent.addCategory(Intent.CATEGORY_HOME);
  3. mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
  4. | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
這段代碼是在init()方法中,對mHomeIntent的初始化,這個Intent就是跳轉到Launcher程序中的配置了 <category android:name="android.intent.category.HOME" />這個屬性的Launcher Activity,另外我們還看到兩個flag [java]
  1. FLAG_ACTIVITY_NEW_TASK和FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

newTask保證了我們回到之前Launcher所在的棧,reset task if need是設置清理棧標志,保證清除掉該棧除Launcher以外其他activity(在Launcher清單文件中我們還看到android:clearTaskOnLaunch="true"這個屬性,後面會描述),這樣我們的Launcher當然會在自己單獨的Task中,而且android:launchMode="singleTask"這個屬性保證不會啟動一個新的Launcher。

通過Launcher啟動的其他Activity不會跑到Launcher所在的Task中(後面的文章會提到Launcher啟動activity的過程)。所以按Home鍵是打開了Launcher這個activity並且保證他在自己單獨的Task中,其他的activity進入stop狀態。

另外Launcher中打開一個activity直接進入之前打開的Task 而不是新打開一個activity.

Copyright © Linux教程網 All Rights Reserved