• 解决Android App 每启动一个Activity就看上去多启动一个应用/进程的问题


    背景

    出现一个很神奇的问题,集成了一个library依赖后,每启动一个FLAG_ACTIVITY_NEW_TASK标志位的Activity就会在任务管理器中多一个"应用"。
    如果去除这个library依赖,则无论启动多少个带FLAG_ACTIVITY_NEW_TASK标志位的Activity,任务管理器中永远都只有这一个"应用"。

    重现步骤

    我们依赖了该library库,然后启动了3个带FLAG_ACTIVITY_NEW_TASK标志位的activityMainActivity->SecondActivity->ThirdActivity

    val intent = Intent(MainActivity@ this, SecondActivity::class.java)
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    startActivity(intent)
    
    • 1
    • 2
    • 3

    我们打开任务管理器,可以看到如下效果
    在这里插入图片描述
    如果,我们去除该library的依赖,打开任务管理器,就只会有一个"应用"。
    或者去除启动Activity时的FLAG_ACTIVITY_NEW_TASK标志,也只会有一个应用
    在这里插入图片描述

    原因

    后来,排查后,发现和taskAffinity有关。

    原来,在该library中,我们在AndroidManifest.xmlApplication节点 添加了一个android:taskAffinity="",导致了这个问题。
    去掉这个值就不会有这个问题了。

    taskAffinity

    taskAffinity我们平时很少去用它,它的作用是什么呢 ?

    查阅了资料可知
    是用于在启动activity时,指定activity放入哪个task (指定想要的任务栈)

    官网文档上关于taskAffinity的说明 : https://developer.android.google.cn/guide/topics/manifest/activity-element#lmode
    在这里插入图片描述
    我们来做下试验

    试验一

    我们保留android:taskAffinity="",启动了3个带FLAG_ACTIVITY_NEW_TASK标志位的activity,MainActivity->SecondActivity->ThirdActivity,可以看到任务管理器里有3个"应用"
    在这里插入图片描述
    我们使用adb命令,查看下当前Activity栈的信息

    adb shell  dumpsys activity activities
    
    • 1

    我们搜索Stack #,可以看到如下信息

      Stack #384: type=standard mode=fullscreen
      isSleeping=false
      mBounds=Rect(0, 0 - 0, 0)
        mLastPausedActivity: ActivityRecord{18aa8f u0 com.heiko.mytest0614/.ThirdActivity t384}
        * Task{812611c #384 visible=true type=standard mode=fullscreen translucent=true I=com.heiko.mytest0614/.ThirdActivity U=0 StackId=384 sz=1}
          ...省略...
    	  taskAffinity=null
    	  ...省略...
    
      Stack #383: type=standard mode=fullscreen
      isSleeping=false
      mBounds=Rect(0, 0 - 0, 0)
        mLastPausedActivity: ActivityRecord{84c8851 u0 com.heiko.mytest0614/.SecondActivity t383}
        * Task{9c4e8b6 #383 visible=true type=standard mode=fullscreen translucent=true I=com.heiko.mytest0614/.SecondActivity U=0 StackId=383 sz=1}
          ...省略...
    	  taskAffinity=null
    	  ...省略...
    
      Stack #382: type=standard mode=fullscreen
      isSleeping=false
      mBounds=Rect(0, 0 - 0, 0)
        mLastPausedActivity: ActivityRecord{c88411e u0 com.heiko.mytest0614/.MainActivity t382}
        * Task{50f0dff #382 visible=true type=standard mode=fullscreen translucent=true I=com.heiko.mytest0614/.MainActivity U=0 StackId=382 sz=1}
    	  ...省略...
          taskAffinity=null
    	  ...省略...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    com.heiko.mytestApp项目,拥有3个任务栈,且taskAffinity都是null

    试验二

    我们去除android:taskAffinity="",启动了3个带FLAG_ACTIVITY_NEW_TASK标志位的activity,MainActivity->SecondActivity->ThirdActivity,可以看到任务管理器里有1个"应用"
    在这里插入图片描述
    我们使用adb命令,查看下当前Activity栈的信息

    adb shell  dumpsys activity activities
    
    • 1

    我们搜索Stack #,可以看到如下信息

    ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
    Display #0 (activities from top to bottom):
      Stack #424: type=standard mode=fullscreen
      isSleeping=false
      mBounds=Rect(0, 0 - 0, 0)
        mResumedActivity: ActivityRecord{66c8f u0 com.heiko.mytest0614/.ThirdActivity t424}
        mLastPausedActivity: ActivityRecord{66c8f u0 com.heiko.mytest0614/.ThirdActivity t424}
        * Task{813f21d #424 visible=true type=standard mode=fullscreen translucent=true A=10314:com.heiko.mytest0614 U=0 StackId=424 sz=3}
          ...省略
     supportsSplitScreenWindowingMode=true      lastActiveTime=1806671486 (inactive for 7s)
     pcFlags 0      * Hist #2: ActivityRecord{66c8f u0 com.heiko.mytest0614/.ThirdActivity t424}
              packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
              ...省略...
              taskAffinity=10314:com.heiko.mytest0614
              ...省略...
          * Hist #1: ActivityRecord{7a80a7 u0 com.heiko.mytest0614/.SecondActivity t424}
              packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
              ...省略...
              taskAffinity=10314:com.heiko.mytest0614
              ...省略...
          * Hist #0: ActivityRecord{870bb65 u0 com.heiko.mytest0614/.MainActivity t424}
              packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
              ...省略...
              taskAffinity=10314:com.heiko.mytest0614
              ...省略...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    com.heiko.mytestApp项目,拥有1个任务栈,这个栈里有三个ActivityRecord,且taskAffinity都是10314:com.heiko.mytest0614

    试验三

    我们去除android:taskAffinity="",ThirdActivity的taskAffinity设置为com.heiko.third,启动了3个带FLAG_ACTIVITY_NEW_TASK标志位的activity,MainActivity->SecondActivity->ThirdActivity,可以看到任务管理器里有2个"应用"

    在这里插入图片描述
    我们使用adb命令,查看下当前Activity栈的信息

    adb shell  dumpsys activity activities
    
    • 1

    我们搜索Stack #,可以看到如下信息

    ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
    Display #0 (activities from top to bottom):
      Stack #437: type=standard mode=fullscreen
      isSleeping=false
      mBounds=Rect(0, 0 - 0, 0)
        mResumedActivity: ActivityRecord{2d1e033 u0 com.heiko.mytest0614/.ThirdActivity t437}
        * Task{1e2ff0 #437 visible=true type=standard mode=fullscreen translucent=true A=10314:com.heiko.third U=0 StackId=437 sz=1}
          ...省略...
     supportsSplitScreenWindowingMode=true      lastActiveTime=1807455552 (inactive for 2s)
     pcFlags 0      * Hist #0: ActivityRecord{2d1e033 u0 com.heiko.mytest0614/.ThirdActivity t437}
              packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
              ...省略...
              taskAffinity=10314:com.heiko.third
              ...省略...
    
      Stack #436: type=standard mode=fullscreen
      isSleeping=false
      mBounds=Rect(0, 0 - 0, 0)
        mLastPausedActivity: ActivityRecord{2197e45 u0 com.heiko.mytest0614/.SecondActivity t436}
        * Task{2384575 #436 visible=true type=standard mode=fullscreen translucent=true A=10314:com.heiko.mytest0614 U=0 StackId=436 sz=2}
          ...省略...
     supportsSplitScreenWindowingMode=true      lastActiveTime=1807455438 (inactive for 2s)
     pcFlags 0      * Hist #1: ActivityRecord{2197e45 u0 com.heiko.mytest0614/.SecondActivity t436}
              packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
              ...省略...
              taskAffinity=10314:com.heiko.mytest0614
              ...省略...
          * Hist #0: ActivityRecord{bfa74ac u0 com.heiko.mytest0614/.MainActivity t436}
              packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
              ...省略...
              taskAffinity=10314:com.heiko.mytest0614
              ...省略...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    com.heiko.mytestApp项目,拥有2个任务栈。
    Stack #437任务栈里有一个ActivityRecordtaskAffinity10314:com.heiko.third
    Stack #436任务栈里有两个ActivityRecordtaskAffinity10314:com.heiko.mytest0614

    试验四

    我们去除android:taskAffinity="",ThirdActivity的launchMode设置为singleInstance,启动了3个带FLAG_ACTIVITY_NEW_TASK标志位的activity,MainActivity->SecondActivity->ThirdActivity,可以看到任务管理器里有1个"应用"
    在这里插入图片描述
    我们使用adb命令,查看下当前Activity栈的信息

    adb shell  dumpsys activity activities
    
    • 1

    我们搜索Stack #,可以看到如下信息

    ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
    Display #0 (activities from top to bottom):
      Stack #434: type=standard mode=fullscreen
      isSleeping=false
      mBounds=Rect(0, 0 - 0, 0)
        mResumedActivity: ActivityRecord{e1a6f04 u0 com.heiko.mytest0614/.ThirdActivity t434}
        * Task{2caced #434 visible=true type=standard mode=fullscreen translucent=true A=10314:com.heiko.mytest0614 U=0 StackId=434 sz=1}
          ...省略...
     pcFlags 0      * Hist #0: ActivityRecord{e1a6f04 u0 com.heiko.mytest0614/.ThirdActivity t434}
              packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
              ...省略...
              taskAffinity=10314:com.heiko.mytest0614
              ...省略...
    		  
    		  
    Stack #433: type=standard mode=fullscreen
      isSleeping=false
      mBounds=Rect(0, 0 - 0, 0)
        mLastPausedActivity: ActivityRecord{8551b41 u0 com.heiko.mytest0614/.SecondActivity t433}
        * Task{4450b31 #433 visible=true type=standard mode=fullscreen translucent=true A=10314:com.heiko.mytest0614 U=0 StackId=433 sz=2}
          ...省略...
     supportsSplitScreenWindowingMode=true      lastActiveTime=1807157149 (inactive for 2s)
     pcFlags 0      * Hist #1: ActivityRecord{8551b41 u0 com.heiko.mytest0614/.SecondActivity t433}
              packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
              ...省略...
              taskAffinity=10314:com.heiko.mytest0614
              ...省略...
          * Hist #0: ActivityRecord{ec9ff65 u0 com.heiko.mytest0614/.MainActivity t433}
              packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
              ...省略...
              taskAffinity=10314:com.heiko.mytest0614
              ...省略...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    com.heiko.mytestApp项目,拥有2个Activity栈,Stack #433任务栈里有两个ActivityRecordStack #434栈中有一个ActivityRecord,且taskAffinity都是10314:com.heiko.mytest0614

    小结

    • taskAffinity的不同,直观的表现是在任务管理器里,以不同的"应用"来体现
    • 微信的每一个小程序,都在任务管理器里单独显示,也是用到了taskAffinity
    • taskAffinity一样的Activity具有同一任务 (从用户的角度来看,则是归属同一"应用")
    • 默认情况下,应用中的所有 Activity的taskAffinity 都一样,为应用的包名
    • 如要要指定 Activity 与任何任务都不一样,需将其设置为空字符串
    • 不仅可以给同一个应用的不同activity设置不同的affinity,也可以给不同应用的activity设置相同的affinity,使它们在用户角度看来好像属于同一个应用
    • 当启动模式设置为 standardsingleTop 时,taskAffinity是不起作用的,待启动的 Activity 会跟随 源Activity 的任务栈,即使你显式声明了不一样的 taskAffinity
    • 当启动模式设置了 singleTask 或者 singleInstance 时,它就会新建任务栈来存储待启动的 Activity 实例
    • 除了 singleTasksingleInstance 以外,FLAG_ACTIVITY_NEW_TASK 也会使 taskAffinity 生效

    在不设置 taskAffinity 的情况下,单独设置 FLAG_ACTIVITY_NEW_TASK 并没有任何意义,不会创建新的任务栈
    FLAG_ACTIVITY_NEW_TASK 更被大家所熟知的用法可能是 从非 Activity 环境启动 Activity 。
    默认情况下,待启动的 Activity 会进入源 Activity 所在的任务栈中。如果是从 非 Activity 环境启动,例如 Service,Broadcast,Application 等,根本不存在与之对应的任务栈,AMS 无从推断该把 Activity 放入哪个任务栈,就会抛出异常 Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag

    对于非 Activity 启动的 Activity需要显示的设置 FLAG_ACTIVITY_NEW_TASK,而singleTask 及 singleInstance 在 AMS 中被预处理后,隐形的设置了 FLAG_ACTIVITY_NEW_TASK,而启动模式是 standard 及 singletTop 的 Activity 不会被设置 FLAG_ACTIVITY_NEW_TASK,除非通过显式的 Intent setFlag() 进行设置。
    FLAG_ACTIVITY_NEW_TASK 这个属性更多的关注点是在 Task,可以认为没有设置 FLAG_ACTIVITY_NEW_TASK 的情况下,taskAffinity 可以不考虑。

    其他

    参考
    Android Task 相关
    任务栈?返回栈?启动模式?
    面试官装x失败之:Activity的启动模式
    taskAffinity的使用
    Android Developer-Activity

  • 相关阅读:
    2022-09-02 第六小组 瞒春 学习笔记
    网课答案公众号搭建-——网课题库接口
    Cesium热力图
    单片机外围电路设计常出现的问题
    全志V3S开发板驱动示例(linux demo驱动开发)
    最小花费——最短路
    第7章 docker存储管理
    MFC Windows 程序设计[259]之扩展Checkbox框(附源码)
    初级软件测试工程师如何涨薪?
    每日一练 bm3 bm2
  • 原文地址:https://blog.csdn.net/EthanCo/article/details/125278904