Skip to content

Commit bd65dda

Browse files
committed
fix: ITaskStackListener AbstractMethodError (#941)
1 parent b522415 commit bd65dda

File tree

4 files changed

+45
-478
lines changed

4 files changed

+45
-478
lines changed

app/src/main/kotlin/li/songe/gkd/shizuku/ActivityTaskManager.kt

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,11 @@ private val taskListener by lazy {
124124

125125
val activityTaskManagerFlow by lazy<StateFlow<SafeActivityTaskManager?>> {
126126
val stateFlow = MutableStateFlow<SafeActivityTaskManager?>(null)
127-
if (TaskListener.unadaptedMethodList.isEmpty()) {
128-
appScope.launchTry(Dispatchers.IO) {
129-
shizukuActivityUsedFlow.collect {
130-
stateFlow.value?.unregisterTaskStackListener(taskListener)
131-
stateFlow.value = if (it) newActivityTaskManager() else null
132-
stateFlow.value?.registerTaskStackListener(taskListener)
133-
}
127+
appScope.launchTry(Dispatchers.IO) {
128+
shizukuActivityUsedFlow.collect {
129+
stateFlow.value?.unregisterTaskStackListener(taskListener)
130+
stateFlow.value = if (it) newActivityTaskManager() else null
131+
stateFlow.value?.registerTaskStackListener(taskListener)
134132
}
135133
}
136134
stateFlow
Lines changed: 9 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -1,161 +1,19 @@
11
package li.songe.gkd.shizuku
22

3-
import android.app.ActivityManager
4-
import android.app.ActivityManagerHidden
53
import android.app.ITaskStackListener
6-
import android.content.ComponentName
7-
import android.os.IBinder
8-
import android.window.TaskSnapshot
9-
import java.lang.reflect.Modifier
10-
import kotlin.reflect.full.declaredFunctions
4+
import android.os.Parcel
5+
116

127
class TaskListener(private val onStackChanged: () -> Unit) : ITaskStackListener.Stub() {
13-
companion object {
14-
// https://github.com/gkd-kit/gkd/issues/941
15-
val unadaptedMethodList by lazy {
16-
val allAdaptedMethodList = TaskListener::class.declaredFunctions
17-
val currentSystemMethodList =
18-
Class.forName("android.app.ITaskStackListener").methods.filter {
19-
it.returnType == Void.TYPE && !it.isDefault && Modifier.isAbstract(it.modifiers) && !Modifier.isStatic(
20-
it.modifiers
21-
)
22-
}
23-
currentSystemMethodList.filterNot { v1 ->
24-
allAdaptedMethodList.any { v2 -> v1.name == v2.name && v1.parameters.size == v2.parameters.size - 1 }
25-
}
8+
9+
public override fun onTransact(code: Int, data: Parcel, reply: Parcel?, flags: Int): Boolean {
10+
// https://github.com/gkd-kit/gkd/issues/941#issuecomment-2784035441
11+
return try {
12+
super.onTransact(code, data, reply, flags)
13+
} catch (_: Throwable) {
14+
true
2615
}
2716
}
2817

2918
override fun onTaskStackChanged() = onStackChanged()
30-
31-
override fun onActivityPinned(
32-
packageName: String?,
33-
userId: Int,
34-
taskId: Int,
35-
stackId: Int
36-
) {
37-
}
38-
39-
override fun onActivityUnpinned() {
40-
}
41-
42-
override fun onPinnedActivityRestartAttempt(clearedTask: Boolean) {
43-
}
44-
45-
override fun onPinnedStackAnimationStarted() {
46-
}
47-
48-
override fun onPinnedStackAnimationEnded() {
49-
}
50-
51-
override fun onActivityForcedResizable(
52-
packageName: String?,
53-
taskId: Int,
54-
reason: Int
55-
) {
56-
}
57-
58-
override fun onActivityDismissingDockedStack() {
59-
}
60-
61-
override fun onActivityLaunchOnSecondaryDisplayFailed(
62-
taskInfo: ActivityManager.RunningTaskInfo?,
63-
requestedDisplayId: Int
64-
) {
65-
}
66-
67-
override fun onActivityLaunchOnSecondaryDisplayRerouted(
68-
taskInfo: ActivityManager.RunningTaskInfo?,
69-
requestedDisplayId: Int
70-
) {
71-
}
72-
73-
override fun onTaskCreated(taskId: Int, componentName: ComponentName?) {
74-
}
75-
76-
override fun onTaskRemoved(taskId: Int) {
77-
}
78-
79-
override fun onTaskMovedToFront(taskInfo: ActivityManager.RunningTaskInfo?) {}
80-
81-
override fun onTaskDescriptionChanged(taskInfo: ActivityManager.RunningTaskInfo?) {}
82-
83-
override fun onActivityRequestedOrientationChanged(
84-
taskId: Int,
85-
requestedOrientation: Int
86-
) {
87-
}
88-
89-
override fun onTaskRemovalStarted(taskInfo: ActivityManager.RunningTaskInfo?) {}
90-
91-
override fun onTaskProfileLocked(taskId: Int, userId: Int) {
92-
}
93-
94-
override fun onTaskSnapshotChanged(
95-
taskId: Int,
96-
snapshot: ActivityManagerHidden.TaskSnapshot?
97-
) {
98-
}
99-
100-
override fun onSizeCompatModeActivityChanged(
101-
displayId: Int,
102-
activityToken: IBinder?
103-
) {
104-
}
105-
106-
override fun onBackPressedOnTaskRoot(taskInfo: ActivityManager.RunningTaskInfo?) {}
107-
108-
override fun onTaskDisplayChanged(taskId: Int, newDisplayId: Int) {}
109-
110-
override fun onActivityRestartAttempt(
111-
task: ActivityManager.RunningTaskInfo?,
112-
homeTaskVisible: Boolean,
113-
clearedTask: Boolean,
114-
wasVisible: Boolean
115-
) {
116-
}
117-
118-
override fun onSingleTaskDisplayDrawn(displayId: Int) {
119-
}
120-
121-
override fun onSingleTaskDisplayEmpty(displayId: Int) {
122-
}
123-
124-
override fun onRecentTaskListUpdated() {}
125-
126-
override fun onRecentTaskListFrozenChanged(frozen: Boolean) {}
127-
128-
override fun onTaskFocusChanged(taskId: Int, focused: Boolean) {}
129-
130-
override fun onTaskRequestedOrientationChanged(
131-
taskId: Int,
132-
requestedOrientation: Int
133-
) {
134-
}
135-
136-
override fun onActivityRotation(displayId: Int) {}
137-
138-
override fun onTaskSnapshotChanged(taskId: Int, snapshot: TaskSnapshot?) {}
139-
140-
override fun onTaskMovedToBack(taskInfo: ActivityManager.RunningTaskInfo?) {}
141-
142-
override fun onLockTaskModeChanged(mode: Int) {}
143-
override fun onActivityDismissingSplitTask(str: String?) {}
144-
145-
override fun onOccludeChangeNotice(
146-
componentName: ComponentName?,
147-
z: Boolean
148-
) {
149-
}
150-
151-
override fun onTaskbarIconVisibleChangeRequest(
152-
componentName: ComponentName?,
153-
z: Boolean
154-
) {
155-
}
156-
157-
override fun onTaskWindowingModeChanged(i: Int) {}
158-
override fun onRecentTaskRemovedForAddTask(taskId: Int) {}
159-
override fun onActivityDismissingDockedTask() {}
160-
override fun onTaskSnapshotInvalidated(taskId: Int) {}
16119
}

app/src/main/kotlin/li/songe/gkd/ui/AdvancedPage.kt

Lines changed: 31 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,13 @@ import com.blankj.utilcode.util.LogUtils
5656
import com.dylanc.activityresult.launcher.launchForResult
5757
import com.ramcosta.composedestinations.annotation.Destination
5858
import com.ramcosta.composedestinations.annotation.RootGraph
59-
import com.ramcosta.composedestinations.generated.destinations.AboutPageDestination
6059
import com.ramcosta.composedestinations.generated.destinations.ActivityLogPageDestination
6160
import com.ramcosta.composedestinations.generated.destinations.SnapshotPageDestination
6261
import com.ramcosta.composedestinations.utils.toDestinationsNavigator
6362
import kotlinx.coroutines.Dispatchers
6463
import kotlinx.coroutines.flow.update
64+
import kotlinx.coroutines.sync.Mutex
65+
import kotlinx.coroutines.sync.withLock
6566
import li.songe.gkd.MainActivity
6667
import li.songe.gkd.appScope
6768
import li.songe.gkd.debug.FloatingService
@@ -71,7 +72,6 @@ import li.songe.gkd.permission.canDrawOverlaysState
7172
import li.songe.gkd.permission.notificationState
7273
import li.songe.gkd.permission.requiredPermission
7374
import li.songe.gkd.permission.shizukuOkState
74-
import li.songe.gkd.shizuku.TaskListener
7575
import li.songe.gkd.shizuku.shizukuCheckActivity
7676
import li.songe.gkd.shizuku.shizukuCheckUserService
7777
import li.songe.gkd.shizuku.shizukuCheckWorkProfile
@@ -470,10 +470,10 @@ fun AdvancedPage() {
470470

471471
}
472472

473+
private val checkShizukuMutex by lazy { Mutex() }
474+
473475
@Composable
474476
private fun ShizukuFragment(enabled: Boolean = true) {
475-
val mainVm = LocalMainViewModel.current
476-
val navController = LocalNavController.current
477477
val shizukuStore by shizukuStoreFlow.collectAsState()
478478
TextSwitch(
479479
title = "界面识别",
@@ -483,34 +483,17 @@ private fun ShizukuFragment(enabled: Boolean = true) {
483483
checked = shizukuStore.enableActivity,
484484
enabled = enabled,
485485
onCheckedChange = appScope.launchAsFn<Boolean>(Dispatchers.IO) {
486-
if (it) {
487-
toast("检测中")
488-
if (!shizukuCheckActivity()) {
489-
toast("检测失败,无法使用")
490-
return@launchAsFn
491-
}
492-
if (TaskListener.unadaptedMethodList.isNotEmpty()) {
493-
LogUtils.d(
494-
"TaskListener.unadaptedMethodList",
495-
*TaskListener.unadaptedMethodList.map {
496-
"${it.name}(${it.parameters.joinToString { p -> "${p.name}:${p.type}" }}):${it.returnType}"
497-
}.toTypedArray()
498-
)
499-
mainVm.dialogFlow.updateDialogOptions(
500-
onDismissRequest = {},
501-
title = "适配提示",
502-
text = "检测到未适配的 API, 已自动禁用部分功能, 请带上日志反馈",
503-
dismissText = "取消",
504-
confirmText = "去反馈",
505-
confirmAction = {
506-
mainVm.dialogFlow.value = null
507-
navController.toDestinationsNavigator().navigate(AboutPageDestination)
508-
}
509-
)
486+
checkShizukuMutex.withLock {
487+
if (it) {
488+
toast("检测中")
489+
if (!shizukuCheckActivity()) {
490+
toast("检测失败,无法使用")
491+
return@launchAsFn
492+
}
493+
toast("已启用")
510494
}
511-
toast("已启用")
495+
shizukuStoreFlow.update { s -> s.copy(enableActivity = it) }
512496
}
513-
shizukuStoreFlow.update { s -> s.copy(enableActivity = it) }
514497
})
515498

516499
TextSwitch(
@@ -521,15 +504,17 @@ private fun ShizukuFragment(enabled: Boolean = true) {
521504
checked = shizukuStore.enableTapClick,
522505
enabled = enabled,
523506
onCheckedChange = appScope.launchAsFn<Boolean>(Dispatchers.IO) {
524-
if (it) {
525-
toast("检测中")
526-
if (!shizukuCheckUserService()) {
527-
toast("检测失败,无法使用")
528-
return@launchAsFn
507+
checkShizukuMutex.withLock {
508+
if (it) {
509+
toast("检测中")
510+
if (!shizukuCheckUserService()) {
511+
toast("检测失败,无法使用")
512+
return@launchAsFn
513+
}
514+
toast("已启用")
529515
}
530-
toast("已启用")
516+
shizukuStoreFlow.update { s -> s.copy(enableTapClick = it) }
531517
}
532-
shizukuStoreFlow.update { s -> s.copy(enableTapClick = it) }
533518
})
534519

535520

@@ -541,15 +526,17 @@ private fun ShizukuFragment(enabled: Boolean = true) {
541526
checked = shizukuStore.enableWorkProfile,
542527
enabled = enabled,
543528
onCheckedChange = appScope.launchAsFn<Boolean>(Dispatchers.IO) {
544-
if (it) {
545-
toast("检测中")
546-
if (!shizukuCheckWorkProfile()) {
547-
toast("检测失败,无法使用")
548-
return@launchAsFn
529+
checkShizukuMutex.withLock {
530+
if (it) {
531+
toast("检测中")
532+
if (!shizukuCheckWorkProfile()) {
533+
toast("检测失败,无法使用")
534+
return@launchAsFn
535+
}
536+
toast("已启用")
549537
}
550-
toast("已启用")
538+
shizukuStoreFlow.update { s -> s.copy(enableWorkProfile = it) }
551539
}
552-
shizukuStoreFlow.update { s -> s.copy(enableWorkProfile = it) }
553540
})
554541

555542
}

0 commit comments

Comments
 (0)