首次安裝apk點(diǎn)擊Home鍵后再次打開導(dǎo)致APP重啟問題

問題描述:

開發(fā)者打包發(fā)布一個(gè)release版本app媚污,將app包通過電腦QQ傳送到手機(jī)QQ上面京髓,點(diǎn)擊安裝甸私,安裝后選擇打開app,頁面結(jié)構(gòu)如下:
1、閃屏頁SplashActivity---> 登錄頁LoginActivity---> 主頁MainActivity
2家破、用戶下載app到手機(jī)喊积,通過文件管理器找到并安裝這個(gè)apk,安裝后提示:“安裝完成,你可以打開xxx應(yīng)用了”,
3、用戶打開app愉老,輸入賬號(hào)密碼跳轉(zhuǎn)到了主頁MainActivity璧尸。
4、用戶按下Home鍵活烙,然后在程序列表點(diǎn)擊app,
先后顯示:閃屏頁SplashActivity---> 登錄頁LoginActivity,APP重啟了!亮瞎了24K鈦合金狗眼的我們覺得這玩法不對(duì)吧?
期待頁面:顯示原先的主頁MainActivity。
奇怪的是:真機(jī)在debug開發(fā)調(diào)試時(shí)不會(huì)出現(xiàn)這個(gè)問題???

問題原因:

debug版本是通過adb安裝啟動(dòng)或平常的桌面Icon圖標(biāo)啟動(dòng),
release版本是安裝這類第三方平臺(tái)啟動(dòng)。
兩者的啟動(dòng)intent不相同!(相同是指:?jiǎn)?dòng)類,action、category等等全部一樣,不可多項(xiàng)也不可缺少)

在解決問題前,先了解一下相關(guān):

1援所、Home主界面其實(shí)也是一個(gè)Activity耻涛。

當(dāng)從APP界面按下Home鍵盤墨辛,實(shí)際是啟動(dòng)APP跳轉(zhuǎn)到Home主界面,這樣我們的程序就被置于后臺(tái),被這個(gè)Home主界面Activity覆蓋。

2彩掐、Activity的Task管理

Android系統(tǒng)的App啟動(dòng)與切換管理依賴于相關(guān)Activity的Task的管理。一個(gè)Task之中可能含有若干個(gè)Activity,為了簡(jiǎn)便起見,我們這里記錄
【Task A】的Activity分別為 【A1】 、【A2】等,
【Task B】的Activity分別為 【B1】 诗充、【B2】茎匠。

那么我們來分析下App之間是怎么切換的造烁。假設(shè)應(yīng)用都是單Task應(yīng)用(相對(duì)于大部分的普通App來說煤伟,都是采用單一Task來管理的)

桌面程序App:【TaskA】 ---- 存在Activity有【A1】 ---- 其棧的結(jié)構(gòu)為 A1
應(yīng)用程序B:【TaskB】 ---- 存在Activity有【B1】【B2】 ---- 其棧的結(jié)構(gòu)為 B1_B2
應(yīng)用程序C: 【TaskC】 ---- 存在Activity有【C1】【C2】 ---- 其棧的結(jié)構(gòu)為 C1_C2

a、那么我們進(jìn)入桌面時(shí):Task之間的結(jié)構(gòu)是 A1 ---- 也就是只有一個(gè)【TaskA】棧(桌面Task),并且位于最前端(這里表現(xiàn)為最后添加的末端)

b押赊、然后我們點(diǎn)擊應(yīng)用程序B的圖標(biāo)咽袜,啟動(dòng)B :Task之間的結(jié)構(gòu)是 A1B1B2 ---- 添加了一個(gè)【TaskB】,而且【TaskB】也是位于最前端瓜浸,現(xiàn)在顯示的是【TaskB】的B2的Activity的界面

c、接著點(diǎn)擊home鍵: Android對(duì)于home做了特殊默認(rèn)處理比原,就是會(huì)把桌面Task挪到所以Task最前端插佛,Task結(jié)構(gòu)應(yīng)該變成 B1_B2_A1 ---- 【TaskA】挪到隊(duì)列最前端,現(xiàn)在顯示的是【TaskA】的A1的Activity的界面量窘,也就是桌面

d雇寇、我們?cè)僭谧烂纥c(diǎn)擊應(yīng)用程序C的圖標(biāo),啟動(dòng)C : Task之間的結(jié)構(gòu)變成 B1B2A1C1C2 ---- 添加了一個(gè)【TaskC】蚌铜,而且【TaskC】也是位于最前端锨侯,現(xiàn)在顯示的是【TaskC】的C2的Activity的界面

從上面的例子,我們可以知道:
  我們編寫任何一個(gè)Activity的時(shí)候冬殃,都可以在AndroidManifest里面顯式指定一個(gè)taskAffinity的屬性囚痴,也就是說該Activity歸屬于對(duì)應(yīng)taskAffinity的棧;如果沒有指定任何taskAffinity审葬,那么該Activity將會(huì)直接歸屬于包名所在的Task之下深滚。而我們啟動(dòng)一個(gè)Activity時(shí)(這里只討論standard啟動(dòng)模式)骂束,那么回去先搜尋對(duì)應(yīng)的Task是否存在,如果不存在成箫,新建一個(gè)Task并將Activity入棧展箱,如果已經(jīng)存在對(duì)應(yīng)的Task,那么直接在對(duì)應(yīng)Task入棧即可蹬昌。

那么問題來了:如果我們?cè)谏厦娴赿步點(diǎn)擊的圖片并不是程序C的圖標(biāo)混驰,而是重新點(diǎn)擊了程序B的圖標(biāo),此時(shí)【TaskB】是已經(jīng)存在的了皂贩,那么為了不會(huì)講B的入口activity(B1)直接在【TaskB】入棧栖榨,而是將【TaskB】挪到前臺(tái)并不做任何Activity啟動(dòng)的操作呢?

3明刷、桌面的啟動(dòng)管理:

回頭研究下AndroidManifest這個(gè)文件婴栽,我們輕而易舉發(fā)現(xiàn),但凡是App入口Activity辈末,那么一定會(huì)包含

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

這幾行代碼愚争。這里到底有什么玄機(jī)呢?其實(shí)這個(gè)就是跟桌面約定好的啟動(dòng)攔截過濾器挤聘。因?yàn)樽烂嬗幸粋€(gè)很明顯的需求就是轰枝,如果我們?cè)俅吸c(diǎn)擊已經(jīng)在后臺(tái)的App圖標(biāo)時(shí),是應(yīng)該將該后臺(tái)任務(wù)挪到前臺(tái)而不是再次啟動(dòng)該App程序组去。
而從柯元旦所著的《android內(nèi)核剖析》一書中有記錄如下規(guī)則:
  每次啟動(dòng)Intent導(dǎo)致新創(chuàng)建Task的時(shí)候鞍陨,該Task會(huì)記錄導(dǎo)致其創(chuàng)建的Intent;而如果后續(xù)需要有一個(gè)新的與創(chuàng)建Intent完全一致(完全一致定位為:?jiǎn)?dòng)類从隆,action诚撵、category等等全部一樣,不可多項(xiàng)也不可缺少)键闺,那么該Intent并不會(huì)觸發(fā)Activity的新建啟動(dòng)寿烟,而只會(huì)將已經(jīng)存在的對(duì)應(yīng)Task移到前臺(tái);這也就是為什么桌面會(huì)在再次點(diǎn)擊圖標(biāo)時(shí)將后臺(tái)任務(wù)挪到前臺(tái)而不是重新啟動(dòng)App的實(shí)現(xiàn)艾杏。

那么為啥要指定入口Activity特定的action和category呢韧衣,那就是為了讓桌面啟動(dòng)app所用的Intent具有特殊性,也就是添加了特別的攔截器购桑,避免其他應(yīng)用內(nèi)或者應(yīng)用間的Intent對(duì)于這個(gè)啟動(dòng)方式的干擾畅铭。

原理剖析:

文件管理器雖然使用Intent來啟動(dòng)剛剛安裝的那個(gè)App,但:它的啟動(dòng)Intent并沒有跟桌面的啟動(dòng)Intent完全一致勃蜘!
我們將桌面的Task記為【TaskDesktop】硕噩,文件管理器的Task記為【TaskFile】,我們應(yīng)用的Task記為【TaskApp】缭贡,分析如下:

進(jìn)入桌面: D1 ---- D1是單純的桌面

打開文件管理器: D1_F1_F2 ---- F2是安裝完畢后詢問是否啟動(dòng)對(duì)應(yīng)程序的Activity

點(diǎn)擊打開: D1_F1_F2_A1_A2 ---- A1是入口閃屏頁炉擅,A2是登錄Activity

返回桌面: F1_F2_A1_A2_D1 ---- 回到桌面頁辉懒,也就是D1前置

點(diǎn)擊A的圖標(biāo): F1_F2_D1_A1_A2_A1 ---- 找到【TaskA】,挪到前臺(tái)谍失,由于比對(duì)Intent并不是完全一致眶俩,所以該請(qǐng)求是新啟動(dòng)Activity,那么把A1添加到對(duì)應(yīng)的【TaskA】中

所以bug出現(xiàn)了快鱼,出現(xiàn)了再一次的閃屏頁【A1】颠印,問題定位成功!

PS:這里我稍微變種一下抹竹,因?yàn)橐话阄覀冮W屏頁都是在啟動(dòng)登錄頁后finish的塞栅,而登錄頁一般是singleTask模式

打開文件管理器: D1_F1_F2 ---- F2是安裝完畢后詢問是否啟動(dòng)對(duì)應(yīng)程序的Activity

點(diǎn)擊打開: D1_F1_F2_A2 ---- A1是入口閃屏頁忘晤,A2是登錄Activity把敢,啟動(dòng)后A1業(yè)務(wù)邏輯應(yīng)該finish掉惠窄,所以從【TaskA】中挪去

返回桌面: F1_F2_A2_D1 ---- 回到桌面頁,也就是D1前置

點(diǎn)擊A的圖標(biāo): F1_F2_D1_A2_A1 -> 找到【TaskA】袄琳,挪到前臺(tái)询件,由于比對(duì)啟動(dòng)的Intent不完全一致,所以新創(chuàng)建一個(gè)A1 Activity跨蟹,那么把A1添加到對(duì)應(yīng)的【TaskA】中雳殊,然后A1所再一次觸發(fā)啟動(dòng)登錄頁 A2,但是登錄頁是singleTask模式窗轩,所以又回到了上次對(duì)應(yīng)的A2登錄頁,所以現(xiàn)象為再一次出現(xiàn)閃屏頁座咆,然后回到原先的登錄頁界面痢艺。

解決方法

1、讓騰訊那些第三方平臺(tái)修正其啟動(dòng)Intent的設(shè)置介陶,使其與原聲桌面啟動(dòng)Intent保持完全一致堤舒。(PS:基本不可能)
2、正常啟動(dòng)的閃屏頁Activity必定在【TaskA】的最底部(實(shí)際已finish掉被登錄頁取代)哺呜,而第二次閃屏Activity不可能位于Task的最底部舌缤,所以在閃屏頁Activity的onCreate代碼:

protected void onCreate(@Nullable Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     
     // 避免從桌面啟動(dòng)程序后,會(huì)重新實(shí)例化入口類的activity
     if (!this.isTaskRoot()) {
         Intent intent = getIntent();
         if (intent != null) {
             String action = intent.getAction();
             if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && Intent.ACTION_MAIN.equals(action)) {
                 finish();
                 return;
             }
         }
     }
 }

或者

   protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //首次啟動(dòng) Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT 為 0某残,再次點(diǎn)擊圖標(biāo)啟動(dòng)時(shí)就不為零了
        if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
            finish();
            return;
        }
    }

讀到這里国撵,細(xì)心的讀者一定會(huì)問:你上面說的情形只適用閃屏頁和登錄頁,如果登錄進(jìn)去主頁MainActivity按Home鍵玻墅,如何處理呢介牙?
1、閃屏頁的OnCreate方法根據(jù)登錄狀態(tài)判斷跳轉(zhuǎn):

        if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
            if (UserInfo.getInstance().isLogined) { // 若已登錄澳厢,跳轉(zhuǎn)到主頁
                readyGoThenKill(MainActivity.class);
            } else { // 若未登錄环础,引導(dǎo)用戶登錄
                readyGoThenKill(UserLoginActivity.class);
            }
            return;
        }

2囚似、設(shè)定MainActivity的launchMode="singleTask",在AndroidManifest.xml修改

<activity
    android:name="com.emp.frame.MainActivity"
    android:launchMode="singleTask" />

轉(zhuǎn)載:https://blog.csdn.net/LVXIANGAN/article/details/82870762

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末线得,一起剝皮案震驚了整個(gè)濱河市饶唤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌贯钩,老刑警劉巖募狂,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異魏保,居然都是意外死亡熬尺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門谓罗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來粱哼,“玉大人,你說我怎么就攤上這事檩咱〗掖耄” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵刻蚯,是天一觀的道長(zhǎng)绊含。 經(jīng)常有香客問我,道長(zhǎng)炊汹,這世上最難降的妖魔是什么躬充? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮讨便,結(jié)果婚禮上充甚,老公的妹妹穿的比我還像新娘。我一直安慰自己霸褒,他們只是感情好伴找,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著废菱,像睡著了一般技矮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上殊轴,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天衰倦,我揣著相機(jī)與錄音,去河邊找鬼梳凛。 笑死耿币,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的韧拒。 我是一名探鬼主播淹接,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼十性,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了塑悼?” 一聲冷哼從身側(cè)響起劲适,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎厢蒜,沒想到半個(gè)月后霞势,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡斑鸦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年愕贡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片巷屿。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡固以,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嘱巾,到底是詐尸還是另有隱情憨琳,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布旬昭,位于F島的核電站篙螟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏问拘。R本人自食惡果不足惜遍略,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望骤坐。 院中可真熱鬧墅冷,春花似錦、人聲如沸或油。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽顶岸。三九已至,卻和暖如春叫编,著一層夾襖步出監(jiān)牢的瞬間辖佣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國打工搓逾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留卷谈,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓霞篡,卻偏偏與公主長(zhǎng)得像世蔗,于是被迫代替她去往敵國和親端逼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容