mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
Bind Shizuku service before navigate to it
Fix CI building
This commit is contained in:
@@ -59,6 +59,7 @@ import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.bintianqi.owndroid.dpm.AccountsViewer
|
||||
import com.bintianqi.owndroid.dpm.AffiliationID
|
||||
import com.bintianqi.owndroid.dpm.AlwaysOnVPNPackage
|
||||
import com.bintianqi.owndroid.dpm.ApplicationManage
|
||||
@@ -213,7 +214,8 @@ fun Home(activity: FragmentActivity, vm: MyViewModel) {
|
||||
composable(route = "HomePage") { HomePage(navCtrl) }
|
||||
|
||||
composable(route = "Permissions") { Permissions(navCtrl) }
|
||||
composable(route = "Shizuku") { Shizuku(vm, navCtrl) }
|
||||
composable(route = "Shizuku") { Shizuku(navCtrl, it.arguments!!) }
|
||||
composable(route = "AccountsViewer") { AccountsViewer(navCtrl, it.arguments!!) }
|
||||
composable(route = "DeviceAdmin") { DeviceAdmin(navCtrl) }
|
||||
composable(route = "ProfileOwner") { ProfileOwner(navCtrl) }
|
||||
composable(route = "DeviceOwner") { DeviceOwner(navCtrl) }
|
||||
@@ -360,7 +362,7 @@ private fun HomePage(navCtrl:NavHostController) {
|
||||
val profileOwner = context.isProfileOwner
|
||||
val refreshStatus by dhizukuErrorStatus.collectAsState()
|
||||
LaunchedEffect(refreshStatus) {
|
||||
activated = context.isDeviceAdmin
|
||||
activated = context.isProfileOwner || context.isDeviceOwner
|
||||
activateType = if(sharedPref.getBoolean("dhizuku", false)) context.getString(R.string.dhizuku) + " - " else ""
|
||||
activateType += context.getString(
|
||||
if(deviceOwner) { R.string.device_owner }
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.bintianqi.owndroid
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@@ -12,7 +11,6 @@ class MyViewModel: ViewModel() {
|
||||
val theme = MutableStateFlow(ThemeSettings())
|
||||
val installedPackages = mutableListOf<PackageInfo>()
|
||||
val selectedPackage = MutableStateFlow("")
|
||||
val shizukuBinder = MutableStateFlow<IBinder?>(null)
|
||||
|
||||
var initialized = false
|
||||
fun initialize(context: Context) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.bintianqi.owndroid
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
@@ -85,3 +86,8 @@ val Long.humanReadableDate: String
|
||||
fun Context.showOperationResultToast(success: Boolean) {
|
||||
Toast.makeText(this, if(success) R.string.success else R.string.failed, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
@SuppressLint("PrivateApi")
|
||||
fun getContext(): Context {
|
||||
return Class.forName("android.app.ActivityThread").getMethod("currentApplication").invoke(null) as Context
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Binder
|
||||
import android.os.Build.VERSION
|
||||
import android.os.Bundle
|
||||
import android.os.RemoteException
|
||||
import android.os.UserManager
|
||||
import android.widget.Toast
|
||||
@@ -29,6 +30,7 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.navigation.NavHostController
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.backToHomeStateFlow
|
||||
@@ -54,6 +56,7 @@ fun Permissions(navCtrl: NavHostController) {
|
||||
val profileOwner = context.isProfileOwner
|
||||
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
|
||||
var dialog by remember { mutableIntStateOf(0) }
|
||||
var bindingShizuku by remember { mutableStateOf(false) }
|
||||
val enrollmentSpecificId = if(VERSION.SDK_INT >= 31 && (deviceOwner || profileOwner)) dpm.enrollmentSpecificId else ""
|
||||
MyScaffold(R.string.permissions, 0.dp, navCtrl) {
|
||||
if(!dpm.isDeviceOwnerApp(context.packageName)) {
|
||||
@@ -82,8 +85,19 @@ fun Permissions(navCtrl: NavHostController) {
|
||||
}
|
||||
FunctionItem(R.string.shizuku) {
|
||||
try {
|
||||
if(Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) { navCtrl.navigate("Shizuku") }
|
||||
else if(Shizuku.shouldShowRequestPermissionRationale()) {
|
||||
if(Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) {
|
||||
bindingShizuku = true
|
||||
val destination = navCtrl.graph.findNode("Shizuku")!!.id
|
||||
bindShizukuService(context, { binder ->
|
||||
val args = Bundle()
|
||||
args.putBinder("binder", binder)
|
||||
bindingShizuku = false
|
||||
navCtrl.navigate(destination, args)
|
||||
}, {
|
||||
Toast.makeText(context, R.string.shizuku_service_disconnected, Toast.LENGTH_SHORT).show()
|
||||
bindingShizuku = false
|
||||
})
|
||||
} else if(Shizuku.shouldShowRequestPermissionRationale()) {
|
||||
Toast.makeText(context, R.string.permission_denied, Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
Sui.init(context.packageName)
|
||||
@@ -124,6 +138,11 @@ fun Permissions(navCtrl: NavHostController) {
|
||||
FunctionItem(R.string.transfer_ownership, icon = R.drawable.admin_panel_settings_fill0) { navCtrl.navigate("TransferOwnership") }
|
||||
}
|
||||
}
|
||||
if(bindingShizuku) {
|
||||
Dialog(onDismissRequest = { bindingShizuku = false }) {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
}
|
||||
if(dialog != 0) {
|
||||
var input by remember { mutableStateOf("") }
|
||||
AlertDialog(
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
package com.bintianqi.owndroid.dpm
|
||||
|
||||
import android.accounts.Account
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.ServiceConnection
|
||||
import android.os.Binder
|
||||
import android.os.Build.VERSION
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import android.widget.Toast
|
||||
import android.util.Log
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -28,56 +33,39 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavHostController
|
||||
import com.bintianqi.owndroid.IUserService
|
||||
import com.bintianqi.owndroid.MyViewModel
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.ui.MyScaffold
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import rikka.shizuku.Shizuku
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun Shizuku(vm: MyViewModel, navCtrl: NavHostController) {
|
||||
fun Shizuku(navCtrl: NavHostController, navArgs: Bundle) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val coScope = rememberCoroutineScope()
|
||||
val outputTextScrollState = rememberScrollState()
|
||||
var outputText by rememberSaveable { mutableStateOf("") }
|
||||
var showDeviceAdminButton by remember { mutableStateOf(!context.isDeviceAdmin) }
|
||||
var showDeviceOwnerButton by remember { mutableStateOf(!context.isDeviceOwner) }
|
||||
var showOrgProfileOwnerButton by remember { mutableStateOf(true) }
|
||||
val binder by vm.shizukuBinder.collectAsStateWithLifecycle()
|
||||
val binder = navArgs.getBinder("binder")!!
|
||||
var service by remember { mutableStateOf<IUserService?>(null) }
|
||||
var loading by remember { mutableStateOf(true) }
|
||||
LaunchedEffect(binder) {
|
||||
if(binder != null && binder!!.pingBinder()) {
|
||||
service = IUserService.Stub.asInterface(binder)
|
||||
loading = false
|
||||
} else {
|
||||
service = null
|
||||
}
|
||||
}
|
||||
LaunchedEffect(service) {
|
||||
if(service == null && !loading) navCtrl.navigateUp()
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
if(binder == null) bindShizukuService(context, vm.shizukuBinder)
|
||||
service = if(binder.pingBinder()) {
|
||||
IUserService.Stub.asInterface(binder)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
MyScaffold(R.string.shizuku, 0.dp, navCtrl, false) {
|
||||
if(loading) {
|
||||
Dialog(onDismissRequest = { navCtrl.navigateUp() }) {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
}
|
||||
|
||||
Button(
|
||||
onClick = {
|
||||
@@ -103,9 +91,16 @@ fun Shizuku(vm: MyViewModel, navCtrl: NavHostController) {
|
||||
}
|
||||
Button(
|
||||
onClick = {
|
||||
coScope.launch{
|
||||
Log.d("Shizuku", "List accounts")
|
||||
try {
|
||||
val accounts = service!!.listAccounts()
|
||||
val dest = navCtrl.graph.findNode("AccountsViewer")!!.id
|
||||
navCtrl.navigate(dest, Bundle().apply { putParcelableArray("accounts", accounts) })
|
||||
} catch(_: Exception) {
|
||||
outputText = service!!.execute("dumpsys account")
|
||||
outputTextScrollState.animateScrollTo(0)
|
||||
coScope.launch{
|
||||
outputTextScrollState.animateScrollTo(0)
|
||||
}
|
||||
}
|
||||
},
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally)
|
||||
@@ -114,23 +109,7 @@ fun Shizuku(vm: MyViewModel, navCtrl: NavHostController) {
|
||||
}
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
|
||||
AnimatedVisibility(showDeviceAdminButton && showDeviceOwnerButton) {
|
||||
Button(
|
||||
onClick = {
|
||||
coScope.launch{
|
||||
outputText = service!!.execute(context.getString(R.string.dpm_activate_da_command))
|
||||
outputTextScrollState.animateScrollTo(0)
|
||||
delay(500)
|
||||
showDeviceAdminButton = !context.isDeviceAdmin
|
||||
}
|
||||
},
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally)
|
||||
) {
|
||||
Text(text = stringResource(R.string.activate_device_admin))
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedVisibility(showDeviceOwnerButton) {
|
||||
AnimatedVisibility(showDeviceOwnerButton, modifier = Modifier.align(Alignment.CenterHorizontally)) {
|
||||
Button(
|
||||
onClick = {
|
||||
coScope.launch{
|
||||
@@ -139,8 +118,7 @@ fun Shizuku(vm: MyViewModel, navCtrl: NavHostController) {
|
||||
delay(500)
|
||||
showDeviceOwnerButton = !context.isDeviceOwner
|
||||
}
|
||||
},
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally)
|
||||
}
|
||||
) {
|
||||
Text(text = stringResource(R.string.activate_device_owner))
|
||||
}
|
||||
@@ -173,14 +151,17 @@ fun Shizuku(vm: MyViewModel, navCtrl: NavHostController) {
|
||||
}
|
||||
}
|
||||
|
||||
fun bindShizukuService(context: Context, shizukuBinder: MutableStateFlow<IBinder?>) {
|
||||
fun bindShizukuService(
|
||||
context: Context,
|
||||
onServiceConnected: (IBinder) -> Unit,
|
||||
onServiceDisconnected: () -> Unit
|
||||
) {
|
||||
val userServiceConnection = object : ServiceConnection {
|
||||
override fun onServiceConnected(componentName: ComponentName, binder: IBinder) {
|
||||
shizukuBinder.value = binder
|
||||
onServiceConnected(binder)
|
||||
}
|
||||
override fun onServiceDisconnected(componentName: ComponentName) {
|
||||
shizukuBinder.value = null
|
||||
Toast.makeText(context, R.string.shizuku_service_disconnected, Toast.LENGTH_SHORT).show()
|
||||
onServiceDisconnected()
|
||||
}
|
||||
}
|
||||
val userServiceArgs = Shizuku.UserServiceArgs(ComponentName(context, ShizukuService::class.java))
|
||||
@@ -194,3 +175,24 @@ fun bindShizukuService(context: Context, shizukuBinder: MutableStateFlow<IBinder
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AccountsViewer(navCtrl: NavHostController, navArgs: Bundle) {
|
||||
val accounts = navArgs.getParcelableArray("accounts") as Array<Account>
|
||||
MyScaffold(R.string.accounts, 8.dp, navCtrl, false) {
|
||||
accounts.forEach {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth().padding(vertical = 4.dp)
|
||||
.clip(RoundedCornerShape(15)).background(MaterialTheme.colorScheme.surfaceVariant)
|
||||
) {
|
||||
SelectionContainer {
|
||||
Column(modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)) {
|
||||
Text(stringResource(R.string.type) + ": " + it.type)
|
||||
Text(stringResource(R.string.name) + ": " + it.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
package com.bintianqi.owndroid.dpm
|
||||
|
||||
import android.accounts.Account
|
||||
import android.accounts.AccountManager
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Parcelable
|
||||
import android.os.UserManager
|
||||
import android.system.Os
|
||||
import androidx.annotation.Keep
|
||||
import com.bintianqi.owndroid.IUserService
|
||||
import com.bintianqi.owndroid.getContext
|
||||
import java.io.BufferedReader
|
||||
import java.io.InputStreamReader
|
||||
import java.lang.Class
|
||||
|
||||
@Keep
|
||||
class ShizukuService: IUserService.Stub() {
|
||||
@@ -33,4 +41,10 @@ class ShizukuService: IUserService.Stub() {
|
||||
}
|
||||
|
||||
override fun getUid(): Int = Os.getuid()
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
override fun listAccounts(): Array<Account> {
|
||||
val am = getContext().getSystemService(Context.ACCOUNT_SERVICE) as AccountManager
|
||||
return am.accounts
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user