optimize shizuku related function and wifi ssid poliicy

This commit is contained in:
BinTianqi
2024-05-29 18:58:12 +08:00
parent 3fd00a5ce0
commit 5027c22626
6 changed files with 194 additions and 135 deletions

View File

@@ -3,17 +3,25 @@ package com.bintianqi.owndroid
import android.Manifest import android.Manifest
import android.os.Build.VERSION import android.os.Build.VERSION
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
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.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material3.* import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.alpha
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.navigation.NavHostController import androidx.navigation.NavHostController
import com.bintianqi.owndroid.dpm.applySelectedPermission
import com.bintianqi.owndroid.dpm.selectedPermission import com.bintianqi.owndroid.dpm.selectedPermission
import com.bintianqi.owndroid.ui.NavIcon import com.bintianqi.owndroid.ui.NavIcon
@@ -37,8 +45,7 @@ fun PermissionPicker(navCtrl: NavHostController) {
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.clickable{ .clickable{
selectedPermission = it.first selectedPermission.value = it.first
applySelectedPermission.value = true
navCtrl.navigateUp() navCtrl.navigateUp()
} }
.padding(vertical = 6.dp, horizontal = 8.dp) .padding(vertical = 6.dp, horizontal = 8.dp)

View File

@@ -337,17 +337,18 @@ private fun PermissionManage(pkgName: String, navCtrl: NavHostController) {
val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
val receiver = ComponentName(context,Receiver::class.java) val receiver = ComponentName(context,Receiver::class.java)
val focusMgr = LocalFocusManager.current val focusMgr = LocalFocusManager.current
var inputPermission by remember{mutableStateOf(selectedPermission)} var inputPermission by remember { mutableStateOf("") }
var currentState by remember{mutableStateOf(context.getString(R.string.unknown))} var currentState by remember { mutableStateOf(context.getString(R.string.unknown)) }
val grantState = mapOf( val grantState = mapOf(
PERMISSION_GRANT_STATE_DEFAULT to stringResource(R.string.decide_by_user), PERMISSION_GRANT_STATE_DEFAULT to stringResource(R.string.decide_by_user),
PERMISSION_GRANT_STATE_GRANTED to stringResource(R.string.granted), PERMISSION_GRANT_STATE_GRANTED to stringResource(R.string.granted),
PERMISSION_GRANT_STATE_DENIED to stringResource(R.string.denied) PERMISSION_GRANT_STATE_DENIED to stringResource(R.string.denied)
) )
LaunchedEffect(applySelectedPermission.collectAsState()) { val applyPermission by selectedPermission.collectAsState()
if(applySelectedPermission.value) { LaunchedEffect(applyPermission) {
inputPermission = selectedPermission if(applyPermission != "") {
applySelectedPermission.value = false inputPermission = applyPermission
selectedPermission.value = ""
} }
} }
LaunchedEffect(pkgName) { LaunchedEffect(pkgName) {
@@ -361,7 +362,7 @@ private fun PermissionManage(pkgName: String, navCtrl: NavHostController) {
value = inputPermission, value = inputPermission,
label = { Text(stringResource(R.string.permission)) }, label = { Text(stringResource(R.string.permission)) },
onValueChange = { onValueChange = {
inputPermission = it; selectedPermission = inputPermission inputPermission = it
currentState = grantState[dpm.getPermissionGrantState(receiver,pkgName,inputPermission)]!! currentState = grantState[dpm.getPermissionGrantState(receiver,pkgName,inputPermission)]!!
}, },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Ascii, imeAction = ImeAction.Done), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Ascii, imeAction = ImeAction.Done),
@@ -577,7 +578,7 @@ private fun CredentialManagePolicy(pkgName: String) {
AnimatedVisibility(policyType != -1) { AnimatedVisibility(policyType != -1) {
Column { Column {
Text(stringResource(R.string.app_list_is)) Text(stringResource(R.string.app_list_is))
SelectionContainer(modifier = Modifier.horizontalScroll(rememberScrollState()).animateContentSize(scrollAnim())) { SelectionContainer(modifier = Modifier.horizontalScroll(rememberScrollState()).animateContentSize()) {
Text(text = if(credentialList.isEmpty()) stringResource(R.string.none) else credentialList.toText()) Text(text = if(credentialList.isEmpty()) stringResource(R.string.none) else credentialList.toText())
} }
Spacer(Modifier.padding(vertical = 10.dp)) Spacer(Modifier.padding(vertical = 10.dp))
@@ -739,7 +740,7 @@ private fun PermittedIME(pkgName: String) {
} }
AnimatedVisibility(!allowAll) { AnimatedVisibility(!allowAll) {
Column { Column {
SelectionContainer(modifier = Modifier.horizontalScroll(rememberScrollState()).animateContentSize(scrollAnim())) { SelectionContainer(modifier = Modifier.horizontalScroll(rememberScrollState()).animateContentSize()) {
if(permittedIme.isEmpty()) { if(permittedIme.isEmpty()) {
Text(stringResource(R.string.only_system_ime_allowed)) Text(stringResource(R.string.only_system_ime_allowed))
} else { } else {
@@ -805,7 +806,7 @@ private fun KeepUninstalledApp(pkgName: String) {
Text(text = stringResource(R.string.keep_uninstalled_packages), style = typography.headlineLarge) Text(text = stringResource(R.string.keep_uninstalled_packages), style = typography.headlineLarge)
Spacer(Modifier.padding(vertical = 5.dp)) Spacer(Modifier.padding(vertical = 5.dp))
Text(text = stringResource(R.string.app_list_is)) Text(text = stringResource(R.string.app_list_is))
SelectionContainer(modifier = Modifier.horizontalScroll(rememberScrollState()).animateContentSize(scrollAnim())) { SelectionContainer(modifier = Modifier.horizontalScroll(rememberScrollState()).animateContentSize()) {
Text(text = if(pkgList.isEmpty()) stringResource(R.string.none) else pkgList.toText()) Text(text = if(pkgList.isEmpty()) stringResource(R.string.none) else pkgList.toText())
} }
Spacer(Modifier.padding(vertical = 5.dp)) Spacer(Modifier.padding(vertical = 5.dp))
@@ -926,7 +927,7 @@ private fun InstallApp() {
@SuppressLint("NewApi") @SuppressLint("NewApi")
@Composable @Composable
fun ClearAppDataDialog(status: MutableState<Boolean>, pkgName: String) { private fun ClearAppDataDialog(status: MutableState<Boolean>, pkgName: String) {
val context = LocalContext.current val context = LocalContext.current
val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
val receiver = ComponentName(context,Receiver::class.java) val receiver = ComponentName(context,Receiver::class.java)
@@ -972,7 +973,7 @@ fun ClearAppDataDialog(status: MutableState<Boolean>, pkgName: String) {
@SuppressLint("NewApi") @SuppressLint("NewApi")
@Composable @Composable
fun DefaultDialerAppDialog(status: MutableState<Boolean>, pkgName: String) { private fun DefaultDialerAppDialog(status: MutableState<Boolean>, pkgName: String) {
val context = LocalContext.current val context = LocalContext.current
val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
AlertDialog( AlertDialog(
@@ -1008,7 +1009,7 @@ fun DefaultDialerAppDialog(status: MutableState<Boolean>, pkgName: String) {
} }
@Composable @Composable
fun AppControlDialog(status: MutableIntState) { private fun AppControlDialog(status: MutableIntState) {
val enabled = dialogGetStatus() val enabled = dialogGetStatus()
Dialog( Dialog(
onDismissRequest = { status.intValue = 0 } onDismissRequest = { status.intValue = 0 }

View File

@@ -5,8 +5,7 @@ import android.content.Intent
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
var selectedPermission = "" var selectedPermission = MutableStateFlow("")
var applySelectedPermission = MutableStateFlow(false)
lateinit var createManagedProfile: ActivityResultLauncher<Intent> lateinit var createManagedProfile: ActivityResultLauncher<Intent>
lateinit var addDeviceAdmin: ActivityResultLauncher<Intent> lateinit var addDeviceAdmin: ActivityResultLauncher<Intent>

View File

@@ -2,7 +2,17 @@ package com.bintianqi.owndroid.dpm
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.admin.DevicePolicyManager import android.app.admin.DevicePolicyManager
import android.app.admin.DevicePolicyManager.* import android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_OFF
import android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_OPPORTUNISTIC
import android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME
import android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_UNKNOWN
import android.app.admin.DevicePolicyManager.PRIVATE_DNS_SET_ERROR_FAILURE_SETTING
import android.app.admin.DevicePolicyManager.PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING
import android.app.admin.DevicePolicyManager.PRIVATE_DNS_SET_NO_ERROR
import android.app.admin.DevicePolicyManager.WIFI_SECURITY_ENTERPRISE_192
import android.app.admin.DevicePolicyManager.WIFI_SECURITY_ENTERPRISE_EAP
import android.app.admin.DevicePolicyManager.WIFI_SECURITY_OPEN
import android.app.admin.DevicePolicyManager.WIFI_SECURITY_PERSONAL
import android.app.admin.WifiSsidPolicy import android.app.admin.WifiSsidPolicy
import android.app.admin.WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_ALLOWLIST import android.app.admin.WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_ALLOWLIST
import android.app.admin.WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_DENYLIST import android.app.admin.WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_DENYLIST
@@ -11,21 +21,56 @@ import android.net.wifi.WifiSsid
import android.os.Build.VERSION import android.os.Build.VERSION
import android.telephony.TelephonyManager import android.telephony.TelephonyManager
import android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID import android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID
import android.telephony.data.ApnSetting.* import android.telephony.data.ApnSetting.AUTH_TYPE_CHAP
import android.telephony.data.ApnSetting.AUTH_TYPE_NONE
import android.telephony.data.ApnSetting.AUTH_TYPE_PAP
import android.telephony.data.ApnSetting.AUTH_TYPE_PAP_OR_CHAP
import android.telephony.data.ApnSetting.Builder
import android.telephony.data.ApnSetting.MVNO_TYPE_GID
import android.telephony.data.ApnSetting.MVNO_TYPE_ICCID
import android.telephony.data.ApnSetting.MVNO_TYPE_IMSI
import android.telephony.data.ApnSetting.MVNO_TYPE_SPN
import android.telephony.data.ApnSetting.PROTOCOL_IP
import android.telephony.data.ApnSetting.PROTOCOL_IPV4V6
import android.telephony.data.ApnSetting.PROTOCOL_IPV6
import android.telephony.data.ApnSetting.PROTOCOL_NON_IP
import android.telephony.data.ApnSetting.PROTOCOL_PPP
import android.telephony.data.ApnSetting.PROTOCOL_UNSTRUCTURED
import android.util.Log 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.AnimatedVisibility
import androidx.compose.animation.animateContentSize import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.* import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.layout.* import androidx.compose.foundation.focusable
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material3.* import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme.colorScheme import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme.typography import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.runtime.* import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
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.alpha import androidx.compose.ui.draw.alpha
@@ -44,9 +89,12 @@ import androidx.navigation.compose.rememberNavController
import com.bintianqi.owndroid.R import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.Receiver import com.bintianqi.owndroid.Receiver
import com.bintianqi.owndroid.toText import com.bintianqi.owndroid.toText
import com.bintianqi.owndroid.ui.* import com.bintianqi.owndroid.ui.Animations
import com.bintianqi.owndroid.ui.RadioButtonItem
import com.bintianqi.owndroid.ui.SubPageItem
import com.bintianqi.owndroid.ui.SwitchItem
import com.bintianqi.owndroid.ui.TopBar
var ssidSet = mutableSetOf<WifiSsid>()
@Composable @Composable
fun Network(navCtrl: NavHostController) { fun Network(navCtrl: NavHostController) {
val localNavCtrl = rememberNavController() val localNavCtrl = rememberNavController()
@@ -197,16 +245,15 @@ private fun WifiSsidPolicy() {
val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
val focusMgr = LocalFocusManager.current val focusMgr = LocalFocusManager.current
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())) { Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())) {
var policy = dpm.wifiSsidPolicy var selectedPolicyType by remember { mutableIntStateOf(-1) }
var selectedPolicyType by remember { mutableIntStateOf(policy?.policyType ?: -1) } val ssidList = remember { mutableStateListOf<WifiSsid>() }
var inputSsid by remember { mutableStateOf("") }
var ssidList by remember { mutableStateOf("") }
val refreshPolicy = { val refreshPolicy = {
policy = dpm.wifiSsidPolicy val policy = dpm.wifiSsidPolicy
ssidList.clear()
selectedPolicyType = policy?.policyType ?: -1 selectedPolicyType = policy?.policyType ?: -1
ssidSet = policy?.ssids ?: mutableSetOf() (policy?.ssids ?: mutableSetOf()).forEach { ssidList.add(it) }
} }
LaunchedEffect(Unit) { refreshPolicy(); ssidList= ssidSet.toText() } LaunchedEffect(Unit) { refreshPolicy() }
Spacer(Modifier.padding(vertical = 10.dp)) Spacer(Modifier.padding(vertical = 10.dp))
Text(text = stringResource(R.string.wifi_ssid_policy), style = typography.headlineLarge) Text(text = stringResource(R.string.wifi_ssid_policy), style = typography.headlineLarge)
Spacer(Modifier.padding(vertical = 5.dp)) Spacer(Modifier.padding(vertical = 5.dp))
@@ -225,13 +272,14 @@ private fun WifiSsidPolicy() {
{ selectedPolicyType == WIFI_SSID_POLICY_TYPE_DENYLIST }, { selectedPolicyType == WIFI_SSID_POLICY_TYPE_DENYLIST },
{ selectedPolicyType = WIFI_SSID_POLICY_TYPE_DENYLIST } { selectedPolicyType = WIFI_SSID_POLICY_TYPE_DENYLIST }
) )
Column(modifier = Modifier.animateContentSize(scrollAnim()).horizontalScroll(rememberScrollState())) { AnimatedVisibility(selectedPolicyType != -1) {
if(ssidList!="") { var inputSsid by remember { mutableStateOf("") }
Column {
Column {
Spacer(Modifier.padding(vertical = 5.dp)) Spacer(Modifier.padding(vertical = 5.dp))
Text(stringResource(R.string.ssid_list_is)) Text(stringResource(R.string.ssid_list_is))
SelectionContainer{ SelectionContainer(modifier = Modifier.animateContentSize().horizontalScroll(rememberScrollState())) {
Text(text = ssidList, color = colorScheme.onPrimaryContainer) Text(if(ssidList.isEmpty()) stringResource(R.string.none) else ssidList.toText())
}
} }
} }
Spacer(Modifier.padding(vertical = 5.dp)) Spacer(Modifier.padding(vertical = 5.dp))
@@ -247,15 +295,13 @@ private fun WifiSsidPolicy() {
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
Button( Button(
onClick = { onClick = {
if(inputSsid=="") { if(inputSsid == "") {
Toast.makeText(context, R.string.cannot_be_empty, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.cannot_be_empty, Toast.LENGTH_SHORT).show()
} else if (WifiSsid.fromBytes(inputSsid.toByteArray()) in ssidSet) { } else if (WifiSsid.fromBytes(inputSsid.toByteArray()) in ssidList) {
Toast.makeText(context, R.string.already_exist, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.already_exist, Toast.LENGTH_SHORT).show()
} else { } else {
ssidSet.add(WifiSsid.fromBytes(inputSsid.toByteArray())) ssidList.add(WifiSsid.fromBytes(inputSsid.toByteArray()))
ssidList = ssidSet.toText()
} }
inputSsid = ""
}, },
modifier = Modifier.fillMaxWidth(0.49F) modifier = Modifier.fillMaxWidth(0.49F)
) { ) {
@@ -263,12 +309,10 @@ private fun WifiSsidPolicy() {
} }
Button( Button(
onClick = { onClick = {
if(inputSsid=="") { if(inputSsid == "") {
Toast.makeText(context, R.string.cannot_be_empty, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.cannot_be_empty, Toast.LENGTH_SHORT).show()
} else if (WifiSsid.fromBytes(inputSsid.toByteArray()) in ssidSet) { } else if (WifiSsid.fromBytes(inputSsid.toByteArray()) in ssidList) {
ssidSet.remove(WifiSsid.fromBytes(inputSsid.toByteArray())) ssidList.remove(WifiSsid.fromBytes(inputSsid.toByteArray()))
inputSsid = ""
ssidList = ssidSet.toText()
} else { } else {
Toast.makeText(context, R.string.not_exist, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.not_exist, Toast.LENGTH_SHORT).show()
} }
@@ -278,19 +322,18 @@ private fun WifiSsidPolicy() {
Text(stringResource(R.string.remove)) Text(stringResource(R.string.remove))
} }
} }
Spacer(Modifier.padding(vertical = 10.dp))
}
}
Button( Button(
onClick = { onClick = {
focusMgr.clearFocus() focusMgr.clearFocus()
if(selectedPolicyType == -1) { if(selectedPolicyType == -1) {
if(policy==null && ssidSet.isNotEmpty()) {
Toast.makeText(context, R.string.please_select_a_policy, Toast.LENGTH_SHORT).show()
}else{
dpm.wifiSsidPolicy = null dpm.wifiSsidPolicy = null
refreshPolicy() refreshPolicy()
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
}
}else{ }else{
dpm.wifiSsidPolicy = if(ssidSet.size==0) { null }else{ WifiSsidPolicy(selectedPolicyType, ssidSet) } dpm.wifiSsidPolicy = if(ssidList.isEmpty()) { null }else{ WifiSsidPolicy(selectedPolicyType, ssidList.toSet()) }
refreshPolicy() refreshPolicy()
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
} }

View File

@@ -11,8 +11,6 @@ import android.os.IBinder
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.AnimatedVisibility
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.SpringSpec
import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
@@ -23,7 +21,14 @@ import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.* import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
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.platform.LocalContext import androidx.compose.ui.platform.LocalContext
@@ -45,25 +50,26 @@ fun ShizukuActivate() {
val receiver = ComponentName(context, Receiver::class.java) val receiver = ComponentName(context, Receiver::class.java)
val coScope = rememberCoroutineScope() val coScope = rememberCoroutineScope()
val outputTextScrollState = rememberScrollState() val outputTextScrollState = rememberScrollState()
var enabled by remember{ mutableStateOf(false) } var enabled by remember { mutableStateOf(false) }
var bindShizuku by remember{ mutableStateOf(false) } var bindShizuku by remember { mutableStateOf(false) }
var outputText by remember { mutableStateOf("") } var outputText by remember { mutableStateOf("") }
var showDeviceAdminButton by remember { mutableStateOf(!dpm.isAdminActive(receiver)) } var showDeviceAdminButton by remember { mutableStateOf(!dpm.isAdminActive(receiver)) }
var showProfileOwnerButton by remember { mutableStateOf(!isProfileOwner(dpm)) } var showProfileOwnerButton by remember { mutableStateOf(!isProfileOwner(dpm)) }
var showDeviceOwnerButton by remember { mutableStateOf(!isDeviceOwner(dpm)) } var showDeviceOwnerButton by remember { mutableStateOf(!isDeviceOwner(dpm)) }
var showOrgProfileOwnerButton by remember { mutableStateOf(true) } var showOrgProfileOwnerButton by remember { mutableStateOf(true) }
LaunchedEffect(Unit) { val service by shizukuService.collectAsState()
if(service == null) { userServiceControl(context, true) } LaunchedEffect(service) {
while(true) {
if(service == null) { if(service == null) {
enabled = false enabled = false
bindShizuku = checkShizukuStatus()==1 bindShizuku = checkShizukuStatus() == 1
}else{ } else {
enabled = true enabled = true
bindShizuku = false bindShizuku = false
} }
delay(200)
} }
LaunchedEffect(Unit) {
shizukuService.value = null
userServiceControl(context, true)
} }
Column( Column(
modifier = Modifier modifier = Modifier
@@ -86,8 +92,15 @@ fun ShizukuActivate() {
Button( Button(
onClick = { onClick = {
outputText = checkPermission(context) outputText = checkPermission(context)
if(service != null) {
enabled = true
bindShizuku = false
} else {
enabled = false
bindShizuku = checkShizukuStatus() == 1
}
coScope.launch { coScope.launch {
outputTextScrollState.animateScrollTo(0, scrollAnim()) outputTextScrollState.animateScrollTo(0)
} }
} }
) { ) {
@@ -98,7 +111,7 @@ fun ShizukuActivate() {
onClick = { onClick = {
coScope.launch{ coScope.launch{
outputText = service!!.execute("dpm list-owners") outputText = service!!.execute("dpm list-owners")
outputTextScrollState.animateScrollTo(0, scrollAnim()) outputTextScrollState.animateScrollTo(0)
} }
}, },
enabled = enabled enabled = enabled
@@ -112,7 +125,7 @@ fun ShizukuActivate() {
onClick = { onClick = {
coScope.launch{ coScope.launch{
outputText = service!!.execute(context.getString(R.string.dpm_activate_da_command)) outputText = service!!.execute(context.getString(R.string.dpm_activate_da_command))
outputTextScrollState.animateScrollTo(0, scrollAnim()) outputTextScrollState.animateScrollTo(0)
delay(500) delay(500)
showDeviceAdminButton = !dpm.isAdminActive(receiver) showDeviceAdminButton = !dpm.isAdminActive(receiver)
} }
@@ -128,7 +141,7 @@ fun ShizukuActivate() {
onClick = { onClick = {
coScope.launch{ coScope.launch{
outputText = service!!.execute(context.getString(R.string.dpm_activate_po_command)) outputText = service!!.execute(context.getString(R.string.dpm_activate_po_command))
outputTextScrollState.animateScrollTo(0, scrollAnim()) outputTextScrollState.animateScrollTo(0)
delay(500) delay(500)
showProfileOwnerButton = !isProfileOwner(dpm) showProfileOwnerButton = !isProfileOwner(dpm)
} }
@@ -144,7 +157,7 @@ fun ShizukuActivate() {
onClick = { onClick = {
coScope.launch{ coScope.launch{
outputText = service!!.execute(context.getString(R.string.dpm_activate_do_command)) outputText = service!!.execute(context.getString(R.string.dpm_activate_do_command))
outputTextScrollState.animateScrollTo(0, scrollAnim()) outputTextScrollState.animateScrollTo(0)
delay(500) delay(500)
showDeviceOwnerButton = !isDeviceOwner(dpm) showDeviceOwnerButton = !isDeviceOwner(dpm)
} }
@@ -166,7 +179,7 @@ fun ShizukuActivate() {
outputText = service!!.execute( outputText = service!!.execute(
"dpm mark-profile-owner-on-organization-owned-device --user $userID com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver" "dpm mark-profile-owner-on-organization-owned-device --user $userID com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver"
) )
outputTextScrollState.animateScrollTo(0, scrollAnim()) outputTextScrollState.animateScrollTo(0)
delay(500) delay(500)
showOrgProfileOwnerButton = !dpm.isOrganizationOwnedDeviceWithManagedProfile showOrgProfileOwnerButton = !dpm.isOrganizationOwnedDeviceWithManagedProfile
} }
@@ -188,16 +201,9 @@ fun ShizukuActivate() {
} }
} }
@Stable private fun checkPermission(context: Context): String {
fun <T> scrollAnim( if(checkShizukuStatus() == -1) { return context.getString(R.string.shizuku_not_started) }
dampingRatio: Float = Spring.DampingRatioNoBouncy, val getUid = if(shizukuService.value == null) { return context.getString(R.string.shizuku_not_bind) } else { shizukuService.value!!.uid }
stiffness: Float = Spring.StiffnessMedium,
visibilityThreshold: T? = null
): SpringSpec<T> = SpringSpec(dampingRatio, stiffness, visibilityThreshold)
private fun checkPermission(context: Context):String{
if(checkShizukuStatus()==-1) { return context.getString(R.string.shizuku_not_started) }
val getUid = if(service==null) { return context.getString(R.string.shizuku_not_bind) } else { service!!.uid }
return when(getUid) { return when(getUid) {
"2000"->context.getString(R.string.shizuku_activated_shell) "2000"->context.getString(R.string.shizuku_activated_shell)
"0"->context.getString(R.string.shizuku_activated_root) "0"->context.getString(R.string.shizuku_activated_root)
@@ -205,12 +211,12 @@ private fun checkPermission(context: Context):String{
} }
} }
fun checkShizukuStatus():Int{ fun checkShizukuStatus(): Int {
val status = try { val status = try {
if(Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) { waitGrantPermission = false; 1 } if(Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) { waitGrantPermission = false; 1 }
else if(Shizuku.shouldShowRequestPermissionRationale()) { 0 } else if(Shizuku.shouldShowRequestPermissionRationale()) { 0 }
else{ else{
if(!waitGrantPermission) {Shizuku.requestPermission(0) } if(!waitGrantPermission) { Shizuku.requestPermission(0) }
waitGrantPermission = true waitGrantPermission = true
0 0
} }
@@ -219,17 +225,17 @@ fun checkShizukuStatus():Int{
} }
fun userServiceControl(context:Context, status:Boolean) { fun userServiceControl(context:Context, status:Boolean) {
if(checkShizukuStatus()!=1) { return } if(checkShizukuStatus() != 1) { return }
val userServiceConnection = object : ServiceConnection { val userServiceConnection = object : ServiceConnection {
override fun onServiceConnected(componentName: ComponentName, binder: IBinder) { override fun onServiceConnected(componentName: ComponentName, binder: IBinder) {
if (binder.pingBinder()) { if (binder.pingBinder()) {
service = IUserService.Stub.asInterface(binder) shizukuService.value = IUserService.Stub.asInterface(binder)
} else { } else {
Toast.makeText(context, R.string.invalid_binder, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.invalid_binder, Toast.LENGTH_SHORT).show()
} }
} }
override fun onServiceDisconnected(componentName: ComponentName) { override fun onServiceDisconnected(componentName: ComponentName) {
service = null shizukuService.value = null
Toast.makeText(context, R.string.shizuku_service_disconnected, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.shizuku_service_disconnected, Toast.LENGTH_SHORT).show()
} }
} }
@@ -242,9 +248,11 @@ fun userServiceControl(context:Context, status:Boolean) {
.processNameSuffix("service") .processNameSuffix("service")
.debuggable(true) .debuggable(true)
.version(26) .version(26)
try {
if(status) { if(status) {
Shizuku.bindUserService(userServiceArgs, userServiceConnection) Shizuku.bindUserService(userServiceArgs, userServiceConnection)
}else{ }else{
Shizuku.unbindUserService(userServiceArgs, userServiceConnection, false) Shizuku.unbindUserService(userServiceArgs, userServiceConnection, false)
} }
} catch(_: Exception) { }
} }

View File

@@ -3,10 +3,11 @@ package com.bintianqi.owndroid.dpm
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 kotlinx.coroutines.flow.MutableStateFlow
import java.io.BufferedReader import java.io.BufferedReader
import java.io.InputStreamReader import java.io.InputStreamReader
var service:IUserService? = null val shizukuService = MutableStateFlow<IUserService?>(null)
@Keep @Keep
class ShizukuService: IUserService.Stub() { class ShizukuService: IUserService.Stub() {