Skip to content

Commit 702708d

Browse files
authored
Bug fix for Samsung devices (InstallApk, Permissions, ClearInput) (#4)
1 parent f1d9edd commit 702708d

File tree

8 files changed

+96
-50
lines changed

8 files changed

+96
-50
lines changed

src/main/kotlin/androidstudio/tools/missed/features/apk/domain/usecase/installapk/InstallApkUseCaseImpl.kt

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package androidstudio.tools.missed.features.apk.domain.usecase.installapk
22

3+
import androidstudio.tools.missed.manager.adb.command.DeviceAdbCommands
34
import androidstudio.tools.missed.manager.device.DeviceManager
45
import kotlinx.coroutines.flow.flow
56

@@ -8,8 +9,12 @@ class InstallApkUseCaseImpl(
89
) : InstallApkUseCase {
910

1011
override suspend fun invoke(packageFilePath: String) = flow<Result<Boolean>> {
11-
deviceManager.installApk(packageFilePath = packageFilePath).onSuccess {
12-
emit(Result.success(true))
12+
deviceManager.executeShellCommand(DeviceAdbCommands.PackageVerifierEnable()).onSuccess {
13+
deviceManager.installApk(packageFilePath = packageFilePath).onSuccess {
14+
emit(Result.success(true))
15+
}.onFailure {
16+
emit(Result.failure(it))
17+
}
1318
}.onFailure {
1419
emit(Result.failure(it))
1520
}

src/main/kotlin/androidstudio/tools/missed/features/permission/di/PermissionModule.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import org.koin.dsl.module
1818

1919
val permissionModule = module {
2020
single<RestartAppUseCase> { RestartAppUseCaseImpl(get()) }
21-
single<FetchAllPermissionsUseCase> { FetchAllPermissionsUseCaseImpl(get(), get()) }
21+
single<FetchAllPermissionsUseCase> { FetchAllPermissionsUseCaseImpl(get()) }
2222
single<GrantPermissionUseCase> { GrantPermissionUseCaseImpl(get(), get()) }
2323
single<RevokePermissionUseCase> { RevokePermissionUseCaseImpl(get(), get()) }
2424
single<GrantAllPermissionUseCase> { GrantAllPermissionUseCaseImpl(get(), get(), get(), get()) }

src/main/kotlin/androidstudio/tools/missed/features/permission/domain/usecase/fetchall/FetchAllPermissionsUseCaseImpl.kt

+76-42
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ package androidstudio.tools.missed.features.permission.domain.usecase.fetchall
33
import androidstudio.tools.missed.features.permission.domain.usecase.entity.PermissionStateModel
44
import androidstudio.tools.missed.manager.adb.command.PermissionAdbCommands
55
import androidstudio.tools.missed.manager.device.DeviceManager
6-
import androidstudio.tools.missed.manager.resource.ResourceManager
76
import kotlinx.coroutines.flow.flow
87

98
class FetchAllPermissionsUseCaseImpl(
10-
private val resourceManager: ResourceManager,
119
private val deviceManager: DeviceManager
1210
) : FetchAllPermissionsUseCase {
1311

@@ -16,7 +14,6 @@ class FetchAllPermissionsUseCaseImpl(
1614

1715
packageId.let {
1816
val allRuntimePermissionDeviceSupported = getAllRuntimePermissionDeviceSupported()
19-
2017
deviceManager.executeShellCommand(
2118
PermissionAdbCommands.AllPermissionInPackageIdInstalled(packageId)
2219
).onSuccess { result ->
@@ -28,61 +25,98 @@ class FetchAllPermissionsUseCaseImpl(
2825
}
2926
}
3027

31-
private suspend fun getAllRuntimePermissionDeviceSupported(): Result<ArrayList<String>> {
28+
private suspend fun getAllRuntimePermissionDeviceSupported(): ArrayList<String> {
3229
val allRuntimePermissionDeviceSupported = deviceManager.executeShellCommand(
3330
PermissionAdbCommands.AllRuntimePermissionDeviceSupported()
3431
)
35-
36-
return if (allRuntimePermissionDeviceSupported.isSuccess) {
37-
val array = ArrayList<String>()
38-
allRuntimePermissionDeviceSupported.getOrNull()?.split("\n")?.let { array.addAll(it) }
39-
Result.success(array)
40-
} else {
41-
Result.failure(
42-
allRuntimePermissionDeviceSupported.exceptionOrNull()
43-
?: Exception(resourceManager.string("failedToGetPermissions"))
44-
)
32+
val array = ArrayList<String>()
33+
if (allRuntimePermissionDeviceSupported.isSuccess) {
34+
allRuntimePermissionDeviceSupported
35+
.getOrNull()?.split("\n")?.let { permissionsText ->
36+
permissionsText.forEach {
37+
array.add(it.trim())
38+
}
39+
}
4540
}
41+
return array
4642
}
4743

4844
@Suppress("ExpressionBodySyntax")
4945
private fun processPermissionResult(
5046
result: String,
51-
allRuntimePermissionInDevice: Result<ArrayList<String>>
47+
allRuntimePermissionDeviceSupported: ArrayList<String>
5248
): ArrayList<PermissionStateModel> {
5349
// Sample result
54-
// android.permission.WAKE_LOCK: granted=false
55-
// android.permission.CAMERA: granted=true, flags=[ USER_SET|USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
56-
57-
val permissions = ArrayList<PermissionStateModel>()
50+
// requested permissions:
51+
// android.permission.FOREGROUND_SERVICE
52+
// android.permission.INTERNET
53+
// android.permission.CAMERA
54+
// ...
55+
// ...
56+
// install permissions:
57+
// android.permission.NFC: granted=true
58+
// android.permission.INTERNET: granted=true
59+
// android.permission.BLUETOOTH_ADMIN: granted=true
60+
// gids=[3002, 3003, 3001]
61+
// runtime permissions:
62+
// android.permission.ACCESS_FINE_LOCATION: granted=true
63+
// android.permission.CAMERA: granted=true
64+
// disabledComponents:
65+
// ...
66+
// enabledComponents:
67+
// ...
68+
// mSkippingApks:
5869

59-
result.split("\n").reversed().forEach { line ->
60-
val permissionArray = line.split(":")
70+
val requestedPermissions = result
71+
.substringAfter("requested permissions:")
72+
.substringBefore("install permissions:")
73+
.trim()
74+
.split("\n")
75+
.map { line ->
76+
val isRuntime = allRuntimePermissionDeviceSupported.any { it.trim() == line.trim() }
77+
PermissionStateModel(name = line.trim(), isGranted = false, isRuntime = isRuntime)
78+
}
79+
.toCollection(ArrayList())
6180

62-
if (permissionArray.getOrNull(0)?.isNotEmpty() == true &&
63-
permissionArray.getOrNull(1)?.isNotEmpty() == true &&
64-
permissionArray.getOrNull(1)?.contains("granted=") == true
65-
) {
66-
val permissionName = permissionArray.getOrNull(0)
67-
var isRunTimePermission = false
81+
val installPermissions = result
82+
.substringAfter("install permissions:")
83+
.substringBefore("runtime permissions:")
84+
.split("\n")
85+
.filter { it.contains("granted=") }
86+
.map { line ->
87+
val (permissionName, isGranted) = line.split(":")
88+
PermissionStateModel(
89+
name = permissionName.trim() ?: "-",
90+
isGranted = isGranted.contains("granted=true"),
91+
isRuntime = false
92+
)
93+
}
94+
.toCollection(ArrayList())
6895

69-
allRuntimePermissionInDevice.onSuccess { runtimePermissions ->
70-
if (permissionName in runtimePermissions) {
71-
isRunTimePermission = true
72-
}
96+
val runtimePermissions = result
97+
.substringAfter("runtime permissions:")
98+
.substringBefore("mSkippingApks:")
99+
.split("\n")
100+
.filter { it.contains("granted=") }
101+
.map { line ->
102+
val (permissionName, isGranted) = line.split(":")
103+
PermissionStateModel(
104+
name = permissionName.trim() ?: "-",
105+
isGranted = isGranted.contains("granted=true"),
106+
isRuntime = true
107+
)
108+
}
109+
.toCollection(ArrayList())
73110

74-
permissions.add(
75-
PermissionStateModel(
76-
name = permissionName ?: "-",
77-
isGranted = permissionArray.getOrNull(1)?.contains("granted=true") ?: false,
78-
isRuntime = isRunTimePermission
79-
)
80-
)
81-
}.onFailure {
82-
throw Throwable(it.message)
83-
}
111+
requestedPermissions.forEachIndexed { index, permission ->
112+
installPermissions.find { it.name == permission.name }?.let {
113+
requestedPermissions[index] = it
114+
}
115+
runtimePermissions.find { it.name == permission.name }?.let {
116+
requestedPermissions[index] = it
84117
}
85118
}
86-
return permissions
119+
120+
return requestedPermissions
87121
}
88122
}

src/main/kotlin/androidstudio/tools/missed/manager/adb/AdbManagerImpl.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class AdbManagerImpl(
3030

3131
companion object {
3232
private const val MAX_TRIALS = 10
33-
private const val INITIAL_ADB_DELAY_MS = 50L
33+
private const val INITIAL_ADB_DELAY_MS = 100L
3434
private const val INITIAL_ADB_RETRY_DELAY_MS = 1000L
3535
}
3636

src/main/kotlin/androidstudio/tools/missed/manager/adb/command/AdbCommand.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ sealed class AdbCommand(
4747
)
4848

4949
class ClearEditText : AdbCommand(
50-
command = "input keycombination 113 29 && input keyevent 67",
50+
command = "input keyevent --longpress \$(for i in `seq 1 30`; do echo KEYCODE_DEL; done)",
5151
isNeedDevice = true,
5252
isNeedPackageId = false
5353
)

src/main/kotlin/androidstudio/tools/missed/manager/adb/command/DeviceAdbCommands.kt

+7
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,11 @@ class DeviceAdbCommands {
2828
isNeedPackageId = false,
2929
successResult = SuccessResultEnum.NOT_EMPTY
3030
)
31+
32+
class PackageVerifierEnable : AdbCommand(
33+
command = "settings put global package_verifier_enable 0\n",
34+
isNeedDevice = true,
35+
isNeedPackageId = false,
36+
successResult = SuccessResultEnum.EMPTY
37+
)
3138
}

src/main/kotlin/androidstudio/tools/missed/manager/adb/command/PermissionAdbCommands.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ package androidstudio.tools.missed.manager.adb.command
33
class PermissionAdbCommands {
44

55
class AllRuntimePermissionDeviceSupported : AdbCommand(
6-
command = "pm list permissions -g -d | awk -F: '/permission:/ {print \$2}'",
6+
command = "pm list permissions -g -d | grep -i \"permission:\" | sed 's/permission://' ",
77
isNeedDevice = false,
88
isNeedPackageId = false,
99
successResult = SuccessResultEnum.NOT_EMPTY
1010
)
1111

1212
class AllPermissionInPackageIdInstalled(val packageId: String) : AdbCommand(
13-
command = "dumpsys package $packageId | grep -E 'permission.*granted' | grep -o '[^\$(printf '\\t') ].*' \n",
13+
command = "dumpsys package $packageId | sed -n '/requested permissions:/,/mSkippingApks:/p'",
1414
isNeedDevice = false,
1515
isNeedPackageId = true,
1616
successResult = SuccessResultEnum.EMPTY_OR_NOT_EMPTY

src/main/kotlin/androidstudio/tools/missed/manager/adb/di/AdbManagerModule.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import java.util.concurrent.TimeUnit
1010

1111
@Suppress("MagicNumber")
1212
val adbManagerModule = module {
13-
single<AndroidDebugBridge> { AndroidDebugBridge.createBridge(10, TimeUnit.SECONDS) }
13+
single<AndroidDebugBridge> { AndroidDebugBridge.createBridge(10000, TimeUnit.SECONDS) }
1414
single<AdbLogger> { AdbLoggerImpl() }
1515
single<AdbManager> { AdbManagerImpl(get(), get(), get()) }
1616
}

0 commit comments

Comments
 (0)