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