From f4fa42c4fc5f71580742b5ff52bacb4753808d33 Mon Sep 17 00:00:00 2001 From: BinTianqi <1220958406@qq.com> Date: Sun, 3 Mar 2024 13:55:23 +0800 Subject: [PATCH] optimize shizuku coroutine --- .../binbin/androidowner/ShizukuActivate.kt | 143 +++++++++--------- app/src/main/res/values/strings.xml | 9 +- 2 files changed, 79 insertions(+), 73 deletions(-) diff --git a/app/src/main/java/com/binbin/androidowner/ShizukuActivate.kt b/app/src/main/java/com/binbin/androidowner/ShizukuActivate.kt index d62eaf6..45db6fe 100644 --- a/app/src/main/java/com/binbin/androidowner/ShizukuActivate.kt +++ b/app/src/main/java/com/binbin/androidowner/ShizukuActivate.kt @@ -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?, dir:File?): String { +suspend fun executeCommand(myContext: Context, command: String, subCommand:String, env: Array?, 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?, 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 } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9992877..43c0fd8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -39,6 +39,7 @@ 不支持 功能开发中 + 请再试一次 激活Device admin @@ -85,9 +86,15 @@ 下面应该出现一行包含“2000”或“0”的文本\n 测试rish 请更新Shizuku - Shizuku v%1$i\n已授权(%2$s) + Shizuku v%1$s\n已授权(%2$s) 请求授权 服务未启动 + + dpm mark-profile-owner-on-organization-owned-device --user %1$s com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver + + dpm set-device-owner com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver + dpm set-profile-owner com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver + dpm set-active-admin com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver 系统