mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 11:05:59 +00:00
16
.gitignore
vendored
16
.gitignore
vendored
@@ -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
|
||||||
|
|||||||
@@ -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")
|
||||||
}
|
}
|
||||||
3
app/proguard-rules.pro
vendored
3
app/proguard-rules.pro
vendored
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.bintianqi.owndroid;
|
||||||
|
|
||||||
|
interface IUserService {
|
||||||
|
void destroy() = 16777114;
|
||||||
|
String execute(String command) = 1;
|
||||||
|
String getUid() = 2;
|
||||||
|
}
|
||||||
@@ -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.
@@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user