Android release包Home鍵重啟問題

個(gè)人博客地址:https://blog.yookingh.cn
該文章地址:https://blog.yookingh.cn/dev/190806-home-Restart.html

BUG描述

  1. 操作流程:打release包——安裝apk——點(diǎn)選“打開”按鈕——點(diǎn)Home鍵——點(diǎn)桌面圖標(biāo)

  2. 現(xiàn)象:App重啟

  3. 原理分析及分析過程

    • 比較【安裝apk直接打開】時(shí)的intent和【桌面圖標(biāo)打開】的intent的區(qū)別

      直接打開:(Logcat直接搜索I/ActivityManager: START u0

      I/ActivityManager: START u0 
      {
        act=android.intent.action.MAIN
        cat=[android.intent.category.LAUNCHER]
        flg=0x10000000
        pkg=com.yooking.test
        cmp=com.yooking.test/.SplashActivity
      }
      from uid 10039
      

      桌面圖標(biāo)打開:

      I/ActivityManager: START u0 
      {
        act=android.intent.action.MAIN
        cat=[android.intent.category.LAUNCHER]
        flg=0x10200000
        cmp=com.yooking.test/.SplashActivity
        bnds=[856,662][1067,951]
      }
      from uid 10068
      
    • 對(duì)比結(jié)果:顯然【桌面圖標(biāo)打開】時(shí)比【安裝apk直接打開】少了一條pkg,多了一條bnds(pkg即Package,bnds即SourceBounds)

    • 猜測:懷疑bug的原因是pkg導(dǎo)致椎椰,那就模擬下唄:(紅波浪線是因?yàn)锧IntDef)

      setClickListener(findViewById(R.id.button),(view)->{//模擬直接打開
          Intent intent = new Intent(Intent.ACTION_MAIN);//act
          intent.addCategory(Intent.CATEGORY_LAUNCHER);//cat
          intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));//flg 0x10000000
          intent.setPackage("com.yooking.test");//pkg
          ComponentName cmp = ComponentName.unflattenFromString("com.yooking.test/.SplashActivity");
          intent.setComponent(new ComponentName());//cmp
          startActivity(intent);
      }) 
      
      setClickListener(findViewById(R.id.button),(view)->{//模擬桌面打開
          Intent intent = new Intent(Intent.ACTION_MAIN);//act
          intent.addCategory(Intent.CATEGORY_LAUNCHER);//cat
          intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED));//flg 0x10200000
          ComponentName cmp = ComponentName.unflattenFromString("com.yooking.test/.SplashActivity");
          intent.setComponent(new ComponentName());//cmp
          startActivity(intent);
      })
      
    • 結(jié)論:模擬結(jié)果與猜測一致礼烈,帶有pkg參數(shù)的意圖跳轉(zhuǎn)時(shí),點(diǎn)home鍵確實(shí)會(huì)出現(xiàn)app重啟現(xiàn)象

解決BUG

  1. bug的成因分析出來了狼电,如何解決?

    根據(jù)前述分析,我們認(rèn)為BUG出現(xiàn)的原因是Android手機(jī)下載app后直接打開時(shí)所傳參數(shù)比桌面圖標(biāo)打開多了一個(gè)pkg導(dǎo)致的疾就。

  2. 解決方案1:莽過去!
    什么叫莽過去艺蝴?就是直截了當(dāng)猬腰,干脆利落,你不是多傳了個(gè)pkg嗎吴趴,那我把你關(guān)了漆诽,再自己啟動(dòng)一個(gè)不就行了?

    boolean firstStart
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        if(firstStart){
            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_LAUNCHER);
            intent.setComponent(new ComponentName(BuildConfig.APPLICATION_ID,SplashActivity.class));
            intent.addFlags(0x10200000);
            startActivity(intent);
            finish();
        }
    }
    

    just look 挺 perfect 的...事實(shí)上嘛...就當(dāng)無事發(fā)生好了...
    原因:帶pkg和不帶pkg被認(rèn)為非同一應(yīng)用锣枝,故而繼續(xù)啟動(dòng)了Splash頁面

  3. 解決方案2:分析BUG現(xiàn)象厢拭,根據(jù)現(xiàn)象解決問題
    目標(biāo)是什么:App啟動(dòng)不重啟
    不重啟意味著什么:點(diǎn)擊Home鍵時(shí)的Activity回歸任務(wù)棧頂部

    任務(wù)棧:GET_TASKS權(quán)限于Android L廢棄,REAL_GET_TASKS權(quán)限僅限系統(tǒng)應(yīng)用有效F踩9!
    因此陨闹,無法在App日志中查看任務(wù)棧信息楞捂。
    任務(wù)棧查看方法:Android Studio 中 Terminal 輸入 adb shell dumpsys activity activities
    

    由于我在SplashActivity中寫了finish方法,可以分別看到:
    #0直接啟動(dòng):

    Running activities (most recent first):
    TaskRecord{ea096c0 #1597 A=[packageName] U=0 StackId=1604 sz=1}
    Run #0: ActivityRecord{e30acd0 u0 [packageName]/[packageName].activity.MainActivity t1597}
    mResumedActivity: ActivityRecord{e30acd0 u0 [packageName]/[packageName].activity.MainActivity t1597}
    mLastPausedActivity: ActivityRecord{f68c709 u0 [packageName]/[packageName].activity.SplashActivity t-1f}
    

    #1點(diǎn)擊Home鍵后趋厉,再次打開寨闹,在Splash頁面時(shí)的任務(wù)棧:

    Running activities (most recent first):
    TaskRecord{ea096c0 #1597 A=[packageName] U=0 StackId=1604 sz=2}
    Run #1: ActivityRecord{433989 u0 [packageName]/[packageName].activity.SplashActivity t1597}
    Run #0: ActivityRecord{e30acd0 u0 [packageName]/[packageName].activity.MainActivity t1597}
    

    兩者對(duì)比,可以看到任務(wù)棧中Splash兩次的id是不同的君账,而main是一致的繁堡。App并非重啟,只是多啟動(dòng)了一次Splash乡数。
    可見:我們只需要消除往后打開時(shí)的Splash頁面即可椭蹄。
    如何做?根據(jù)上述分析净赴,有如下判斷

    在SplashActivity中
    if(SplashActivity在 任務(wù)棧最底部 ){
        //App為正常啟動(dòng)
    }else{
        //App為已經(jīng)啟動(dòng)并且點(diǎn)擊Home鍵后再次打開
        關(guān)閉被錯(cuò)誤打開的SplashActivity
    }
    

    判斷是否為 任務(wù)棧最底部的 源碼:

    /**
     * Return whether this activity is the root of a task.  The root is the
     * first activity in a task.
     *
     * @return True if this is the root activity, else false.
    */
    @Override
    public boolean isTaskRoot() {
        try {
            return ActivityManager.getService().getTaskForActivity(mToken, true) >= 0;
        } catch (RemoteException e) {
            return false;
        }
    }
    

    判斷方法:

    public class SplashActivity extends BaseActivity{
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            if (!this.isTaskRoot()) {//判斷是否為根Activity
                Intent mainIntent = getIntent();
                String action = mainIntent.getAction();
                //判斷是否為啟動(dòng)頁 如果App不會(huì)因?yàn)槠渌蛘{(diào)用該頁面绳矩,可以不寫if語句
                if (mainIntent.hasCategory(Intent.CATEGORY_LAUNCHER) 
                    && Intent.ACTION_MAIN.equals(action)) {
                    finish();
                    return;
                }
            }
        }
    }
    

    這個(gè)代碼應(yīng)該緊隨super.onCreate(savedInstanceState);之后。
    onCreate確保當(dāng)前Activity是正在創(chuàng)建狀態(tài)玖翅,而在setContentView之前翼馆,確保Activity是未渲染的割以,此時(shí)關(guān)閉不會(huì)讓用戶察覺

總結(jié)

  1. 方案二雖然確實(shí)能夠解決Home鍵重啟問題,但是也會(huì)導(dǎo)致App啟動(dòng)速度變慢(有一個(gè)白屏過程)写妥,而這個(gè)問題在App使用360/樂固等加固后拳球,更為嚴(yán)重,這或許是需要進(jìn)一步解決的珍特。

  2. 我在項(xiàng)目中用了取巧的解決方案:迷惑用戶——將白屏替換成啟動(dòng)頁祝峻。為啟動(dòng)頁設(shè)置一個(gè)Theme(僅限啟動(dòng)頁)

    <style name="Splash_Theme" parent="AppTheme_NoActionBar">
        <item name="android:windowBackground">@drawable/splash</item>
    </style>
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市扎筒,隨后出現(xiàn)的幾起案子莱找,更是在濱河造成了極大的恐慌,老刑警劉巖嗜桌,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奥溺,死亡現(xiàn)場離奇詭異,居然都是意外死亡骨宠,警方通過查閱死者的電腦和手機(jī)浮定,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來层亿,“玉大人桦卒,你說我怎么就攤上這事∧溆郑” “怎么了方灾?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長碌更。 經(jīng)常有香客問我裕偿,道長,這世上最難降的妖魔是什么痛单? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任嘿棘,我火速辦了婚禮,結(jié)果婚禮上旭绒,老公的妹妹穿的比我還像新娘蔫巩。我一直安慰自己,他們只是感情好快压,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著垃瞧,像睡著了一般蔫劣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上个从,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天脉幢,我揣著相機(jī)與錄音歪沃,去河邊找鬼。 笑死嫌松,一個(gè)胖子當(dāng)著我的面吹牛沪曙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播萎羔,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼液走,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了贾陷?” 一聲冷哼從身側(cè)響起缘眶,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎髓废,沒想到半個(gè)月后巷懈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡慌洪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年顶燕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冈爹。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡涌攻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出犯助,到底是詐尸還是另有隱情癣漆,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布剂买,位于F島的核電站惠爽,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏瞬哼。R本人自食惡果不足惜婚肆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望坐慰。 院中可真熱鬧较性,春花似錦、人聲如沸结胀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽糟港。三九已至攀操,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間秸抚,已是汗流浹背速和。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國打工歹垫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人颠放。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓排惨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親碰凶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子暮芭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359