From 0416882aa6912877ad4282df6e5983bca0417593 Mon Sep 17 00:00:00 2001 From: alieRN <45766489+aliernfrog@users.noreply.github.com> Date: Sat, 14 Sep 2024 23:25:57 +0300 Subject: [PATCH] feat(shizuku): add support for Sui --- .../permissions/ShizukuPermissionsScreen.kt | 45 +++++++++++++++++-- .../pftool/ui/viewmodel/ShizukuViewModel.kt | 41 ++++++++++------- app/src/main/res/values/strings.xml | 9 ++-- 3 files changed, 71 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/com/aliernfrog/pftool/ui/screen/permissions/ShizukuPermissionsScreen.kt b/app/src/main/java/com/aliernfrog/pftool/ui/screen/permissions/ShizukuPermissionsScreen.kt index 2ffc2a3b..9c188ae7 100644 --- a/app/src/main/java/com/aliernfrog/pftool/ui/screen/permissions/ShizukuPermissionsScreen.kt +++ b/app/src/main/java/com/aliernfrog/pftool/ui/screen/permissions/ShizukuPermissionsScreen.kt @@ -17,6 +17,7 @@ import androidx.compose.material.icons.filled.RestartAlt import androidx.compose.material3.Button import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable @@ -32,6 +33,7 @@ import com.aliernfrog.pftool.R import com.aliernfrog.pftool.enum.ShizukuStatus import com.aliernfrog.pftool.ui.component.ButtonIcon import com.aliernfrog.pftool.ui.component.CardWithActions +import com.aliernfrog.pftool.ui.component.FadeVisibility import com.aliernfrog.pftool.ui.viewmodel.ShizukuViewModel import com.aliernfrog.pftool.util.staticutil.GeneralUtil import org.koin.androidx.compose.koinViewModel @@ -77,7 +79,7 @@ fun ShizukuPermissionsScreen( .align(Alignment.CenterHorizontally) .padding(16.dp), buttons = { - TextButton( + if (shizukuViewModel.managerInstalled) TextButton( onClick = { shizukuViewModel.launchManager(context) } @@ -111,7 +113,7 @@ private fun ShizukuSetupGuide( val context = LocalContext.current val uriHandler = LocalUriHandler.current - if (shizukuViewModel.installed) Text( + if (shizukuViewModel.managerInstalled) Text( text = stringResource(R.string.permissions_shizuku_introduction), style = MaterialTheme.typography.bodyMedium, modifier = Modifier.padding(8.dp) @@ -134,11 +136,11 @@ private fun ShizukuSetupGuide( ShizukuStatus.UNKNOWN, ShizukuStatus.NOT_INSTALLED -> { Button( onClick = { - uriHandler.openUri("https://play.google.com/store/apps/details?id=moe.shizuku.privileged.api") + shizukuViewModel.launchManager(context) } ) { ButtonIcon(rememberVectorPainter(Icons.AutoMirrored.Filled.OpenInNew)) - Text(stringResource(R.string.permissions_shizuku_install_install)) + Text(stringResource(R.string.permissions_shizuku_installShizuku)) } } ShizukuStatus.WAITING_FOR_BINDER -> { @@ -175,5 +177,40 @@ private fun ShizukuSetupGuide( } } + FadeVisibility( + shizukuViewModel.deviceRooted && shizukuViewModel.status != ShizukuStatus.UNAUTHORIZED + ) { + CardWithActions( + title = stringResource(R.string.permissions_shizuku_rooted), + buttons = { + OutlinedButton( + onClick = { + uriHandler.openUri(ShizukuViewModel.SUI_GITHUB) + } + ) { + ButtonIcon(rememberVectorPainter(Icons.AutoMirrored.Filled.OpenInNew)) + Text(stringResource(R.string.permissions_shizuku_sui)) + } + Button( + onClick = { + shizukuViewModel.launchManager(context) + } + ) { + ButtonIcon(rememberVectorPainter(Icons.AutoMirrored.Filled.OpenInNew)) + Text(stringResource( + if (shizukuViewModel.managerInstalled) R.string.permissions_shizuku_openShizuku + else R.string.permissions_shizuku_installShizuku + )) + } + }, + modifier = Modifier.fillMaxWidth().padding(8.dp) + ) { + Text( + text = stringResource(R.string.permissions_shizuku_rooted_description), + style = MaterialTheme.typography.bodyMedium + ) + } + } + Spacer(Modifier.navigationBarsPadding()) } \ No newline at end of file diff --git a/app/src/main/java/com/aliernfrog/pftool/ui/viewmodel/ShizukuViewModel.kt b/app/src/main/java/com/aliernfrog/pftool/ui/viewmodel/ShizukuViewModel.kt index c3665c24..7e181b37 100644 --- a/app/src/main/java/com/aliernfrog/pftool/ui/viewmodel/ShizukuViewModel.kt +++ b/app/src/main/java/com/aliernfrog/pftool/ui/viewmodel/ShizukuViewModel.kt @@ -2,8 +2,10 @@ package com.aliernfrog.pftool.ui.viewmodel import android.content.ComponentName import android.content.Context +import android.content.Intent import android.content.ServiceConnection import android.content.pm.PackageManager +import android.net.Uri import android.os.IBinder import android.util.Log import androidx.compose.material.icons.Icons @@ -26,7 +28,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch import rikka.shizuku.Shizuku - +import java.io.File class ShizukuViewModel( val prefs: PreferenceManager, @@ -35,11 +37,16 @@ class ShizukuViewModel( ) : ViewModel() { companion object { const val SHIZUKU_PACKAGE = "moe.shizuku.privileged.api" + const val SHIZUKU_PLAY_STORE = "https://play.google.com/store/apps/details?id=moe.shizuku.privileged.api" + const val SUI_GITHUB = "https://github.com/RikkaApps/Sui" } var status by mutableStateOf(ShizukuStatus.UNKNOWN) - val installed: Boolean + val managerInstalled: Boolean get() = status != ShizukuStatus.NOT_INSTALLED && status != ShizukuStatus.UNKNOWN + val deviceRooted = System.getenv("PATH")?.split(":")?.any { path -> + File(path, "su").canExecute() + } ?: false var fileService: IFileService? = null var fileServiceRunning by mutableStateOf(false) @@ -60,7 +67,7 @@ class ShizukuViewModel( private val userServiceConnection = object : ServiceConnection { override fun onServiceConnected(componentName: ComponentName, binder: IBinder) { val shizukuNeverLoad = prefs.shizukuNeverLoad.value - Log.d(TAG, "user service connected, shizukuNeverLoad ${shizukuNeverLoad}") + Log.d(TAG, "user service connected, shizukuNeverLoad: $shizukuNeverLoad") if (shizukuNeverLoad) return fileService = IFileService.Stub.asInterface(binder) fileServiceRunning = true @@ -90,13 +97,17 @@ class ShizukuViewModel( Shizuku.addBinderReceivedListener(binderReceivedListener) Shizuku.addBinderDeadListener(binderDeadListener) Shizuku.addRequestPermissionResultListener(permissionResultListener) + checkAvailability(context) } fun launchManager(context: Context) { try { - context.startActivity( + if (managerInstalled) context.startActivity( context.packageManager.getLaunchIntentForPackage(SHIZUKU_PACKAGE) - ) + ) else { + val intent = Intent(Intent.ACTION_VIEW, Uri.parse(SHIZUKU_PLAY_STORE)) + context.startActivity(intent) + } } catch (e: Exception) { Log.e(TAG, "ShizukuViewModel/launchManager: failed to start activity ", e) topToastState.showErrorToast() @@ -105,14 +116,13 @@ class ShizukuViewModel( fun checkAvailability(context: Context): ShizukuStatus { status = try { - if (!isInstalled(context)) ShizukuStatus.NOT_INSTALLED - else if (!Shizuku.pingBinder()) ShizukuStatus.WAITING_FOR_BINDER - else { + if (Shizuku.pingBinder()) { if (Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) ShizukuStatus.AVAILABLE else ShizukuStatus.UNAUTHORIZED - } + } else if (!isManagerInstalled(context)) ShizukuStatus.NOT_INSTALLED + else ShizukuStatus.WAITING_FOR_BINDER } catch (e: Exception) { - Log.e(TAG, "updateStatus: ", e) + Log.e(TAG, "ShizukuViewModel/checkAvailability: failed to determine status", e) ShizukuStatus.UNKNOWN } if (status == ShizukuStatus.AVAILABLE && !fileServiceRunning) { @@ -125,13 +135,10 @@ class ShizukuViewModel( return status } - private fun isInstalled(context: Context): Boolean { - return try { - context.packageManager.getPackageInfo(SHIZUKU_PACKAGE, 0) != null - } catch (e: Exception) { - Log.e(TAG, "isInstalled: ", e) - false - } + private fun isManagerInstalled(context: Context) = try { + context.packageManager.getPackageInfo(SHIZUKU_PACKAGE, 0) != null + } catch (_: Exception) { + false } override fun onCleared() { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 85df20c8..865a470a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -46,13 +46,16 @@ PF Tool used this folder in older versions, choose this folder if you want to access maps you have exported before Shizuku is an app which lets other apps use shell permissions by making use of wireless debugging.\nShizuku mode can be disabled from Settings > Storage > Storage access type Open Shizuku + Install Shizuku Install Shizuku to get started - Install Shizuku is not running Start Shizuku service to proceed Permission needed PF Tool does not have permissions to use Shizuku Grant permission + Start Shizuku automatically + On rooted devices, you can set Shizuku to start automatically when your device boots up, you can find this option in Shizuku\nAlternatively, you can use Shizuku\'s Magisk module \"Sui\" which works similarly + Sui Waiting for file service.. Taking long? Try restarting PF Tool Restart @@ -142,8 +145,8 @@ Storage access type Scoped storage Only access the directories PF Tool needs - Shizuku - Use Shizuku to access storage + Shizuku/Sui + Use Shizuku or Sui to access storage All files access (legacy) Access all files, this may be easier to setup Folders