記錄一個奇怪的bug:紅米Note5A 手機按Home鍵后每次進入App都會出現(xiàn)閃屏頁

前言

前些天凰棉,測試MM發(fā)現(xiàn)了一個比較奇怪的bug膀哲。

具體表現(xiàn)是:

1往产、將app包通過電腦QQ傳送到手機QQ上面,點擊安裝某宪,安裝后選擇打開app (此間的應(yīng)用邏輯應(yīng)該是要觸發(fā) 【閃屏頁Activity】仿村, 然后跳轉(zhuǎn) 【主頁Activity】)

2、然后MM在 【主頁Activity】 時按下了 【Home鍵】兴喂,回到桌面

3蔼囊、再點擊app的icon圖標,原諒耿直的我們都是覺得應(yīng)該直接回到【主頁Activity】衣迷,但是結(jié)果卻是又一次觸發(fā) 【閃屏頁Activity】畏鼓,亮瞎了24K鈦合金狗眼的我們覺得這玩法不對吧?

4蘑险、然后滴肿,收拾收拾心情開始定位之路吧~

現(xiàn)象分析

先說說項目結(jié)構(gòu)吧,我們這邊的項目需求邏輯是 先進入 【閃屏頁Activity】(普通的Activity佃迄,啟動模式為standard)泼差,然后根據(jù)一堆初始化操作和判斷,一般是接著進入【主頁Activity】(Activity的啟動模式為singleTask)呵俏;點擊home鍵不做任何攔截處理堆缘,按照系統(tǒng)默認邏輯返回Lanuch桌面。

也就是說普碎,app的整體交互邏輯并沒有特殊之處吼肥,并非業(yè)務(wù)邏輯導(dǎo)致的bug。那么回顧下不同的地方,也就是啟動App的入口的區(qū)別了缀皱,一者是平常的桌面Icon圖標啟動斗这,一者是QQ安裝這類第三方平臺啟動。我們都知道啤斗,桌面啟動的話也是通過startActivity這個api通過特定的Intent向ActivityManagerServer發(fā)起啟動任務(wù)表箭;所以我們可以推導(dǎo)出QQ安裝啟動這類方式也是通過Intent啟動對應(yīng)的App。

再往下分析的話钮莲,可能需要一些前置知識需要了解才能更好的理解免钻。

前置知識

1、Activity的Task管理

一般來說崔拥,整個Android系統(tǒng)的App啟動與切換管理依賴于相關(guān)Activity的Task的管理极舔。一個Task之中可能含有若干個Activity,為了簡便起見链瓦,我們這里記錄【Task A】的Activity分別為 【A1】 拆魏、【A2】等,【Task B】的Activity分別為 【B1】 澡绩、【B2】稽揭。

那么我們來分析下App之間是怎么切換的俺附。

假設(shè)應(yīng)用都是單Task應(yīng)用(相對于大部分的普通App來說肥卡,都是采用單一Task來管理的)

桌面程序App:【TaskA】 ---- 存在Activity有【A1】 ---- 其棧的結(jié)構(gòu)為 A1

應(yīng)用程序B:【TaskB】 ---- 存在Activity有【B1】【B2】 ---- 其棧的結(jié)構(gòu)為 B1B2

應(yīng)用程序C: 【TaskC】 ---- 存在Activity有【C1】【C2】 ---- 其棧的結(jié)構(gòu)為 C1C2

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

b步鉴、然后我們點擊應(yīng)用程序B的圖標,啟動B :Task之間的結(jié)構(gòu)是 A1B1B2 ---- 添加了一個【TaskB】璃哟,而且【TaskB】也是位于最前端氛琢,現(xiàn)在顯示的是【TaskB】的B2的Activity的界面

c、接著點擊home鍵: Android對于home做了特殊默認處理随闪,就是會把桌面Task挪到所以Task最前端阳似,Task結(jié)構(gòu)應(yīng)該變成 B1B2A1 ---- 【TaskA】挪到隊列最前端,現(xiàn)在顯示的是【TaskA】的A1的Activity的界面铐伴,也就是桌面

d撮奏、我們再在桌面點擊應(yīng)用程序C的圖標,啟動C : Task之間的結(jié)構(gòu)變成 B1B2A1C1C2 ---- 添加了一個【TaskC】当宴,而且【TaskC】也是位于最前端畜吊,現(xiàn)在顯示的是【TaskC】的C2的Activity的界面

從上面的例子,我們可以大致了解到Android是怎么管理不同app之間切換的邏輯:

我們編寫任何一個Activity的時候户矢,都可以在AndroidManifest里面顯式指定一個taskAffinity的屬性玲献,也就是說該Activity歸屬于對應(yīng)taskAffinity的棧;如果沒有指定任何taskAffinity,那么該Activity將會直接歸屬于包名所在的Task之下捌年。而我們啟動一個Activity時(這里只討論standard啟動模式)瓢娜,那么回去先搜尋對應(yīng)的Task是否存在,如果不存在礼预,新建一個Task并將Activity入棧恋腕,如果已經(jīng)存在對應(yīng)的Task,那么直接在對應(yīng)Task入棧即可逆瑞。

那么問題來了:如果我們在上面第d步點擊的圖片并不是程序C的圖標荠藤,而是重新點擊了程序B的圖標,此時【TaskB】是已經(jīng)存在的了获高,那么為了不會講B的入口activity(B1)直接在【TaskB】入棧哈肖,而是將【TaskB】挪到前臺并不做任何Activity啟動的操作呢?

2念秧、桌面的啟動管理:

回頭研究下AndroidManifest這個文件淤井,我們輕而易舉發(fā)現(xiàn),但凡是App入口Activity摊趾,那么一定會包含

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

這幾行代碼币狠。這里到底有什么玄機呢?其實這個就是跟桌面約定好的啟動攔截過濾器砾层。因為桌面有一個很明顯的需求就是漩绵,如果我們再次點擊已經(jīng)在后臺的App圖標時,是應(yīng)該將該后臺任務(wù)挪到前臺而不是再次啟動該App程序肛炮。

而從柯元旦所著的《android內(nèi)核剖析》一書中有記錄如下規(guī)則:

每次啟動Intent導(dǎo)致新創(chuàng)建Task的時候止吐,該Task會記錄導(dǎo)致其創(chuàng)建的Intent;而如果后續(xù)需要有一個新的與創(chuàng)建Intent完全一致(完全一致定位為:啟動類侨糟,action碍扔、category等等全部一樣,不可多項也不可缺少)秕重,那么該Intent并不會觸發(fā)Activity的新建啟動不同,而只會將已經(jīng)存在的對應(yīng)Task移到前臺;這也就是為什么桌面會在再次點擊圖標時將后臺任務(wù)挪到前臺而不是重新啟動App的實現(xiàn)溶耘。

那么為啥要指定入口Activity特定的action和category呢二拐,有一個原因我們可以確定,就是為了讓桌面啟動app所用的Intent具有特殊性汰具,也就是添加了特別的攔截器卓鹿,避免其他應(yīng)用內(nèi)或者應(yīng)用間的Intent對于這個啟動方式的干擾。

說了這么多留荔,我們可以著手分析上續(xù)bug的產(chǎn)生原因了吟孙。

原理剖析

從此我們可以知道QQ安裝器其實也就是使用Intent來啟動其剛剛安裝的那個App澜倦,但是問題所在的是:他們的啟動Intent并沒有跟桌面的啟動Intent完全一致!

我們將桌面的Task記為【TaskL】杰妓,QQ安裝器的Task記為【TaskQ】藻治,我們應(yīng)用的Task記為【TaskA】,那么分析如下:

進入桌面: L1 ---- L1是單純的桌面

打開QQ: L1Q1Q2 ---- Q2是安裝完畢后詢問是否啟動對應(yīng)程序的Activity

點擊打開: L1Q1Q2A1A2 ---- A1是入口閃屏頁巷挥,A2是主頁Activity

返回桌面: Q1Q2A1A2L1 ---- 回到桌面頁桩卵,也就是L1前置

點擊A的圖標: Q1Q2L1A1A2A1 ---- 找到【TaskA】,挪到前臺倍宾,由于比對Intent并不是完全一致雏节,所以該請求是新啟動Activity,那么把A1添加到對應(yīng)的【TaskA】中

所以bug出現(xiàn)了高职,出現(xiàn)了再一次的閃屏頁【A1】钩乍,問題定位成功!

PS:這里我稍微變種一下怔锌,因為一般我們閃屏頁都是在啟動主頁后finish的寥粹,而主頁一般是singleTask模式

打開QQ: L1Q1Q2 ---- Q2是安裝完畢后詢問是否啟動對應(yīng)程序的Activity

點擊打開: L1Q1Q2A2 ---- A1是入口閃屏頁,A2是主頁Activity埃元,啟動后A1業(yè)務(wù)邏輯應(yīng)該finish掉涝涤,所以從【TaskA】中挪去

返回桌面: Q1Q2A2L1 ---- 回到桌面頁,也就是L1前置

點擊A的圖標: Q1Q2L1A2A1 -> Q1Q2L1A2A1 ---- 找到【TaskA】岛杀,挪到前臺阔拳,由于比對Intent并不是完全一致,所以該請求是新啟動Activity楞件,那么把A1添加到對應(yīng)的【TaskA】中衫生,然后A1所再一次觸發(fā)啟動主頁裳瘪,但是主頁是singleTask模式土浸,所以又回到了上次對應(yīng)的A2主頁,所以現(xiàn)象為再一次出現(xiàn)閃屏頁彭羹,然后回到原先的主頁界面黄伊。

解決思路

1、讓騰訊那些第三方平臺修正其啟動Intent的設(shè)置派殷,使其與原聲桌面啟動Intent保持完全一致还最。(PS:基本不可能)

2、自身業(yè)務(wù)代碼規(guī)避毡惜,我們可以知道拓轻,如果是多余的閃屏頁入口Activity的話,其基本不可能位于Task的根部经伙,而如果正常啟動的話扶叉,閃屏頁入口Activity必定在多對應(yīng)的Task的根部位置,那么我們可以從這個地方對于這個bug進行規(guī)避,方法就是在閃屏頁入口Activity的onCreate代碼加入如下一段代碼:

// 避免從桌面啟動程序后枣氧,會重新實例化入口類的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;
      }
  }
}

問題解決痰哨!

參考文章: Android Bug分析系列:第三方平臺安裝app啟動后屯阀,home鍵回到桌面后點擊app啟動時會再次啟動入口類bug的原因剖析

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子甘苍,更是在濱河造成了極大的恐慌,老刑警劉巖舀凛,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件珊蟀,死亡現(xiàn)場離奇詭異,居然都是意外死亡覆糟,警方通過查閱死者的電腦和手機瞒大,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來搪桂,“玉大人透敌,你說我怎么就攤上這事√咝担” “怎么了酗电?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長内列。 經(jīng)常有香客問我撵术,道長,這世上最難降的妖魔是什么话瞧? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任嫩与,我火速辦了婚禮,結(jié)果婚禮上交排,老公的妹妹穿的比我還像新娘划滋。我一直安慰自己,他們只是感情好埃篓,可當(dāng)我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布处坪。 她就那樣靜靜地躺著,像睡著了一般架专。 火紅的嫁衣襯著肌膚如雪同窘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天部脚,我揣著相機與錄音想邦,去河邊找鬼。 笑死委刘,一個胖子當(dāng)著我的面吹牛丧没,可吹牛的內(nèi)容都是我干的服傍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼骂铁,長吁一口氣:“原來是場噩夢啊……” “哼吹零!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拉庵,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤灿椅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后钞支,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茫蛹,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年烁挟,在試婚紗的時候發(fā)現(xiàn)自己被綠了婴洼。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡撼嗓,死狀恐怖柬采,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情且警,我是刑警寧澤粉捻,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站斑芜,受9級特大地震影響肩刃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜杏头,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一盈包、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧醇王,春花似錦呢燥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至根暑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間徙邻,已是汗流浹背排嫌。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留缰犁,地道東北人淳地。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓怖糊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親颇象。 傳聞我的和親對象是個殘疾皇子伍伤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,066評論 2 355

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