use Shizuku API instead of rish

#10
This commit is contained in:
BinTianqi
2024-04-23 13:44:22 +08:00
parent fe6d640d32
commit e78b9809ee
12 changed files with 205 additions and 134 deletions

16
.gitignore vendored
View File

@@ -1,13 +1,13 @@
*.iml *.iml
/.gradle .gradle
/local.properties local.properties
/.idea .idea
.DS_Store .DS_Store
/build build
/captures captures
.externalNativeBuild .externalNativeBuild
.cxx .cxx
local.properties app/build
/app/build app/release
/app/release app/debug
.androidide .androidide

View File

@@ -34,6 +34,7 @@ android {
} }
buildFeatures { buildFeatures {
compose = true compose = true
aidl = true
} }
composeOptions { composeOptions {
kotlinCompilerExtensionVersion = "1.5.1" kotlinCompilerExtensionVersion = "1.5.1"
@@ -56,4 +57,6 @@ dependencies {
implementation("com.google.accompanist:accompanist-drawablepainter:0.35.0-alpha") implementation("com.google.accompanist:accompanist-drawablepainter:0.35.0-alpha")
implementation("androidx.compose.material3:material3:1.2.0") implementation("androidx.compose.material3:material3:1.2.0")
implementation("androidx.navigation:navigation-compose:2.7.7") implementation("androidx.navigation:navigation-compose:2.7.7")
implementation("dev.rikka.shizuku:provider:13.1.5")
implementation("dev.rikka.shizuku:api:13.1.5")
} }

View File

@@ -12,6 +12,7 @@
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *; # public *;
#} #}
-keep class com.bintianqi.owndroid.dpm.ShizukuService
# Uncomment this to preserve the line number information for # Uncomment this to preserve the line number information for
# debugging stack traces. # debugging stack traces.
@@ -19,4 +20,4 @@
# If you keep the line number information, uncomment this to # If you keep the line number information, uncomment this to
# hide the original source file name. # hide the original source file name.
-renamesourcefileattribute SourceFile # -renamesourcefileattribute SourceFile

View File

@@ -19,6 +19,7 @@
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/> <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/>
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" /> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" />
<uses-sdk tools:overrideLibrary="rikka.shizuku.provider,rikka.shizuku.api,rikka.shizuku.shared,rikka.shizuku.aidl"/>
<application <application
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"
@@ -72,5 +73,12 @@
<action android:name="com.bintianqi.owndroid.PKG_INSTALL_RESULT"/> <action android:name="com.bintianqi.owndroid.PKG_INSTALL_RESULT"/>
</intent-filter> </intent-filter>
</receiver> </receiver>
<provider
android:name="rikka.shizuku.ShizukuProvider"
android:authorities="${applicationId}.shizuku"
android:multiprocess="false"
android:enabled="true"
android:exported="true"
android:permission="android.permission.INTERACT_ACROSS_USERS_FULL" />
</application> </application>
</manifest> </manifest>

View File

@@ -0,0 +1,7 @@
package com.bintianqi.owndroid;
interface IUserService {
void destroy() = 16777114;
String execute(String command) = 1;
String getUid() = 2;
}

View File

@@ -1,5 +0,0 @@
#!/system/bin/sh
BASEDIR=$(dirname "$0")
DEX="$BASEDIR"/rish_shizuku.dex
[ -z "$RISH_APPLICATION_ID" ] && export RISH_APPLICATION_ID="com.bintianqi.owndroid"
/system/bin/app_process -Djava.class.path="$DEX" /system/bin --nice-name=rish rikka.shizuku.shell.ShizukuShellLoader "$@"

Binary file not shown.

View File

@@ -25,4 +25,3 @@ fun isDeviceOwner(dpm: DevicePolicyManager): Boolean {
fun isProfileOwner(dpm: DevicePolicyManager): Boolean { fun isProfileOwner(dpm: DevicePolicyManager): Boolean {
return dpm.isProfileOwnerApp("com.bintianqi.owndroid") return dpm.isProfileOwnerApp("com.bintianqi.owndroid")
} }

View File

@@ -3,83 +3,87 @@ package com.bintianqi.owndroid.dpm
import android.app.admin.DevicePolicyManager import android.app.admin.DevicePolicyManager
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Context.MODE_PRIVATE import android.content.ServiceConnection
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.IBinder
import android.util.Log
import android.widget.Toast import android.widget.Toast
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.Spring import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.SpringSpec import androidx.compose.animation.core.SpringSpec
import androidx.compose.foundation.focusable
import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Warning
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
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.KeyboardType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.bintianqi.owndroid.IUserService
import com.bintianqi.owndroid.R import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.Receiver import com.bintianqi.owndroid.Receiver
import kotlinx.coroutines.Dispatchers import com.bintianqi.owndroid.backToHome
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import rikka.shizuku.Shizuku
import org.apache.commons.io.IOUtils
import java.io.*
@Composable @Composable
fun ShizukuActivate(){ fun ShizukuActivate(){
val myContext = LocalContext.current val myContext = LocalContext.current
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
val myComponent = ComponentName(myContext, Receiver::class.java) val myComponent = ComponentName(myContext, Receiver::class.java)
val focusMgr = LocalFocusManager.current
val filesDir = myContext.filesDir
LaunchedEffect(Unit){ extractRish(myContext) }
val coScope = rememberCoroutineScope() val coScope = rememberCoroutineScope()
val scrollState = rememberScrollState()
val outputTextScrollState = rememberScrollState() val outputTextScrollState = rememberScrollState()
var enabled by remember{ mutableStateOf(false) }
var bindShizuku by remember{ mutableStateOf(false) }
var outputText by remember{mutableStateOf("")}
LaunchedEffect(Unit){
if(service==null){userServiceControl(myContext, true)}
while(true){
if(service==null){
enabled = false
bindShizuku = checkShizukuStatus()==1
}else{
enabled = true
bindShizuku = false
}
delay(200)
}
}
Column( Column(
modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(scrollState), modifier = Modifier
.fillMaxSize()
.padding(horizontal = 8.dp)
.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
){ ){
var outputText by remember{mutableStateOf("")} AnimatedVisibility(bindShizuku) {
if(Binder.getCallingUid()/100000!=0){ Button(
Row{ onClick = {
Icon(imageVector = Icons.Rounded.Warning, contentDescription = null, tint = colorScheme.onErrorContainer) userServiceControl(myContext, true)
Text(text = stringResource(R.string.not_primary_user_not_support_shizuku), color = colorScheme.onErrorContainer) outputText = ""
}
){
Text(stringResource(R.string.bind_shizuku))
} }
} }
Button( Button(
onClick = { onClick = {
outputText = checkPermission(myContext)
coScope.launch { coScope.launch {
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
outputTextScrollState.animateScrollTo(0, scrollAnim()) outputTextScrollState.animateScrollTo(0, scrollAnim())
val getUid = executeCommand(myContext, "sh rish.sh","id -u",null,filesDir)
outputText = if(getUid.contains("2000")){
myContext.getString(R.string.shizuku_activated_shell)
}else if(getUid.contains("0")){
myContext.getString(R.string.shizuku_activated_root)
}else if(getUid.contains("Error: 1")){
myContext.getString(R.string.shizuku_not_started)
}else{
getUid
}
} }
} }
) { ) {
@@ -89,11 +93,11 @@ fun ShizukuActivate(){
Button( Button(
onClick = { onClick = {
coScope.launch{ coScope.launch{
outputText= executeCommand(myContext, "sh rish.sh","dpm list-owners",null,filesDir) outputText = service!!.execute("dpm list-owners")
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
outputTextScrollState.animateScrollTo(0, scrollAnim()) outputTextScrollState.animateScrollTo(0, scrollAnim())
} }
} },
enabled = enabled
) { ) {
Text(text = stringResource(R.string.list_owners)) Text(text = stringResource(R.string.list_owners))
} }
@@ -105,11 +109,13 @@ fun ShizukuActivate(){
Button( Button(
onClick = { onClick = {
coScope.launch{ coScope.launch{
outputText = executeCommand(myContext, "sh rish.sh", myContext.getString(R.string.dpm_activate_da_command), null, filesDir) outputText = service!!.execute(myContext.getString(R.string.dpm_activate_da_command))
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
outputTextScrollState.animateScrollTo(0, scrollAnim()) outputTextScrollState.animateScrollTo(0, scrollAnim())
delay(600)
if(myDpm.isAdminActive(myComponent)){backToHome=true}
} }
} },
enabled = enabled
) { ) {
Text(text = stringResource(R.string.activate_device_admin)) Text(text = stringResource(R.string.activate_device_admin))
} }
@@ -118,11 +124,13 @@ fun ShizukuActivate(){
Button( Button(
onClick = { onClick = {
coScope.launch{ coScope.launch{
outputText = executeCommand(myContext, "sh rish.sh", myContext.getString(R.string.dpm_activate_po_command), null, filesDir) outputText = service!!.execute(myContext.getString(R.string.dpm_activate_po_command))
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
outputTextScrollState.animateScrollTo(0, scrollAnim()) outputTextScrollState.animateScrollTo(0, scrollAnim())
delay(600)
if(isProfileOwner(myDpm)){backToHome=true}
} }
} },
enabled = enabled
) { ) {
Text(text = stringResource(R.string.activate_profile_owner)) Text(text = stringResource(R.string.activate_profile_owner))
} }
@@ -130,11 +138,13 @@ fun ShizukuActivate(){
Button( Button(
onClick = { onClick = {
coScope.launch{ coScope.launch{
outputText = executeCommand(myContext, "sh rish.sh", myContext.getString(R.string.dpm_activate_do_command), null, filesDir) outputText = service!!.execute(myContext.getString(R.string.dpm_activate_do_command))
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
outputTextScrollState.animateScrollTo(0, scrollAnim()) outputTextScrollState.animateScrollTo(0, scrollAnim())
delay(600)
if(isDeviceOwner(myDpm)){backToHome=true}
} }
} },
enabled = enabled
) { ) {
Text(text = stringResource(R.string.activate_device_owner)) Text(text = stringResource(R.string.activate_device_owner))
} }
@@ -143,43 +153,29 @@ fun ShizukuActivate(){
} }
if( if(
VERSION.SDK_INT>=30&&!isDeviceOwner(myDpm)&&!myDpm.isProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE)&& VERSION.SDK_INT>=30&&isProfileOwner(myDpm)&&myDpm.isManagedProfile(myComponent)
!myDpm.isOrganizationOwnedDeviceWithManagedProfile
){ ){
Column { Column {
Text(text = stringResource(R.string.org_owned_work_profile), style = typography.titleLarge, color = colorScheme.onPrimaryContainer)
Text(text = stringResource(R.string.input_userid_of_work_profile))
var inputUserID by remember{mutableStateOf("")}
OutlinedTextField(
value = inputUserID, onValueChange = {inputUserID=it},
label = {Text("UserID")},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
modifier = Modifier.focusable().fillMaxWidth().padding(vertical = 2.dp)
)
Button( Button(
onClick = { onClick = {
coScope.launch{ coScope.launch{
focusMgr.clearFocus() val userID = Binder.getCallingUid() / 100000
outputText = executeCommand( outputText = service!!.execute(
myContext, "sh rish.sh", myContext.getString(R.string.activate_org_profile_command_with_user_id, inputUserID), "dpm mark-profile-owner-on-organization-owned-device --user $userID com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver"
null, filesDir
) )
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
outputTextScrollState.animateScrollTo(0, scrollAnim()) outputTextScrollState.animateScrollTo(0, scrollAnim())
if(myDpm.isOrganizationOwnedDeviceWithManagedProfile){
Toast.makeText(myContext, myContext.getString(R.string.success),Toast.LENGTH_SHORT).show()
}
} }
}, },
modifier = Modifier.fillMaxWidth() enabled = enabled
) { ) {
Text(text = stringResource(R.string.activate)) Text(text = stringResource(R.string.activate_org_profile))
} }
} }
} }
SelectionContainer(modifier = Modifier.align(Alignment.Start).horizontalScroll(outputTextScrollState)){ SelectionContainer(modifier = Modifier
.align(Alignment.Start)
.horizontalScroll(outputTextScrollState)){
Text(text = outputText, softWrap = false, modifier = Modifier.padding(4.dp)) Text(text = outputText, softWrap = false, modifier = Modifier.padding(4.dp))
} }
@@ -194,48 +190,53 @@ fun <T> scrollAnim(
visibilityThreshold: T? = null visibilityThreshold: T? = null
): SpringSpec<T> = SpringSpec(dampingRatio, stiffness, visibilityThreshold) ): SpringSpec<T> = SpringSpec(dampingRatio, stiffness, visibilityThreshold)
fun extractRish(myContext:Context){ private fun checkPermission(context: Context):String{
val assetsMgr = myContext.assets if(checkShizukuStatus()==-1){return context.getString(R.string.shizuku_not_started)}
myContext.deleteFile("rish.sh") val getUid = if(service==null){return context.getString(R.string.shizuku_not_bind)}else{service!!.uid}
myContext.deleteFile("rish_shizuku.dex") return when(getUid){
val shInput = assetsMgr.open("rish.sh") "2000"->context.getString(R.string.shizuku_activated_shell)
val shOutput = myContext.openFileOutput("rish.sh",MODE_PRIVATE) "0"->context.getString(R.string.shizuku_activated_root)
IOUtils.copy(shInput,shOutput) else->context.getString(R.string.unknown_status)+"\nUID: $getUid"
shOutput.close() }
val dexInput = assetsMgr.open("rish_shizuku.dex")
val dexOutput = myContext.openFileOutput("rish_shizuku.dex",MODE_PRIVATE)
IOUtils.copy(dexInput,dexOutput)
dexOutput.close()
if(VERSION.SDK_INT>=34){ Runtime.getRuntime().exec("chmod 400 rish_shizuku.dex",null,myContext.filesDir) }
} }
suspend fun executeCommand(myContext: Context, command: String, subCommand:String, env: Array<String>?, dir:File?): String { fun checkShizukuStatus():Int{
var result = "" val status = try {
val tunnel:ByteArrayInputStream if (Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) { 1 }
val process:Process else if (Shizuku.shouldShowRequestPermissionRationale()) { 0 }
val outputStream:OutputStream else { Shizuku.requestPermission(0); 0 }
try { }catch(e:Exception){ -1 }
tunnel = ByteArrayInputStream(subCommand.toByteArray()) Log.e("Shizuku",status.toString())
process = withContext(Dispatchers.IO){Runtime.getRuntime().exec(command, env, dir)} return status
outputStream = process.outputStream }
IOUtils.copy(tunnel,outputStream)
withContext(Dispatchers.IO){ outputStream.close() } fun userServiceControl(context:Context, status:Boolean){
val exitCode = withContext(Dispatchers.IO){ process.waitFor() } if(checkShizukuStatus()!=1){ return }
if(exitCode!=0){ result+="Error: $exitCode" } val userServiceConnection = object : ServiceConnection {
}catch(e:Exception){ override fun onServiceConnected(componentName: ComponentName, binder: IBinder) {
e.printStackTrace() if (binder.pingBinder()) {
return e.toString() service = IUserService.Stub.asInterface(binder)
} } else {
try { Toast.makeText(context,context.getString(R.string.invalid_binder),Toast.LENGTH_SHORT).show()
val outputReader = BufferedReader(InputStreamReader(process.inputStream)) }
var outputLine: String }
while(withContext(Dispatchers.IO){ outputReader.readLine() }.also {outputLine = it}!=null) { result+="$outputLine\n" } override fun onServiceDisconnected(componentName: ComponentName) {
val errorReader = BufferedReader(InputStreamReader(process.errorStream)) service = null
var errorLine: String Toast.makeText(context,context.getString(R.string.shizuku_service_disconnected),Toast.LENGTH_SHORT).show()
while(withContext(Dispatchers.IO){ errorReader.readLine() }.also {errorLine = it}!=null) { result+="$errorLine\n" } }
} catch(e: NullPointerException) { }
e.printStackTrace() val userServiceArgs = Shizuku.UserServiceArgs(
} ComponentName(
if(result==""){ return myContext.getString(R.string.try_again) } context.packageName,ShizukuService::class.java.name
return result )
)
.daemon(false)
.processNameSuffix("service")
.debuggable(true)
.version(26)
if(status){
Shizuku.bindUserService(userServiceArgs,userServiceConnection)
}else{
Shizuku.unbindUserService(userServiceArgs,userServiceConnection,false)
}
} }

View File

@@ -0,0 +1,46 @@
package com.bintianqi.owndroid.dpm
import android.os.IBinder
import android.system.Os
import com.bintianqi.owndroid.IUserService
import java.io.BufferedReader
import java.io.InputStreamReader
var service:IUserService? = null
class ShizukuService: IUserService.Stub() {
override fun asBinder(): IBinder {
TODO("Not yet implemented")
}
override fun destroy(){ }
override fun execute(command: String?): String {
var result = ""
val process:Process
try {
process = Runtime.getRuntime().exec(command)
val exitCode = process.waitFor()
if(exitCode!=0){ result+="Error: $exitCode" }
}catch(e:Exception){
e.printStackTrace()
return e.toString()
}
try {
val outputReader = BufferedReader(InputStreamReader(process.inputStream))
var outputLine: String
while(outputReader.readLine().also {outputLine = it}!=null) { result+="$outputLine\n" }
val errorReader = BufferedReader(InputStreamReader(process.errorStream))
var errorLine: String
while(errorReader.readLine().also {errorLine = it}!=null) { result+="$errorLine\n" }
} catch(e: NullPointerException) {
e.printStackTrace()
}
if(result==""){ return "No result" }
return result
}
override fun getUid(): String {
return Os.getuid().toString()
}
}

View File

@@ -41,6 +41,7 @@
<string name="unknown_effect">效果未知</string> <string name="unknown_effect">效果未知</string>
<string name="options">选项</string> <string name="options">选项</string>
<string name="copy_command">复制代码</string> <string name="copy_command">复制代码</string>
<string name="unknown_status">未知状态</string>
<!--Permissions--> <!--Permissions-->
<string name="device_admin">Device admin</string> <string name="device_admin">Device admin</string>
@@ -83,6 +84,12 @@
<string name="shizuku_activated_root">已授权Root</string> <string name="shizuku_activated_root">已授权Root</string>
<string name="activate_profile_owner">激活Profile owner</string> <string name="activate_profile_owner">激活Profile owner</string>
<string name="activate_device_owner">激活Device owner</string> <string name="activate_device_owner">激活Device owner</string>
<string name="activate_org_profile">激活由组织拥有的工作资料</string>
<string name="shizuku_service_disconnected">Shizuku服务断开连接</string>
<string name="shizuku_not_bind">Shizuku未连接</string>
<string name="invalid_binder">无效Binder</string>
<string name="bind_shizuku">连接Shizuku</string>
<string name="shizuku_permission_denied">未授权</string>
<!--System--> <!--System-->
<string name="system_manage">系统</string> <string name="system_manage">系统</string>

View File

@@ -44,6 +44,7 @@
<string name="copy_command">Copy Command</string> <string name="copy_command">Copy Command</string>
<string name="package_name">Package name</string> <string name="package_name">Package name</string>
<string name="not_exist">Not exist</string> <string name="not_exist">Not exist</string>
<string name="unknown_status">Unknown status</string>
<!--Permissions--> <!--Permissions-->
<string name="device_admin">Device admin</string> <string name="device_admin">Device admin</string>
@@ -87,9 +88,6 @@
<string name="input_userid_of_work_profile">Enter UserID of work profile</string> <string name="input_userid_of_work_profile">Enter UserID of work profile</string>
<string name="list_owners">List owners</string> <string name="list_owners">List owners</string>
<string name="shizuku_not_started">Shizuku not started. </string> <string name="shizuku_not_started">Shizuku not started. </string>
<string name="activate_org_profile_command_with_user_id" tools:ignore="TypographyDashes" translatable="false">
dpm mark-profile-owner-on-organization-owned-device --user %1$s 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_do_command" translatable="false">dpm set-device-owner com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver</string>
<string name="dpm_activate_po_command" translatable="false">dpm set-profile-owner com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver</string> <string name="dpm_activate_po_command" translatable="false">dpm set-profile-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="dpm_activate_da_command" translatable="false">dpm set-active-admin com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver</string>
@@ -97,6 +95,12 @@
<string name="shizuku_activated_root">Permission granted (Root)</string> <string name="shizuku_activated_root">Permission granted (Root)</string>
<string name="activate_profile_owner">Activate profile owner</string> <string name="activate_profile_owner">Activate profile owner</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="shizuku_service_disconnected">Shizuku service disconnected</string>
<string name="invalid_binder">Invalid binder</string>
<string name="bind_shizuku">Connect Shizuku</string>
<string name="shizuku_not_bind">Shizuku disconnected</string>
<string name="shizuku_permission_denied">Permission denied</string>
<!--System--> <!--System-->
<string name="system_manage">System manager</string> <string name="system_manage">System manager</string>