Skip to content

Commit 1b46ca7

Browse files
committed
Update ActivityTaskTracker
1 parent 1c754fe commit 1b46ca7

File tree

7 files changed

+478
-121
lines changed

7 files changed

+478
-121
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package me.ycdev.android.lib.common.activity
2+
3+
import android.content.ComponentName
4+
import android.content.Context
5+
import android.content.pm.ActivityInfo
6+
import android.content.pm.PackageManager
7+
import androidx.annotation.VisibleForTesting
8+
import java.util.concurrent.ConcurrentHashMap
9+
10+
data class ActivityMeta(
11+
val componentName: ComponentName,
12+
val taskAffinity: String,
13+
val launchMode: Int,
14+
val allowTaskReparenting: Boolean
15+
) {
16+
companion object {
17+
private val cache = ConcurrentHashMap<String, ActivityMeta>()
18+
19+
/**
20+
* @throws PackageManager.NameNotFoundException if component not found in the system
21+
*/
22+
fun get(context: Context, activity: ComponentName): ActivityMeta {
23+
val key = activity.flattenToShortString()
24+
var meta = cache[key]
25+
if (meta != null) {
26+
return meta
27+
}
28+
29+
val info = context.packageManager.getActivityInfo(activity, 0)
30+
val taskAffinity = info.taskAffinity ?: context.applicationInfo.taskAffinity
31+
val allowTaskReparenting = (info.flags and ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) > 0
32+
meta = ActivityMeta(activity, taskAffinity, info.launchMode, allowTaskReparenting)
33+
cache[key] = meta
34+
return meta
35+
}
36+
37+
@VisibleForTesting
38+
internal fun initCache(vararg metas: ActivityMeta) {
39+
cache.clear()
40+
metas.forEach {
41+
val key = it.componentName.flattenToShortString()
42+
cache[key] = it
43+
}
44+
}
45+
}
46+
}

baseLib/src/main/java/me/ycdev/android/lib/common/activity/ActivityInfo.kt renamed to baseLib/src/main/java/me/ycdev/android/lib/common/activity/ActivityRunningState.kt

+5-4
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ package me.ycdev.android.lib.common.activity
22

33
import android.content.ComponentName
44

5-
data class ActivityInfo(
5+
data class ActivityRunningState(
66
val componentName: ComponentName,
7-
val taskId: Int,
7+
val hashCode: Int,
8+
var taskId: Int,
89
var state: State = State.None
910
) {
10-
fun makeCopy(): ActivityInfo {
11-
val cloned = ActivityInfo(componentName, taskId)
11+
fun makeCopy(): ActivityRunningState {
12+
val cloned = ActivityRunningState(componentName, hashCode, taskId)
1213
cloned.state = state
1314
return cloned
1415
}

baseLib/src/main/java/me/ycdev/android/lib/common/activity/ActivityTask.kt

+16-14
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,40 @@ package me.ycdev.android.lib.common.activity
33
import android.content.ComponentName
44
import java.util.Stack
55

6-
class ActivityTask(val taskId: Int) {
7-
private val activities = arrayListOf<ActivityInfo>()
6+
class ActivityTask(val taskId: Int, val taskAffinity: String) {
7+
private val activities = arrayListOf<ActivityRunningState>()
88

9-
internal fun addActivity(activity: ActivityInfo) {
9+
internal fun addActivity(activity: ActivityRunningState) {
1010
if (activity.taskId != taskId) {
1111
throw RuntimeException("Activity taskId[${activity.taskId}] != AppTask[$taskId]")
1212
}
1313
activities.add(activity)
1414
}
1515

16-
internal fun popActivity(componentName: ComponentName): ActivityInfo {
16+
internal fun popActivity(componentName: ComponentName, hashCode: Int): ActivityRunningState {
1717
val it = activities.asReversed().iterator()
1818
while (it.hasNext()) {
1919
val activity = it.next()
20-
if (activity.componentName == componentName) {
20+
if (activity.componentName == componentName && activity.hashCode == hashCode) {
2121
it.remove()
2222
return activity
2323
}
2424
}
25-
throw RuntimeException("Cannot find $componentName")
25+
val hashHex = Integer.toHexString(hashCode)
26+
throw RuntimeException("Cannot find $componentName@$hashHex")
2627
}
2728

28-
fun lastActivity(componentName: ComponentName): ActivityInfo {
29+
fun lastActivity(componentName: ComponentName, hashCode: Int): ActivityRunningState {
2930
activities.asReversed().forEach {
30-
if (it.componentName == componentName) {
31+
if (it.componentName == componentName && it.hashCode == hashCode) {
3132
return it
3233
}
3334
}
34-
throw RuntimeException("Cannot find $componentName")
35+
val hashHex = Integer.toHexString(hashCode)
36+
throw RuntimeException("Cannot find $componentName@$hashHex")
3537
}
3638

37-
fun topActivity(): ActivityInfo {
39+
fun topActivity(): ActivityRunningState {
3840
if (activities.isEmpty()) {
3941
throw RuntimeException("The task is empty. Cannot get the top Activity.")
4042
}
@@ -44,8 +46,8 @@ class ActivityTask(val taskId: Int) {
4446
/**
4547
* @return The last Activity in returned list is the top Activity
4648
*/
47-
fun getActivityStack(): Stack<ActivityInfo> {
48-
val stack = Stack<ActivityInfo>()
49+
fun getActivityStack(): Stack<ActivityRunningState> {
50+
val stack = Stack<ActivityRunningState>()
4951
activities.forEach {
5052
stack.push(it)
5153
}
@@ -55,14 +57,14 @@ class ActivityTask(val taskId: Int) {
5557
fun isEmpty() = activities.isEmpty()
5658

5759
fun makeCopy(): ActivityTask {
58-
val task = ActivityTask(taskId)
60+
val task = ActivityTask(taskId, taskAffinity)
5961
activities.forEach {
6062
task.activities.add(it.makeCopy())
6163
}
6264
return task
6365
}
6466

6567
override fun toString(): String {
66-
return "AppTask[taskId=$taskId, activities=$activities]"
68+
return "AppTask[taskId=$taskId, taskAffinity=$taskAffinity, activities=$activities]"
6769
}
6870
}

0 commit comments

Comments
 (0)