mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 11:05:59 +00:00
Bind Shizuku service before navigate to it
Fix CI building
This commit is contained in:
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -61,7 +61,7 @@ jobs:
|
|||||||
|
|
||||||
upload-telegram:
|
upload-telegram:
|
||||||
name: Upload Builds
|
name: Upload Builds
|
||||||
if: ${{ github.ref_name == 'dev' }}
|
if: github.ref_name == 'dev'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: ["build"]
|
needs: ["build"]
|
||||||
steps:
|
steps:
|
||||||
@@ -91,6 +91,6 @@ jobs:
|
|||||||
mv ./$RELEASE_SIGNED_PWD/app-release.apk ./$RELEASE_SIGNED_PWD.apk && rm -rf ./$RELEASE_SIGNED_PWD
|
mv ./$RELEASE_SIGNED_PWD/app-release.apk ./$RELEASE_SIGNED_PWD.apk && rm -rf ./$RELEASE_SIGNED_PWD
|
||||||
../binaries/telegram-bot-api --api-id=${{ secrets.TELEGRAM_API_APP_ID }} --api-hash=${{ secrets.TELEGRAM_API_HASH }} --local 2>&1 > /dev/null &
|
../binaries/telegram-bot-api --api-id=${{ secrets.TELEGRAM_API_APP_ID }} --api-hash=${{ secrets.TELEGRAM_API_HASH }} --local 2>&1 > /dev/null &
|
||||||
export token=${{ secrets.TELEGRAM_BOT_KEY }}
|
export token=${{ secrets.TELEGRAM_BOT_KEY }}
|
||||||
curl -v "http://127.0.0.1:8081/bot$token/sendMediaGroup?chat_id=-1002216379163&media=%5B%7B%22type%22%3A%22document%22%2C%22media%22%3A%22attach%3A%2F%2FreleaseTest%22%7D%2C%7B%22type%22%3A%22document%22%2C%22media%22%3A%22attach%3A%2F%2FreleaseSigned%22%2C%22parse_mode%22%3A%22HTML%22%2C%22caption%22%3A${ESCAPED}%7D%5D" \
|
curl -v "http://127.0.0.1:8081/bot$token/sendMediaGroup?chat_id=-1002203528169&media=%5B%7B%22type%22%3A%22document%22%2C%22media%22%3A%22attach%3A%2F%2FreleaseTest%22%7D%2C%7B%22type%22%3A%22document%22%2C%22media%22%3A%22attach%3A%2F%2FreleaseSigned%22%2C%22parse_mode%22%3A%22HTML%22%2C%22caption%22%3A${ESCAPED}%7D%5D" \
|
||||||
-F releaseTest="@$RELEASE_TEST_PWD.apk" \
|
-F releaseTest="@$RELEASE_TEST_PWD.apk" \
|
||||||
-F releaseSigned="@$RELEASE_SIGNED_PWD.apk"
|
-F releaseSigned="@$RELEASE_SIGNED_PWD.apk"
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package com.bintianqi.owndroid;
|
package com.bintianqi.owndroid;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
|
|
||||||
interface IUserService {
|
interface IUserService {
|
||||||
String execute(String command) = 1;
|
String execute(String command) = 1;
|
||||||
int getUid() = 2;
|
int getUid() = 2;
|
||||||
|
Account[] listAccounts() = 3;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import androidx.navigation.NavHostController
|
|||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
|
import com.bintianqi.owndroid.dpm.AccountsViewer
|
||||||
import com.bintianqi.owndroid.dpm.AffiliationID
|
import com.bintianqi.owndroid.dpm.AffiliationID
|
||||||
import com.bintianqi.owndroid.dpm.AlwaysOnVPNPackage
|
import com.bintianqi.owndroid.dpm.AlwaysOnVPNPackage
|
||||||
import com.bintianqi.owndroid.dpm.ApplicationManage
|
import com.bintianqi.owndroid.dpm.ApplicationManage
|
||||||
@@ -213,7 +214,8 @@ fun Home(activity: FragmentActivity, vm: MyViewModel) {
|
|||||||
composable(route = "HomePage") { HomePage(navCtrl) }
|
composable(route = "HomePage") { HomePage(navCtrl) }
|
||||||
|
|
||||||
composable(route = "Permissions") { Permissions(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 = "DeviceAdmin") { DeviceAdmin(navCtrl) }
|
||||||
composable(route = "ProfileOwner") { ProfileOwner(navCtrl) }
|
composable(route = "ProfileOwner") { ProfileOwner(navCtrl) }
|
||||||
composable(route = "DeviceOwner") { DeviceOwner(navCtrl) }
|
composable(route = "DeviceOwner") { DeviceOwner(navCtrl) }
|
||||||
@@ -360,7 +362,7 @@ private fun HomePage(navCtrl:NavHostController) {
|
|||||||
val profileOwner = context.isProfileOwner
|
val profileOwner = context.isProfileOwner
|
||||||
val refreshStatus by dhizukuErrorStatus.collectAsState()
|
val refreshStatus by dhizukuErrorStatus.collectAsState()
|
||||||
LaunchedEffect(refreshStatus) {
|
LaunchedEffect(refreshStatus) {
|
||||||
activated = context.isDeviceAdmin
|
activated = context.isProfileOwner || context.isDeviceOwner
|
||||||
activateType = if(sharedPref.getBoolean("dhizuku", false)) context.getString(R.string.dhizuku) + " - " else ""
|
activateType = if(sharedPref.getBoolean("dhizuku", false)) context.getString(R.string.dhizuku) + " - " else ""
|
||||||
activateType += context.getString(
|
activateType += context.getString(
|
||||||
if(deviceOwner) { R.string.device_owner }
|
if(deviceOwner) { R.string.device_owner }
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.bintianqi.owndroid
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.IBinder
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
@@ -12,7 +11,6 @@ class MyViewModel: ViewModel() {
|
|||||||
val theme = MutableStateFlow(ThemeSettings())
|
val theme = MutableStateFlow(ThemeSettings())
|
||||||
val installedPackages = mutableListOf<PackageInfo>()
|
val installedPackages = mutableListOf<PackageInfo>()
|
||||||
val selectedPackage = MutableStateFlow("")
|
val selectedPackage = MutableStateFlow("")
|
||||||
val shizukuBinder = MutableStateFlow<IBinder?>(null)
|
|
||||||
|
|
||||||
var initialized = false
|
var initialized = false
|
||||||
fun initialize(context: Context) {
|
fun initialize(context: Context) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.bintianqi.owndroid
|
package com.bintianqi.owndroid
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.app.admin.DevicePolicyManager
|
import android.app.admin.DevicePolicyManager
|
||||||
import android.content.ClipData
|
import android.content.ClipData
|
||||||
import android.content.ClipboardManager
|
import android.content.ClipboardManager
|
||||||
@@ -85,3 +86,8 @@ val Long.humanReadableDate: String
|
|||||||
fun Context.showOperationResultToast(success: Boolean) {
|
fun Context.showOperationResultToast(success: Boolean) {
|
||||||
Toast.makeText(this, if(success) R.string.success else R.string.failed, Toast.LENGTH_SHORT).show()
|
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.content.pm.PackageManager
|
||||||
import android.os.Binder
|
import android.os.Binder
|
||||||
import android.os.Build.VERSION
|
import android.os.Build.VERSION
|
||||||
|
import android.os.Bundle
|
||||||
import android.os.RemoteException
|
import android.os.RemoteException
|
||||||
import android.os.UserManager
|
import android.os.UserManager
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
@@ -29,6 +30,7 @@ import androidx.compose.ui.res.painterResource
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.input.ImeAction
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import com.bintianqi.owndroid.R
|
import com.bintianqi.owndroid.R
|
||||||
import com.bintianqi.owndroid.backToHomeStateFlow
|
import com.bintianqi.owndroid.backToHomeStateFlow
|
||||||
@@ -54,6 +56,7 @@ fun Permissions(navCtrl: NavHostController) {
|
|||||||
val profileOwner = context.isProfileOwner
|
val profileOwner = context.isProfileOwner
|
||||||
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
|
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
|
||||||
var dialog by remember { mutableIntStateOf(0) }
|
var dialog by remember { mutableIntStateOf(0) }
|
||||||
|
var bindingShizuku by remember { mutableStateOf(false) }
|
||||||
val enrollmentSpecificId = if(VERSION.SDK_INT >= 31 && (deviceOwner || profileOwner)) dpm.enrollmentSpecificId else ""
|
val enrollmentSpecificId = if(VERSION.SDK_INT >= 31 && (deviceOwner || profileOwner)) dpm.enrollmentSpecificId else ""
|
||||||
MyScaffold(R.string.permissions, 0.dp, navCtrl) {
|
MyScaffold(R.string.permissions, 0.dp, navCtrl) {
|
||||||
if(!dpm.isDeviceOwnerApp(context.packageName)) {
|
if(!dpm.isDeviceOwnerApp(context.packageName)) {
|
||||||
@@ -82,8 +85,19 @@ fun Permissions(navCtrl: NavHostController) {
|
|||||||
}
|
}
|
||||||
FunctionItem(R.string.shizuku) {
|
FunctionItem(R.string.shizuku) {
|
||||||
try {
|
try {
|
||||||
if(Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) { navCtrl.navigate("Shizuku") }
|
if(Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) {
|
||||||
else if(Shizuku.shouldShowRequestPermissionRationale()) {
|
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()
|
Toast.makeText(context, R.string.permission_denied, Toast.LENGTH_SHORT).show()
|
||||||
} else {
|
} else {
|
||||||
Sui.init(context.packageName)
|
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") }
|
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) {
|
if(dialog != 0) {
|
||||||
var input by remember { mutableStateOf("") }
|
var input by remember { mutableStateOf("") }
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
|
|||||||
@@ -1,22 +1,27 @@
|
|||||||
package com.bintianqi.owndroid.dpm
|
package com.bintianqi.owndroid.dpm
|
||||||
|
|
||||||
|
import android.accounts.Account
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.ServiceConnection
|
import android.content.ServiceConnection
|
||||||
import android.os.Binder
|
import android.os.Binder
|
||||||
import android.os.Build.VERSION
|
import android.os.Build.VERSION
|
||||||
|
import android.os.Bundle
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.widget.Toast
|
import android.util.Log
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.horizontalScroll
|
import androidx.compose.foundation.horizontalScroll
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -28,56 +33,39 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.Dialog
|
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import com.bintianqi.owndroid.IUserService
|
import com.bintianqi.owndroid.IUserService
|
||||||
import com.bintianqi.owndroid.MyViewModel
|
|
||||||
import com.bintianqi.owndroid.R
|
import com.bintianqi.owndroid.R
|
||||||
import com.bintianqi.owndroid.ui.MyScaffold
|
import com.bintianqi.owndroid.ui.MyScaffold
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import rikka.shizuku.Shizuku
|
import rikka.shizuku.Shizuku
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun Shizuku(vm: MyViewModel, navCtrl: NavHostController) {
|
fun Shizuku(navCtrl: NavHostController, navArgs: Bundle) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val dpm = context.getDPM()
|
val dpm = context.getDPM()
|
||||||
val receiver = context.getReceiver()
|
val receiver = context.getReceiver()
|
||||||
val coScope = rememberCoroutineScope()
|
val coScope = rememberCoroutineScope()
|
||||||
val outputTextScrollState = rememberScrollState()
|
val outputTextScrollState = rememberScrollState()
|
||||||
var outputText by rememberSaveable { mutableStateOf("") }
|
var outputText by rememberSaveable { mutableStateOf("") }
|
||||||
var showDeviceAdminButton by remember { mutableStateOf(!context.isDeviceAdmin) }
|
|
||||||
var showDeviceOwnerButton by remember { mutableStateOf(!context.isDeviceOwner) }
|
var showDeviceOwnerButton by remember { mutableStateOf(!context.isDeviceOwner) }
|
||||||
var showOrgProfileOwnerButton by remember { mutableStateOf(true) }
|
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 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) {
|
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) {
|
MyScaffold(R.string.shizuku, 0.dp, navCtrl, false) {
|
||||||
if(loading) {
|
|
||||||
Dialog(onDismissRequest = { navCtrl.navigateUp() }) {
|
|
||||||
CircularProgressIndicator()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -103,10 +91,17 @@ fun Shizuku(vm: MyViewModel, navCtrl: NavHostController) {
|
|||||||
}
|
}
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
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")
|
outputText = service!!.execute("dumpsys account")
|
||||||
|
coScope.launch{
|
||||||
outputTextScrollState.animateScrollTo(0)
|
outputTextScrollState.animateScrollTo(0)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier.align(Alignment.CenterHorizontally)
|
modifier = Modifier.align(Alignment.CenterHorizontally)
|
||||||
) {
|
) {
|
||||||
@@ -114,23 +109,7 @@ fun Shizuku(vm: MyViewModel, navCtrl: NavHostController) {
|
|||||||
}
|
}
|
||||||
Spacer(Modifier.padding(vertical = 5.dp))
|
Spacer(Modifier.padding(vertical = 5.dp))
|
||||||
|
|
||||||
AnimatedVisibility(showDeviceAdminButton && showDeviceOwnerButton) {
|
AnimatedVisibility(showDeviceOwnerButton, modifier = Modifier.align(Alignment.CenterHorizontally)) {
|
||||||
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) {
|
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
coScope.launch{
|
coScope.launch{
|
||||||
@@ -139,8 +118,7 @@ fun Shizuku(vm: MyViewModel, navCtrl: NavHostController) {
|
|||||||
delay(500)
|
delay(500)
|
||||||
showDeviceOwnerButton = !context.isDeviceOwner
|
showDeviceOwnerButton = !context.isDeviceOwner
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
modifier = Modifier.align(Alignment.CenterHorizontally)
|
|
||||||
) {
|
) {
|
||||||
Text(text = stringResource(R.string.activate_device_owner))
|
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 {
|
val userServiceConnection = object : ServiceConnection {
|
||||||
override fun onServiceConnected(componentName: ComponentName, binder: IBinder) {
|
override fun onServiceConnected(componentName: ComponentName, binder: IBinder) {
|
||||||
shizukuBinder.value = binder
|
onServiceConnected(binder)
|
||||||
}
|
}
|
||||||
override fun onServiceDisconnected(componentName: ComponentName) {
|
override fun onServiceDisconnected(componentName: ComponentName) {
|
||||||
shizukuBinder.value = null
|
onServiceDisconnected()
|
||||||
Toast.makeText(context, R.string.shizuku_service_disconnected, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val userServiceArgs = Shizuku.UserServiceArgs(ComponentName(context, ShizukuService::class.java))
|
val userServiceArgs = Shizuku.UserServiceArgs(ComponentName(context, ShizukuService::class.java))
|
||||||
@@ -194,3 +175,24 @@ fun bindShizukuService(context: Context, shizukuBinder: MutableStateFlow<IBinder
|
|||||||
e.printStackTrace()
|
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
|
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 android.system.Os
|
||||||
import androidx.annotation.Keep
|
import androidx.annotation.Keep
|
||||||
import com.bintianqi.owndroid.IUserService
|
import com.bintianqi.owndroid.IUserService
|
||||||
|
import com.bintianqi.owndroid.getContext
|
||||||
import java.io.BufferedReader
|
import java.io.BufferedReader
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
|
import java.lang.Class
|
||||||
|
|
||||||
@Keep
|
@Keep
|
||||||
class ShizukuService: IUserService.Stub() {
|
class ShizukuService: IUserService.Stub() {
|
||||||
@@ -33,4 +41,10 @@ class ShizukuService: IUserService.Stub() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getUid(): Int = Os.getuid()
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,7 +122,7 @@
|
|||||||
<string name="activate_device_owner">Активировать владельца устройства</string>
|
<string name="activate_device_owner">Активировать владельца устройства</string>
|
||||||
<string name="activate_org_profile">Активировать рабочий профиль, принадлежащий организации</string>
|
<string name="activate_org_profile">Активировать рабочий профиль, принадлежащий организации</string>
|
||||||
<string name="shizuku_service_disconnected">Служба Shizuku отключена</string>
|
<string name="shizuku_service_disconnected">Служба Shizuku отключена</string>
|
||||||
|
<string name="accounts">Accounts</string> <!--TODO-->
|
||||||
|
|
||||||
<!--Системные-->
|
<!--Системные-->
|
||||||
<string name="system">Syetem</string> <!--TODO-->
|
<string name="system">Syetem</string> <!--TODO-->
|
||||||
|
|||||||
@@ -124,6 +124,7 @@
|
|||||||
<string name="activate_device_owner">Cihaz Sahibini Etkinleştir</string>
|
<string name="activate_device_owner">Cihaz Sahibini Etkinleştir</string>
|
||||||
<string name="activate_org_profile">Kuruluş Profili Sahibini Etkinleştir</string>
|
<string name="activate_org_profile">Kuruluş Profili Sahibini Etkinleştir</string>
|
||||||
<string name="shizuku_service_disconnected">Shizuku Hizmeti Bağlantısı Kesildi</string>
|
<string name="shizuku_service_disconnected">Shizuku Hizmeti Bağlantısı Kesildi</string>
|
||||||
|
<string name="accounts">Accounts</string> <!--TODO-->
|
||||||
|
|
||||||
<!--System-->
|
<!--System-->
|
||||||
<string name="system">Sistem</string>
|
<string name="system">Sistem</string>
|
||||||
|
|||||||
@@ -118,6 +118,7 @@
|
|||||||
<string name="activate_device_owner">激活Device owner</string>
|
<string name="activate_device_owner">激活Device owner</string>
|
||||||
<string name="activate_org_profile">激活由组织拥有的工作资料</string>
|
<string name="activate_org_profile">激活由组织拥有的工作资料</string>
|
||||||
<string name="shizuku_service_disconnected">Shizuku服务断开连接</string>
|
<string name="shizuku_service_disconnected">Shizuku服务断开连接</string>
|
||||||
|
<string name="accounts">账号</string>
|
||||||
|
|
||||||
<!--System-->
|
<!--System-->
|
||||||
<string name="system">系统</string>
|
<string name="system">系统</string>
|
||||||
@@ -661,7 +662,7 @@
|
|||||||
<string name="info_security_log">设备上不能有非附属用户</string>
|
<string name="info_security_log">设备上不能有非附属用户</string>
|
||||||
<string name="info_pre_reboot_security_log">并非所有设备都支持重启前安全日志</string>
|
<string name="info_pre_reboot_security_log">并非所有设备都支持重启前安全日志</string>
|
||||||
<string name="info_disable_account_management">当某个帐户类型的帐户管理被禁用时,将无法添加或删除该类型的帐户。</string>
|
<string name="info_disable_account_management">当某个帐户类型的帐户管理被禁用时,将无法添加或删除该类型的帐户。</string>
|
||||||
<string name="info_frp_policy">恢复出厂设置保护(Factory reset protection)策略用于防止不受信任的重置(Fastboot或Recovery)。需要设备支持持久数据块服务(Persistent data block service)</string>
|
<string name="info_frp_policy">恢复出厂设置保护(Factory reset protection)策略决定哪些帐户可以解锁经过不受信任的恢复出厂设置(fastboot或recovery)的设备。\n要启用此功能,设备必须支持持久数据块服务(Persistent data block service)。\n如果在开发者选项中启用了OEM解锁,则FRP将被禁用。</string>
|
||||||
<string name="info_wipe_data_in_managed_user">此用户的所有数据将会被清除,但是用户不会被删除。</string>
|
<string name="info_wipe_data_in_managed_user">此用户的所有数据将会被清除,但是用户不会被删除。</string>
|
||||||
<string name="info_lockdown_admin_configured_network">控制用户是否可以更改管理员配置的网络。启用此锁定后,用户仍然可以配置和连接到其他Wi-Fi,或使用其他Wi-Fi功能(如网络共享)。</string>
|
<string name="info_lockdown_admin_configured_network">控制用户是否可以更改管理员配置的网络。启用此锁定后,用户仍然可以配置和连接到其他Wi-Fi,或使用其他Wi-Fi功能(如网络共享)。</string>
|
||||||
<string name="info_minimum_wifi_security_level">指定Wi-Fi网络所需的最低安全等级。设备将无法连接到低于最低安全等级的网络。如果当前网络不满足要求,则会断开连接。</string>
|
<string name="info_minimum_wifi_security_level">指定Wi-Fi网络所需的最低安全等级。设备将无法连接到低于最低安全等级的网络。如果当前网络不满足要求,则会断开连接。</string>
|
||||||
|
|||||||
@@ -127,10 +127,10 @@
|
|||||||
<string name="list_accounts">List accounts</string>
|
<string name="list_accounts">List accounts</string>
|
||||||
<string name="shizuku_not_started">Shizuku not started. </string>
|
<string name="shizuku_not_started">Shizuku not started. </string>
|
||||||
<string name="dpm_activate_do_command" translatable="false">dpm set-device-owner com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver</string>
|
<string name="dpm_activate_do_command" translatable="false">dpm set-device-owner com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver</string>
|
||||||
<string name="dpm_activate_da_command" translatable="false">dpm set-active-admin com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver</string>
|
|
||||||
<string name="activate_device_owner">Activate Device owner</string>
|
<string name="activate_device_owner">Activate Device owner</string>
|
||||||
<string name="activate_org_profile">Activate organization-owned work profile</string>
|
<string name="activate_org_profile">Activate organization-owned work profile</string>
|
||||||
<string name="shizuku_service_disconnected">Shizuku service disconnected</string>
|
<string name="shizuku_service_disconnected">Shizuku service disconnected</string>
|
||||||
|
<string name="accounts">Accounts</string>
|
||||||
|
|
||||||
<!--System-->
|
<!--System-->
|
||||||
<string name="system">System</string>
|
<string name="system">System</string>
|
||||||
@@ -701,7 +701,7 @@
|
|||||||
<string name="info_security_log">If a Device owner use this function, all users should be affiliated.</string>
|
<string name="info_security_log">If a Device owner use this function, all users should be affiliated.</string>
|
||||||
<string name="info_pre_reboot_security_log">Not all devices support pre-reboot security logs.</string>
|
<string name="info_pre_reboot_security_log">Not all devices support pre-reboot security logs.</string>
|
||||||
<string name="info_disable_account_management">When account management is disabled for an account type, adding or removing an account of that type will not be possible.</string>
|
<string name="info_disable_account_management">When account management is disabled for an account type, adding or removing an account of that type will not be possible.</string>
|
||||||
<string name="info_frp_policy">Factory reset protection can protect the device after untrusted factory reset (in Recovery or Fastboot).\nTo enable this feature, the device must support persistent data block service.</string>
|
<string name="info_frp_policy">The factory reset protection policy determines which accounts can unlock a device that has gone through untrusted factory reset(fastboot or recovery).\nTo enable this feature, the device must support persistent data block service.\nFactory reset protection is disabled if OEM unlocking is enabled in Developer Options.</string>
|
||||||
<string name="info_wipe_data_in_managed_user">All data of this user will be wiped, but that user won\'t be removed.</string>
|
<string name="info_wipe_data_in_managed_user">All data of this user will be wiped, but that user won\'t be removed.</string>
|
||||||
<string name="info_lockdown_admin_configured_network">Control whether the user can change networks configured by the admin.\nWhen this lockdown is enabled, the user can still configure and connect to other Wi-Fi networks, or use other Wi-Fi capabilities such as tethering.</string>
|
<string name="info_lockdown_admin_configured_network">Control whether the user can change networks configured by the admin.\nWhen this lockdown is enabled, the user can still configure and connect to other Wi-Fi networks, or use other Wi-Fi capabilities such as tethering.</string>
|
||||||
<string name="info_minimum_wifi_security_level">Specify the minimum security level required for Wi-Fi networks. The device may not connect to networks that do not meet the minimum security level. If the current network does not meet the minimum security level set, it will be disconnected.</string>
|
<string name="info_minimum_wifi_security_level">Specify the minimum security level required for Wi-Fi networks. The device may not connect to networks that do not meet the minimum security level. If the current network does not meet the minimum security level set, it will be disconnected.</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user