fix: sync auth state
Some checks are pending
Build-Apk / build (push) Waiting to run

This commit is contained in:
二刺螈 2024-11-05 23:07:34 +08:00
parent 305c65b776
commit 80b2a23c1f
5 changed files with 50 additions and 28 deletions

View File

@ -172,7 +172,11 @@ val shizukuOkState by lazy {
) )
} }
suspend fun updatePermissionState() { fun startQueryPkgSettingActivity(context: Activity) {
XXPermissions.startPermissionActivity(context, Permission.GET_INSTALLED_APPS)
}
fun updatePermissionState() {
arrayOf( arrayOf(
notificationState, notificationState,
canDrawOverlaysState, canDrawOverlaysState,

View File

@ -3,19 +3,23 @@ package li.songe.gkd.service
import android.provider.Settings import android.provider.Settings
import android.service.quicksettings.Tile import android.service.quicksettings.Tile
import android.service.quicksettings.TileService import android.service.quicksettings.TileService
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import li.songe.gkd.app import li.songe.gkd.app
import li.songe.gkd.appScope
import li.songe.gkd.permission.writeSecureSettingsState import li.songe.gkd.permission.writeSecureSettingsState
import li.songe.gkd.util.OnChangeListen import li.songe.gkd.util.OnChangeListen
import li.songe.gkd.util.OnDestroy import li.songe.gkd.util.OnDestroy
import li.songe.gkd.util.OnTileClick import li.songe.gkd.util.OnTileClick
import li.songe.gkd.util.componentName import li.songe.gkd.util.componentName
import li.songe.gkd.util.lastRestartA11yServiceTimeFlow import li.songe.gkd.util.lastRestartA11yServiceTimeFlow
import li.songe.gkd.util.launchTry
import li.songe.gkd.util.storeFlow import li.songe.gkd.util.storeFlow
import li.songe.gkd.util.toast import li.songe.gkd.util.toast
import li.songe.gkd.util.useLogLifecycle import li.songe.gkd.util.useLogLifecycle
@ -125,13 +129,13 @@ fun switchA11yService(): Boolean {
return true return true
} }
fun fixRestartService(): Boolean { fun fixRestartService() = appScope.launchTry(Dispatchers.IO) {
// 1. 服务没有运行 // 1. 服务没有运行
// 2. 用户配置开启了服务 // 2. 用户配置开启了服务
// 3. 有写入系统设置权限 // 3. 有写入系统设置权限
if (!A11yService.isRunning.value && storeFlow.value.enableService && writeSecureSettingsState.updateAndGet()) { if (!A11yService.isRunning.value && storeFlow.value.enableService && writeSecureSettingsState.updateAndGet()) {
val t = System.currentTimeMillis() val t = System.currentTimeMillis()
if (t - lastRestartA11yServiceTimeFlow.value < 10_000) return false if (t - lastRestartA11yServiceTimeFlow.value < 5_000) return@launchTry
lastRestartA11yServiceTimeFlow.value = t lastRestartA11yServiceTimeFlow.value = t
val names = getServiceNames() val names = getServiceNames()
val a11yBroken = names.contains(a11yClsName) val a11yBroken = names.contains(a11yClsName)
@ -139,13 +143,13 @@ fun fixRestartService(): Boolean {
// 无障碍出现故障, 重启服务 // 无障碍出现故障, 重启服务
names.remove(a11yClsName) names.remove(a11yClsName)
updateServiceNames(names) updateServiceNames(names)
// 必须等待一段时间, 否则概率不会触发系统重启无障碍服务
delay(500)
} }
names.add(a11yClsName) names.add(a11yClsName)
updateServiceNames(names) updateServiceNames(names)
toast("重启无障碍") toast("重启无障碍")
return true
} }
return false
} }
val a11yClsName by lazy { A11yService::class.componentName.flattenToShortString() } val a11yClsName by lazy { A11yService::class.componentName.flattenToShortString() }

View File

@ -172,14 +172,6 @@ fun AuthA11yPage() {
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
) )
} }
TextButton(onClick = throttle(fn = vm.viewModelScope.launchAsFn(Dispatchers.IO) {
grantPermissionByRoot()
})) {
Text(
text = "ROOT授权",
style = MaterialTheme.typography.bodyLarge,
)
}
TextButton(onClick = { TextButton(onClick = {
vm.showCopyDlgFlow.value = true vm.showCopyDlgFlow.value = true
}) { }) {
@ -188,6 +180,14 @@ fun AuthA11yPage() {
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
) )
} }
TextButton(onClick = throttle(fn = vm.viewModelScope.launchAsFn(Dispatchers.IO) {
grantPermissionByRoot()
})) {
Text(
text = "ROOT授权",
style = MaterialTheme.typography.bodyLarge,
)
}
} }
} else { } else {
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))

View File

@ -24,15 +24,27 @@ import androidx.lifecycle.viewModelScope
import li.songe.gkd.MainActivity import li.songe.gkd.MainActivity
import li.songe.gkd.permission.canQueryPkgState import li.songe.gkd.permission.canQueryPkgState
import li.songe.gkd.permission.requiredPermission import li.songe.gkd.permission.requiredPermission
import li.songe.gkd.permission.startQueryPkgSettingActivity
import li.songe.gkd.ui.style.EmptyHeight import li.songe.gkd.ui.style.EmptyHeight
import li.songe.gkd.util.appRefreshingFlow import li.songe.gkd.util.appRefreshingFlow
import li.songe.gkd.util.launchAsFn import li.songe.gkd.util.launchAsFn
import li.songe.gkd.util.mayQueryPkgNoAccessFlow
import li.songe.gkd.util.throttle import li.songe.gkd.util.throttle
@Composable @Composable
fun QueryPkgAuthCard() { fun QueryPkgAuthCard() {
val canQueryPkg by canQueryPkgState.stateFlow.collectAsState() val canQueryPkg by canQueryPkgState.stateFlow.collectAsState()
if (!canQueryPkg) { val mayQueryPkgNoAccess by mayQueryPkgNoAccessFlow.collectAsState()
val appRefreshing by appRefreshingFlow.collectAsState()
if (appRefreshing) {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Spacer(modifier = Modifier.height(EmptyHeight / 2))
CircularProgressIndicator()
}
} else if (!canQueryPkg || mayQueryPkgNoAccess) {
val context = LocalContext.current as MainActivity val context = LocalContext.current as MainActivity
Column( Column(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@ -46,27 +58,20 @@ fun QueryPkgAuthCard() {
) )
Spacer(modifier = Modifier.height(4.dp)) Spacer(modifier = Modifier.height(4.dp))
Text( Text(
text = "如需显示所有应用\n授予[读取应用列表权限]", text = if (!canQueryPkg) "如需显示所有应用\n授予[读取应用列表权限]" else "检测到应用数量过少\n可尝试授予[读取应用列表权限]",
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
) )
TextButton(onClick = throttle(fn = context.mainVm.viewModelScope.launchAsFn { TextButton(onClick = throttle(fn = context.mainVm.viewModelScope.launchAsFn {
requiredPermission(context, canQueryPkgState) if (!canQueryPkg) {
requiredPermission(context, canQueryPkgState)
} else {
startQueryPkgSettingActivity(context)
}
})) { })) {
Text(text = "申请权限") Text(text = "申请权限")
} }
} }
} else {
val appRefreshing by appRefreshingFlow.collectAsState()
if (appRefreshing) {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Spacer(modifier = Modifier.height(EmptyHeight / 2))
CircularProgressIndicator()
}
}
} }
} }

View File

@ -12,6 +12,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import li.songe.gkd.META
import li.songe.gkd.app import li.songe.gkd.app
import li.songe.gkd.appScope import li.songe.gkd.appScope
import li.songe.gkd.data.AppInfo import li.songe.gkd.data.AppInfo
@ -35,6 +36,14 @@ val orderedAppInfosFlow by lazy {
} }
} }
// https://github.com/orgs/gkd-kit/discussions/761
// 某些设备在应用更新后出现权限错乱/缓存错乱
val mayQueryPkgNoAccessFlow by lazy {
appInfoCacheFlow.map(appScope) { c ->
c.values.count { a -> !a.isSystem && !a.hidden && a.id != META.appId } < 8
}
}
private val packageReceiver by lazy { private val packageReceiver by lazy {
object : BroadcastReceiver() { object : BroadcastReceiver() {
/** /**
@ -80,7 +89,7 @@ private fun updateAppInfo(appId: String) {
val newMap = appInfoCacheFlow.value.toMutableMap() val newMap = appInfoCacheFlow.value.toMutableMap()
val info = try { val info = try {
packageManager.getPackageInfo(appId, 0) packageManager.getPackageInfo(appId, 0)
} catch (e: PackageManager.NameNotFoundException) { } catch (_: PackageManager.NameNotFoundException) {
null null
} }
if (info != null) { if (info != null) {