optimize shizuku coroutine

This commit is contained in:
BinTianqi
2024-03-03 13:55:23 +08:00
parent e27d4b41b2
commit f4fa42c4fc
2 changed files with 79 additions and 73 deletions

View File

@@ -36,6 +36,9 @@ 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 kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.apache.commons.io.IOUtils
import rikka.shizuku.Shizuku
import java.io.*
@@ -50,9 +53,10 @@ fun ShizukuActivate(){
val isWear = sharedPref.getBoolean("isWear",false)
val bodyTextStyle = if(isWear){ typography.bodyMedium }else{ typography.bodyLarge }
val filesDir = myContext.filesDir
var launchExtractRish by remember{mutableStateOf(true)}
LaunchedEffect(launchExtractRish){ if(launchExtractRish){ extractRish(myContext);launchExtractRish=false } }
LaunchedEffect(Unit){ extractRish(myContext) }
val coScope = rememberCoroutineScope()
val scrollState = rememberScrollState()
val outputTextScrollState = rememberScrollState()
Column(modifier = Modifier.verticalScroll(scrollState)){
var outputText by remember{mutableStateOf("")}
if(Binder.getCallingUid()/100000!=0){
@@ -82,40 +86,40 @@ fun ShizukuActivate(){
Text(text = stringResource(R.string.activate), style = typography.titleLarge, color = colorScheme.onPrimaryContainer)
if(!myDpm.isAdminActive(myComponent)){
var launchActivateDA by remember{mutableStateOf(false)}
LaunchedEffect(launchActivateDA){
if(launchActivateDA){
outputText = executeCommand("sh rish.sh", "dpm set-active-admin com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver", null, filesDir)
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
launchActivateDA=false
}
}
Button(onClick = {launchActivateDA=true}, modifier = Modifier.fillMaxWidth()) {
Button(
onClick = {
coScope.launch{
outputText = executeCommand(myContext, "sh rish.sh", myContext.getString(R.string.dpm_activate_da_command), null, filesDir)
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
outputTextScrollState.animateScrollTo(0, scrollAnim())
}
},
modifier = Modifier.fillMaxWidth()) {
Text(text = "Device admin")
}
}
var launchActivatePO by remember{mutableStateOf(false)}
LaunchedEffect(launchActivatePO){
if(launchActivatePO){
outputText = executeCommand("sh rish.sh", "dpm set-profile-owner com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver", null, filesDir)
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
launchActivatePO=false
}
}
Button(onClick = {launchActivatePO=true}, modifier = Modifier.fillMaxWidth()) {
Button(
onClick = {
coScope.launch{
outputText = executeCommand(myContext, "sh rish.sh", myContext.getString(R.string.dpm_activate_po_command), null, filesDir)
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
outputTextScrollState.animateScrollTo(0, scrollAnim())
}
},
modifier = Modifier.fillMaxWidth()) {
Text(text = "Profile owner")
}
var launchActivateDO by remember{mutableStateOf(false)}
LaunchedEffect(launchActivateDO){
if(launchActivateDO){
outputText = executeCommand("sh rish.sh", "dpm set-device-owner com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver", null, filesDir)
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
launchActivateDO=false
}
}
Button(onClick = {launchActivateDO=true}, modifier = Modifier.fillMaxWidth()) {
Button(
onClick = {
coScope.launch{
outputText = executeCommand(myContext, "sh rish.sh", myContext.getString(R.string.dpm_activate_do_command), null, filesDir)
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
outputTextScrollState.animateScrollTo(0, scrollAnim())
}
},
modifier = Modifier.fillMaxWidth()) {
Text(text = "Device owner")
}
@@ -134,24 +138,19 @@ fun ShizukuActivate(){
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
modifier = Modifier.focusable().fillMaxWidth().padding(vertical = 2.dp)
)
var launchActivateOrgProfile by remember{mutableStateOf(false)}
LaunchedEffect(launchActivateOrgProfile){
if(launchActivateOrgProfile){
focusMgr.clearFocus()
outputText = executeCommand(
"sh rish.sh",
"dpm mark-profile-owner-on-organization-owned-device --user $inputUserID com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver",
null, filesDir
)
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
launchActivateOrgProfile=false
}
}
Button(
onClick = {
launchActivateOrgProfile=true
if(myDpm.isOrganizationOwnedDeviceWithManagedProfile){
Toast.makeText(myContext, myContext.getString(R.string.success),Toast.LENGTH_SHORT).show()
coScope.launch{
focusMgr.clearFocus()
outputText = executeCommand(
myContext, "sh rish.sh", myContext.getString(R.string.activate_org_profile_command_with_user_id, inputUserID),
null, filesDir
)
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
outputTextScrollState.animateScrollTo(0, scrollAnim())
if(myDpm.isOrganizationOwnedDeviceWithManagedProfile){
Toast.makeText(myContext, myContext.getString(R.string.success),Toast.LENGTH_SHORT).show()
}
}
},
modifier = Modifier.fillMaxWidth()
@@ -161,36 +160,35 @@ fun ShizukuActivate(){
}
}
var launchListOwners by remember{mutableStateOf(false)}
LaunchedEffect(launchListOwners){
if(launchListOwners){
outputText=executeCommand("sh rish.sh","dpm list-owners",null,filesDir)
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
launchListOwners=false
}
}
Button(
onClick = {launchListOwners=true}, modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp)
onClick = {
coScope.launch{
outputText=executeCommand(myContext, "sh rish.sh","dpm list-owners",null,filesDir)
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
outputTextScrollState.animateScrollTo(0, scrollAnim())
}
},
modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp)
) {
Text(text = stringResource(R.string.list_owners))
}
var launchTest by remember{mutableStateOf(false)}
LaunchedEffect(launchTest){
if(launchTest){
outputText= myContext.getString(R.string.should_contain_2000_or_0)
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
outputText+=executeCommand("sh rish.sh","id",null,filesDir)
launchTest=false
}
}
Button(
onClick = {launchTest=true}, modifier = Modifier.align(Alignment.CenterHorizontally)
onClick = {
coScope.launch {
outputText= myContext.getString(R.string.should_contain_2000_or_0)
scrollState.animateScrollTo(scrollState.maxValue, scrollAnim())
outputTextScrollState.animateScrollTo(0, scrollAnim())
outputText+=executeCommand(myContext, "sh rish.sh","id",null,filesDir)
}
},
modifier = Modifier.align(Alignment.CenterHorizontally)
) {
Text(text = stringResource(R.string.test_rish))
}
SelectionContainer(modifier = Modifier.horizontalScroll(rememberScrollState())){
SelectionContainer(modifier = Modifier.horizontalScroll(outputTextScrollState)){
Text(text = outputText, style = bodyTextStyle, softWrap = false, modifier = Modifier.padding(4.dp))
}
@@ -227,25 +225,25 @@ private fun checkPermission(myContext: Context):String {
try{
if(Shizuku.checkSelfPermission()==PackageManager.PERMISSION_GRANTED) {
val permission = when(Shizuku.getUid()){ 0->"Root"; 2000->"Shell"; else->myContext.getString(R.string.unknown) }
myContext.getString(R.string.shizuku_permission_granted, Shizuku.getVersion(), permission)
myContext.getString(R.string.shizuku_permission_granted, Shizuku.getVersion().toString(), permission)
}else if(Shizuku.shouldShowRequestPermissionRationale()){ myContext.getString(R.string.denied) }
else{ Shizuku.requestPermission(0); myContext.getString(R.string.request_permission) }
}catch(e: Throwable){ myContext.getString(R.string.shizuku_not_started) }
}
}
fun executeCommand(command: String, subCommand:String, env: Array<String>?, dir:File?): String {
suspend fun executeCommand(myContext: Context, command: String, subCommand:String, env: Array<String>?, dir:File?): String {
var result = ""
val tunnel:ByteArrayInputStream
val process:Process
val outputStream:OutputStream
try {
tunnel = ByteArrayInputStream(subCommand.toByteArray())
process = Runtime.getRuntime().exec(command,env,dir)
process = withContext(Dispatchers.IO){Runtime.getRuntime().exec(command, env, dir)}
outputStream = process.outputStream
IOUtils.copy(tunnel,outputStream)
outputStream.close()
val exitCode = process.waitFor()
withContext(Dispatchers.IO){ outputStream.close() }
val exitCode = withContext(Dispatchers.IO){ process.waitFor() }
if(exitCode!=0){ result+="Error: $exitCode" }
}catch(e:Exception){
e.printStackTrace()
@@ -254,12 +252,13 @@ fun executeCommand(command: String, subCommand:String, env: Array<String>?, dir:
try {
val outputReader = BufferedReader(InputStreamReader(process.inputStream))
var outputLine: String
while(outputReader.readLine().also {outputLine = it}!=null) { result+="$outputLine\n" }
while(withContext(Dispatchers.IO){ 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" }
while(withContext(Dispatchers.IO){ errorReader.readLine() }.also {errorLine = it}!=null) { result+="$errorLine\n" }
} catch(e: NullPointerException) {
e.printStackTrace()
}
if(result==""){ return myContext.getString(R.string.try_again) }
return result
}

View File

@@ -39,6 +39,7 @@
<string name="unsupported">不支持</string>
<string name="developing">功能开发中</string>
<string name="place_holder" />
<string name="try_again">请再试一次</string>
<!--Permissions-->
<string name="activate_device_admin">激活Device admin</string>
@@ -85,9 +86,15 @@
<string name="should_contain_2000_or_0">下面应该出现一行包含“2000”或“0”的文本\n</string>
<string name="test_rish">测试rish</string>
<string name="please_update_shizuku">请更新Shizuku</string>
<string name="shizuku_permission_granted">Shizuku v%1$i\n已授权%2$s</string>
<string name="shizuku_permission_granted">Shizuku v%1$s\n已授权%2$s</string>
<string name="request_permission">请求授权</string>
<string name="shizuku_not_started">服务未启动</string>
<string name="activate_org_profile_command_with_user_id" tools:ignore="TypographyDashes">
dpm mark-profile-owner-on-organization-owned-device --user %1$s com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver
</string>
<string name="dpm_activate_do_command">dpm set-device-owner com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver</string>
<string name="dpm_activate_po_command">dpm set-profile-owner com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver</string>
<string name="dpm_activate_da_command">dpm set-active-admin com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver</string>
<!--System-->
<string name="device_ctrl">系统</string>