关于android:taskAffinity这个属性在日常开发中不一定能用到,但是在某些特殊的场景下就会发挥很好的作用。

在介绍这个属性前先要了解一些关于任务和返回栈的概念。
任务是指在执行特定作业时与用户交互的一系列 Activity。 这些 Activity 按照各自的打开顺序排列在堆栈(即“返回栈”)中。
根据android官网中的解释:

android:taskAffinity

The task that the activity has an affinity for. Activities with the same affinity conceptually belong to the same task (to the same “application” from the user’s perspective). The affinity of a task is determined by the affinity of its root activity.
The affinity determines two things — the task that the activity is re-parented to (see the allowTaskReparenting attribute) and the task that will house the activity when it is launched with the FLAG_ACTIVITY_NEW_TASK flag.

By default, all activities in an application have the same affinity. You can set this attribute to group them differently, and even place activities defined in different applications within the same task. To specify that the activity does not have an affinity for any task, set it to an empty string.

If this attribute is not set, the activity inherits the affinity set for the application (see the element’s taskAffinity attribute). The name of the default affinity for an application is the package name set by the element.

前面啰嗦的解释已经说过了。下面来介绍我在项目中的应用场景。

在开发的时候难免会遇到这种需求,需要对外提供接口以供其他应该调用,我在最近的项目中对外提供aidl,别的同事通过里面的接口调用我的功能,在实现相关功能的同时还需要有界面展示。这就是大概功能。

我这通过对话框的形式来展现一些控制功能,对话框是依赖activity的,所以我以一个透明的activity作为依托在调用我这功能的时候先启动该透明的activity,然后在activity中启动对话框,在对话框销毁的时候finish()掉activity。但是这个恰恰买下了隐患。

当同事用另外一个应用调用我的接口时正常没有问题。但是如果启动了我的应用然后按home,再调用我的接口,在dialog结束后我的应用会被调起。

究其原因就是因为这个透明的activity和我其他应用的activity使用的是同一个taskAffinity(Activities with the same affinity conceptually belong to the same task)这样一来在dialog销毁后销毁透明activity这样之前被home到后台的界面就显示了出来。

如果想更加直观的看到这个现象可以adb shell dumpsys activity activities > c:a.txt将当前task还有stack打印出来,可以很直观的看到这个现象。会发现透明activity和我的应用的主界面是同属一个Task的,这样根据

Android 通过taskId获取task信息 task for android_解决方案

可以看出出现该问题的原因在此。

解决方案很简单就是对这个透明的activity使用自定的taskAffinity,自己写一个就ok了。除了这种解决方案还可以通过singleInstance的launch mode来解决此问题。