android:allowTaskReparenting
翻译过来的一下是允许重新找父母(允许迁移任务栈),如果一个Activity设置了这个属性,其他应用启动这个activity的时候分两种情况处理:
1.这个activity对应的进程已经启动了:则这个activity直接附属到自己所对应的进程的应用栈上
2.这个activity对应的进程没有启动:则这个activity先直接附属到启动它的应用的应用栈上,当activity对应的进程启动后,则会主动迁移到activity对应的进程。
有一个比喻非常之形象:
你捡到一条狗,在家里喂养几天觉得不错,当自己家的了;但是突然有一天他的主人找上门来了,小狗还是乖乖和主人走了。。。
这条狗就是带有allowTaskReparenting属性的activity
demo1(com.cn.demo1)有两个activity: MainActivity,AllowTaskReparentingActivity, AllowTaskReparentingActivity设置了android:allowTaskReparenting="true"属性
demo2(com.cn.demo2)有一个activity:MainActivity
安装demo1、demo2之后,先启动demo2,在demo2中demo1中的AllowTaskReparentingActivity,使用dumpsys activity activities查看堆栈情况:
Running activities (most recent first):
TaskRecord{4497c288 #566 A=com.cn.demo2 U=0 sz=2}
Run #2: ActivityRecord{44664828 u0 com.cn.demo1/.AllowTaskReparentingActivity t566}
Run #1: ActivityRecord{4497bf70 u0 com.cn.demo2/.MainActivity t566}
TaskRecord{4321d2d0 #83 A=com.android.packageinstaller U=0 sz=1}
Run #0: ActivityRecord{4409df10 u0 com.android.packageinstaller/.PackageInstallerActivity t83}
任务栈com.cn.demo2有两个Activity,一个是demo2的MainActivity,一个是demo1的AllowTaskReparentingActivity,
AllowTaskReparentingActivity在上,MainActivity在下
按Home退出到后台,堆栈状态不变,再点击demo2图标打开demo2,查看堆栈情况
Running activities (most recent first):
TaskRecord{4497c288 #566 A=com.cn.demo2 U=0 sz=1}
Run #2: ActivityRecord{4497bf70 u0 com.cn.demo2/.MainActivity t566}
TaskRecord{43aa4278 #564 A=com.cn.demo1 U=0 sz=2}
Run #1: ActivityRecord{44664828 u0 com.cn.demo1/.AllowTaskReparentingActivity t564}
TaskRecord{4321d2d0 #83 A=com.android.packageinstaller U=0 sz=1}
Run #0: ActivityRecord{4409df10 u0 com.android.packageinstaller/.PackageInstallerActivity t83}
OK,重新点击图标的时候com.cn.demo2/.MainActivity和com.cn.demo1/.AllowTaskReparentingActivity已经分离开了,这就是 android:allowTaskReparenting=true起到的作用,如果为false,任务栈的状态时不会变(分离)的。
如果用demo2启动com.cn.demo1/.AllowTaskReparentingActivity,然后Home退出到桌面,然后再点击demo1图标看一下堆栈状态
Running activities (most recent first):
TaskRecord{442f3588 #585 A=com.cn.demo1 U=0 sz=2}
Run #2: ActivityRecord{43d9f308 u0 com.cn.demo1/.AllowTaskReparentingActivity t585}
TaskRecord{448abf70 #584 A=com.cn.demo2 U=0 sz=1}
Run #1: ActivityRecord{43d42230 u0 com.cn.demo2/.MainActivity t584}
TaskRecord{4321d2d0 #83 A=com.android.packageinstaller U=0 sz=1}
Run #0: ActivityRecord{4409df10 u0 com.android.packageinstaller/.PackageInstallerActivity t83}
效果是一样的,我们产看一下编号#585堆栈的activity情况如下:
Recent tasks:
* Recent #0: TaskRecord{442f3588 #585 A=com.cn.demo1 U=0 sz=2}
numActivities=2 rootWasReset=true userId=0 mTaskType=0 numFullscreen=2 mOnTopOfHome=true
affinity=com.cn.demo1
intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.cn.demo1/.MainActivity}
realActivity=com.cn.demo1/.MainActivity
Activities=[ActivityRecord{43e2c298 u0 com.cn.demo1/.MainActivity t585}, ActivityRecord{43d9f308 u0 com.cn.demo1/.AllowTaskReparentingActivity t585}]
askedCompatMode=false
lastThumbnail=null lastDescription=null
lastActiveTime=1704769727 (inactive for 6s)
变量Activities里面有两个activity:Activities=[ActivityRecord{43e2c298 u0 com.cn.demo1/.MainActivity t585}, ActivityRecord{43d9f308 u0 com.cn.demo1/.AllowTaskReparentingActivity t585}]其中MainActivity在下,AllowTaskReparentingActivity在上,可以猜测是demo1先启动的MainActivity,再将AllowTaskReparentingActivity从栈com.cn.demo2迁移到栈com.cn.demo1上。
android:allowTaskReparenting在提供页面给第三方调用的时候能够被用到。
android:clearTaskOnLaunch
这个属性用来标记是否从task清除除根Activity之外的所有的Activity,“true”表示清除,“false”表示不清除,默认为“false”。同样,这个属性也只对根Activity起作用,其他的Activity都会被忽略。
如果设置了这个属性为“true”,每次用户重新启动这个应用时,都只会看到根Activity,task中的其他Activity都会被清除出栈。如果我们的应用中引用到了其他应用的Activity,这些Activity设置了allowTaskReparenting属性为“true”,则它们会被重新宿主到有共同affinity的task中。
启动A后,再点击按钮启动B,点击home键,返回到home screen 。(A、B属于同一个栈)
a.长按home键,在recent中点击应用图标,显示B界面。
b.再点击应用图标,显示A界面
根据这一个表现,则说明从launch点击图标进入应用和长按Home键从最近列表进入应用是有区别的,区别如下:
1.点击Launcher里面的图标,本质上就是调用的startActivity,action是android.intent.action.MAIN,category是android.intent.category.LAUNCHER,flag是FLAG_ACTIVITY_RESET_TASK_IF_NEEDED & FLAG_ACTIVITY_NEW_TASK,component是你的A。
2.从RecentActivity进入,源码里面对flag做了这种处理:intent.setFlags((intent.getFlags()&~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) | Intent.FLAG_ACTIVITY_NEW_TASK);去掉了flag里面FLAG_ACTIVITY_RESET_TASK_IF_NEEDED那一位标志。
区别就在于FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,一旦用户设置了FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,那么就会执行resetTaskIfNeeded来清理task,很明显这种情况下从Home进入的时候清理了Task,而从最近列表进入则resume顶部的activity。
android:alwaysRetainTaskState
如果用户在一定时间内不再访问Task,比如说30分钟,那么系统有可能会清楚Task中的状态(只保留root activity)。设置此属性为"true"可以避免这种情况
android:finishOnTaskLaunch
当Task再次被启动是,设置android:finishOnTaskLaunch为true,该Activity就销毁,我还不知道怎么让Task再次启动