問題描述:
1、從Android應用市場下載并安裝應用,安裝完成后,當前界面下方會出現“打開”按鈕,這時候我們點擊“打開”,會啟動應用,進入到應用的啟動頁面,然后進入應用的主界面,這個時候我們什么也不做,按Home鍵返回到桌面,找到應用圖標所在區域,點擊應用圖標,此時我們所期待的現象是重新回到之前我們打開的頁面,對嗎?然后這個時候你點擊桌面上的應用圖標打開應用,這個時候你會驚奇的發現應用重新啟動了。按返回鍵你退出應用一次,然后又回到了之前啟動的應用頁面了。
2、另外,在部分第三方桌面啟動app的時候也會有這種情況出現,我測試的時候使用的“米粒桌面“,在全部應用頁打開應用,按Home鍵切到米粒桌面,在米粒桌面的最近使用中打開,會跟上面的結果一樣,應用被重啟了!
問題重現:
通過上面現象描述,大家應該看懂了問題,可以通過一個具體的實現來重現一下這個問題,首先我安裝米粒桌面(非廣告,只是我用習慣了,第三方應用市場也是可以),然后安裝“哄你”app(也可以嘗試其他的app),安裝完成后,在米粒桌面的全部應用頁面中啟動 “哄你”APP,然后按home鍵切換到米粒桌面的首頁,找到最近使用的app列表,打開“哄你”APP,這個時候發現應用會重啟,并且退出的時候退出兩次才會回到桌面,那么我們來分析一下這是為什么呢?當然,哄你這款軟件并不會,因為我做過處理了,所以如果你們想試驗的,可以隨便挑一款其他APP來測試。
下面是我的調試打印信息:
1、首先從全部應用頁面啟動哄你APP:
可以看到啟動頁的Intent信息:
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.kk.sleep/.splash.ui.EntryActivity bnds=[275,1336][545,1606] }
2、按Home鍵回到桌面,從最近應用中打開哄你APP:
可以看到啟動頁的OnCrate()再次被調用了! Intent的信息:
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10600000 pkg=com.kk.sleep cmp=com.kk.sleep/.splash.ui.EntryActivity }
從上面的調試Log中可以看到兩次啟動的Intent中的Flag不一致!
解決方案:
在啟動的Activity的OnCreate方法中加入:
if(!this.isTaskRoot()) {
Log.d(TAG+"_entry","avoid the enrtyActivity re-created");
Intent intent = getIntent();
if(intent !=null) {
String action = intent.getAction();
if(intent.hasCategory(Intent.CATEGORY_LAUNCHER) && Intent.ACTION_MAIN.equals(action)) {
finish();
return;
}
}
}else{
setContentView(R.layout.activity_entry);
init();
}
if(!isTaskRoot()),判斷該Activity是不是任務空間的源Activity,如果返回Flase,就是說是被系統重新實例化出來,如果這個Activity是你的Lanucher Activity,這里可以直接Finish關閉頁面了。
需要的注意是:
1、如果上面的Activity中實現了finish() 和 onDestroy() 方法,一定要保證這兩個方法中不會有對空對象的操作以及注銷未注冊的廣播等類似操作,因為第二次打開應用時,Oncreate()中還沒初始化的時候,就會調用finish()方法,及直接觸發onDestroy()方法,而這兩個函數里面的對象變量都還未進行初始化等操作。
2、finish() 和 onDestroy() 方法中不能有System.exit(0);否則第二次打開應用殺掉進程時也會將第一次打開的應用殺掉。
解決問題的辦法很簡單,一行代碼就搞定,但如果不細心,就難以發現這類煩人的問題。如果大家有什么疑問可以留言,歡迎大家一起交流。