mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
Set default Affiliation ID while app launch
Wipe data warning timer Display profile owner entry in non-system users Fix some UI bugs
This commit is contained in:
@@ -48,6 +48,7 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
@@ -66,12 +67,14 @@ import com.bintianqi.owndroid.dpm.getReceiver
|
||||
import com.bintianqi.owndroid.dpm.isDeviceAdmin
|
||||
import com.bintianqi.owndroid.dpm.isDeviceOwner
|
||||
import com.bintianqi.owndroid.dpm.isProfileOwner
|
||||
import com.bintianqi.owndroid.dpm.setDefaultAffiliationID
|
||||
import com.bintianqi.owndroid.dpm.toggleInstallAppActivity
|
||||
import com.bintianqi.owndroid.ui.Animations
|
||||
import com.bintianqi.owndroid.ui.theme.OwnDroidTheme
|
||||
import com.rosan.dhizuku.api.Dhizuku
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import org.lsposed.hiddenapibypass.HiddenApiBypass
|
||||
import java.util.Locale
|
||||
|
||||
@@ -85,16 +88,18 @@ class MainActivity : FragmentActivity() {
|
||||
enableEdgeToEdge()
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
super.onCreate(savedInstanceState)
|
||||
val sharedPref = applicationContext.getSharedPreferences("data", MODE_PRIVATE)
|
||||
val context = applicationContext
|
||||
val sharedPref = context.getSharedPreferences("data", MODE_PRIVATE)
|
||||
if (VERSION.SDK_INT >= 28) HiddenApiBypass.setHiddenApiExemptions("")
|
||||
if(sharedPref.getBoolean("auth", false)) {
|
||||
showAuth.value = true
|
||||
}
|
||||
val locale = applicationContext.resources?.configuration?.locale
|
||||
val locale = context.resources?.configuration?.locale
|
||||
zhCN = locale == Locale.SIMPLIFIED_CHINESE || locale == Locale.CHINESE || locale == Locale.CHINA
|
||||
toggleInstallAppActivity()
|
||||
val vm by viewModels<MyViewModel>()
|
||||
if(!vm.initialized) vm.initialize(applicationContext)
|
||||
if(!vm.initialized) vm.initialize(context)
|
||||
lifecycleScope.launch { setDefaultAffiliationID(context) }
|
||||
setContent {
|
||||
OwnDroidTheme(vm) {
|
||||
Home(vm)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.bintianqi.owndroid
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
@@ -11,6 +12,7 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.bintianqi.owndroid.ui.theme.OwnDroidTheme
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class ManageSpaceActivity: FragmentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -32,21 +34,26 @@ class ManageSpaceActivity: FragmentActivity() {
|
||||
},
|
||||
onDismissRequest = { finish() },
|
||||
dismissButton = {
|
||||
if(!protected) TextButton(onClick = { finish() }) {
|
||||
TextButton(onClick = { finish() }) {
|
||||
Text(stringResource(R.string.cancel))
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
if(!protected) TextButton(
|
||||
onClick = {
|
||||
if(!protected) {
|
||||
applicationContext.filesDir.deleteRecursively()
|
||||
filesDir.deleteRecursively()
|
||||
cacheDir.deleteRecursively()
|
||||
codeCacheDir.deleteRecursively()
|
||||
if(Build.VERSION.SDK_INT >= 24) {
|
||||
dataDir.resolve("shared_prefs").deleteRecursively()
|
||||
} else {
|
||||
sharedPref.edit().clear().apply()
|
||||
}
|
||||
finish()
|
||||
exitProcess(0)
|
||||
}
|
||||
) {
|
||||
Text(stringResource(if(protected) R.string.cancel else R.string.confirm))
|
||||
Text(stringResource(R.string.confirm))
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -470,9 +470,9 @@ private fun PermissionManage(pkgName: String) {
|
||||
Text(selectedPermission.permission)
|
||||
Spacer(Modifier.padding(vertical = 4.dp))
|
||||
if(!(VERSION.SDK_INT >=31 && context.isProfileOwner && selectedPermission.profileOwnerRestricted)) {
|
||||
GrantPermissionItem(R.string.grant, PERMISSION_GRANT_STATE_GRANTED)
|
||||
GrantPermissionItem(R.string.granted, PERMISSION_GRANT_STATE_GRANTED)
|
||||
}
|
||||
GrantPermissionItem(R.string.deny, PERMISSION_GRANT_STATE_DENIED)
|
||||
GrantPermissionItem(R.string.denied, PERMISSION_GRANT_STATE_DENIED)
|
||||
GrantPermissionItem(R.string.default_stringres, PERMISSION_GRANT_STATE_DEFAULT)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import android.content.pm.IPackageInstaller
|
||||
import android.content.pm.PackageInstaller
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build.VERSION
|
||||
import android.os.UserManager
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.RequiresApi
|
||||
@@ -401,3 +402,24 @@ data class SecurityEventItem(
|
||||
@SerialName("log_level") val logLevel: Int?,
|
||||
val data: String
|
||||
)
|
||||
|
||||
fun setDefaultAffiliationID(context: Context) {
|
||||
if(VERSION.SDK_INT < 26) return
|
||||
val sharedPrefs = context.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||||
if(!sharedPrefs.getBoolean("default_affiliation_id_set", false)) {
|
||||
try {
|
||||
val um = context.getSystemService(Context.USER_SERVICE) as UserManager
|
||||
if(context.isDeviceOwner || (!um.isSystemUser && context.isProfileOwner)) {
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val affiliationIDs = dpm.getAffiliationIds(receiver)
|
||||
if(affiliationIDs.isEmpty()) {
|
||||
dpm.setAffiliationIds(receiver, setOf("OwnDroid_default_affiliation_id"))
|
||||
sharedPrefs.edit().putBoolean("default_affiliation_id_set", true).apply()
|
||||
}
|
||||
}
|
||||
} catch(e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -700,7 +700,7 @@ private fun WifiAuthKeypair() {
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
OutlinedTextField(
|
||||
value = keyPair,
|
||||
label = { Text(stringResource(R.string.keypair)) },
|
||||
label = { Text(stringResource(R.string.alias)) },
|
||||
onValueChange = { keyPair = it },
|
||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
||||
keyboardActions = KeyboardActions(onDone = { focusMgr.clearFocus() }),
|
||||
@@ -723,7 +723,7 @@ private fun WifiAuthKeypair() {
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(0.49F)
|
||||
) {
|
||||
Text(stringResource(R.string.add))
|
||||
Text(stringResource(R.string.grant))
|
||||
}
|
||||
Button(
|
||||
onClick = {
|
||||
@@ -732,7 +732,7 @@ private fun WifiAuthKeypair() {
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(0.96F)
|
||||
) {
|
||||
Text(stringResource(R.string.remove))
|
||||
Text(stringResource(R.string.revoke))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,10 @@ import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Binder
|
||||
import android.os.Build.VERSION
|
||||
import android.os.RemoteException
|
||||
import android.os.UserManager
|
||||
import android.widget.Toast
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.*
|
||||
@@ -90,6 +92,7 @@ private fun Home(localNavCtrl:NavHostController,listScrollState:ScrollState) {
|
||||
val deviceAdmin = context.isDeviceAdmin
|
||||
val deviceOwner = context.isDeviceOwner
|
||||
val profileOwner = context.isProfileOwner
|
||||
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
|
||||
var dialog by remember { mutableIntStateOf(0) }
|
||||
val enrollmentSpecificId = if(VERSION.SDK_INT >= 31 && (deviceOwner || profileOwner)) dpm.enrollmentSpecificId else ""
|
||||
Column(modifier = Modifier.fillMaxSize().verticalScroll(listScrollState)) {
|
||||
@@ -110,13 +113,13 @@ private fun Home(localNavCtrl:NavHostController,listScrollState:ScrollState) {
|
||||
R.string.device_admin, stringResource(if(deviceAdmin) R.string.activated else R.string.deactivated),
|
||||
operation = { localNavCtrl.navigate("DeviceAdmin") }
|
||||
)
|
||||
if(profileOwner) {
|
||||
if(profileOwner || !userManager.isSystemUser) {
|
||||
SubPageItem(
|
||||
R.string.profile_owner, stringResource(R.string.activated),
|
||||
R.string.profile_owner, stringResource(if(profileOwner) R.string.activated else R.string.deactivated),
|
||||
operation = { localNavCtrl.navigate("ProfileOwner") }
|
||||
)
|
||||
}
|
||||
if(!profileOwner) {
|
||||
if(!profileOwner && userManager.isSystemUser) {
|
||||
SubPageItem(
|
||||
R.string.device_owner, stringResource(if(deviceOwner) R.string.activated else R.string.deactivated),
|
||||
operation = { localNavCtrl.navigate("DeviceOwner") }
|
||||
@@ -376,7 +379,13 @@ private fun ProfileOwner() {
|
||||
Text(stringResource(R.string.deactivate))
|
||||
}
|
||||
}
|
||||
InfoCard(R.string.profile_owner)
|
||||
if(!profileOwner) {
|
||||
val command = context.getString(R.string.activate_profile_owner_command, (Binder.getCallingUid() / 100000).toString())
|
||||
SelectionContainer {
|
||||
Text(command)
|
||||
}
|
||||
CopyTextButton(R.string.copy_command, command)
|
||||
}
|
||||
}
|
||||
if(deactivateDialog && VERSION.SDK_INT >= 24) {
|
||||
AlertDialog(
|
||||
@@ -394,7 +403,8 @@ private fun ProfileOwner() {
|
||||
onClick = {
|
||||
dpm.clearProfileOwner(receiver)
|
||||
deactivateDialog = false
|
||||
}
|
||||
},
|
||||
colors = ButtonDefaults.textButtonColors(contentColor = colorScheme.error)
|
||||
) {
|
||||
Text(stringResource(R.string.confirm))
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import androidx.compose.foundation.horizontalScroll
|
||||
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.rememberScrollState
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
@@ -192,9 +193,7 @@ fun ShizukuActivate() {
|
||||
}
|
||||
}
|
||||
|
||||
SelectionContainer(modifier = Modifier
|
||||
.align(Alignment.Start)
|
||||
.horizontalScroll(outputTextScrollState)) {
|
||||
SelectionContainer(modifier = Modifier.fillMaxWidth().horizontalScroll(outputTextScrollState)) {
|
||||
Text(text = outputText, softWrap = false, modifier = Modifier.padding(4.dp))
|
||||
}
|
||||
|
||||
|
||||
@@ -125,6 +125,7 @@ import com.bintianqi.owndroid.ui.SubPageItem
|
||||
import com.bintianqi.owndroid.ui.SwitchItem
|
||||
import com.bintianqi.owndroid.ui.TopBar
|
||||
import com.bintianqi.owndroid.uriToStream
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
@@ -1255,7 +1256,6 @@ private fun WipeData() {
|
||||
val context = LocalContext.current
|
||||
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val focusMgr = LocalFocusManager.current
|
||||
var warning by remember { mutableStateOf(false) }
|
||||
var wipeDevice by remember { mutableStateOf(false) }
|
||||
@@ -1333,6 +1333,14 @@ private fun WipeData() {
|
||||
},
|
||||
onDismissRequest = { warning = false },
|
||||
confirmButton = {
|
||||
var timer by remember { mutableIntStateOf(6) }
|
||||
LaunchedEffect(Unit) {
|
||||
while(timer > 0) {
|
||||
timer -= 1
|
||||
delay(1000)
|
||||
}
|
||||
}
|
||||
val timerText = if(timer > 0) "(${timer}s)" else ""
|
||||
TextButton(
|
||||
onClick = {
|
||||
var flag = 0
|
||||
@@ -1350,9 +1358,11 @@ private fun WipeData() {
|
||||
}
|
||||
}
|
||||
},
|
||||
colors = ButtonDefaults.textButtonColors(contentColor = colorScheme.error)
|
||||
colors = ButtonDefaults.textButtonColors(contentColor = colorScheme.error),
|
||||
modifier = Modifier.animateContentSize(),
|
||||
enabled = timer == 0
|
||||
) {
|
||||
Text(stringResource(R.string.confirm))
|
||||
Text(stringResource(R.string.confirm) + timerText)
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
@@ -1392,27 +1402,30 @@ private fun SysUpdatePolicy() {
|
||||
RadioButtonItem(R.string.none, selectedPolicy == null, { selectedPolicy = null })
|
||||
var windowedPolicyStart by remember { mutableStateOf("") }
|
||||
var windowedPolicyEnd by remember { mutableStateOf("") }
|
||||
if(selectedPolicy == 2) {
|
||||
Spacer(Modifier.padding(vertical = 3.dp))
|
||||
OutlinedTextField(
|
||||
value = windowedPolicyStart,
|
||||
label = { Text(stringResource(R.string.start_time)) },
|
||||
onValueChange = { windowedPolicyStart = it },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
||||
keyboardActions = KeyboardActions(onDone = { focusMgr.clearFocus() }),
|
||||
modifier = Modifier.fillMaxWidth(0.5F)
|
||||
)
|
||||
Spacer(Modifier.padding(horizontal = 3.dp))
|
||||
OutlinedTextField(
|
||||
value = windowedPolicyEnd,
|
||||
onValueChange = {windowedPolicyEnd = it },
|
||||
label = { Text(stringResource(R.string.end_time)) },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
||||
keyboardActions = KeyboardActions(onDone = { focusMgr.clearFocus() }),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(Modifier.padding(vertical = 3.dp))
|
||||
Text(text = stringResource(R.string.minutes_in_one_day))
|
||||
AnimatedVisibility(selectedPolicy == 2) {
|
||||
Column {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
OutlinedTextField(
|
||||
value = windowedPolicyStart,
|
||||
label = { Text(stringResource(R.string.start_time)) },
|
||||
onValueChange = { windowedPolicyStart = it },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
||||
keyboardActions = KeyboardActions(onDone = { focusMgr.clearFocus() }),
|
||||
modifier = Modifier.fillMaxWidth(0.49F)
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = windowedPolicyEnd,
|
||||
onValueChange = {windowedPolicyEnd = it },
|
||||
label = { Text(stringResource(R.string.end_time)) },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
||||
keyboardActions = KeyboardActions(onDone = { focusMgr.clearFocus() }),
|
||||
modifier = Modifier.fillMaxWidth(0.96F).padding(bottom = 2.dp)
|
||||
)
|
||||
}
|
||||
Text(text = stringResource(R.string.minutes_in_one_day))
|
||||
}
|
||||
}
|
||||
Button(
|
||||
onClick = {
|
||||
@@ -1426,7 +1439,7 @@ private fun SysUpdatePolicy() {
|
||||
dpm.setSystemUpdatePolicy(receiver,policy)
|
||||
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier.fillMaxWidth().padding(top = 8.dp)
|
||||
) {
|
||||
Text(stringResource(R.string.apply))
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<string name="denied">Запрещено</string>
|
||||
<string name="grant">Разрешить</string>
|
||||
<string name="deny">Запретить</string>
|
||||
<string name="revoke">Revoke</string> <!--TODO-->
|
||||
<string name="current_state">Текущее состояние: %1$s</string>
|
||||
<string name="auto">Авто</string>
|
||||
<string name="password">Пароль</string>
|
||||
@@ -59,6 +60,7 @@
|
||||
<string name="next">Следующий</string>
|
||||
<string name="on">On</string> <!--TODO-->
|
||||
<string name="off">Off</string> <!--TODO-->
|
||||
<string name="alias">Alias</string> <!--TODO-->
|
||||
|
||||
|
||||
<!--Разрешения-->
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
<string name="denied">Reddedildi</string>
|
||||
<string name="grant">Ver</string>
|
||||
<string name="deny">Reddet</string>
|
||||
<string name="revoke">Revoke</string> <!--TODO-->
|
||||
<string name="current_state">Mevcut Durum: %1$s</string>
|
||||
<string name="auto">Otomatik</string>
|
||||
<string name="password">Şifre</string>
|
||||
@@ -60,6 +61,7 @@
|
||||
<string name="next">Next</string> <!--TODO-->
|
||||
<string name="on">On</string> <!--TODO-->
|
||||
<string name="off">Off</string> <!--TODO-->
|
||||
<string name="alias">Alias</string> <!--TODO-->
|
||||
|
||||
<!--Permissions-->
|
||||
<string name="click_to_activate">Etkinleştirmek İçin Tıklayın</string>
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
<string name="whitelist">白名单</string>
|
||||
<string name="granted">允许</string>
|
||||
<string name="denied">拒绝</string>
|
||||
<string name="grant">允许</string>
|
||||
<string name="grant">授予</string>
|
||||
<string name="deny">拒绝</string>
|
||||
<string name="revoke">吊销</string>
|
||||
<string name="current_state">当前状态:%1$s</string>
|
||||
<string name="auto">自动</string>
|
||||
<string name="password">密码</string>
|
||||
@@ -57,6 +58,7 @@
|
||||
<string name="next">下一个</string>
|
||||
<string name="on">开启</string>
|
||||
<string name="off">关闭</string>
|
||||
<string name="alias">别名</string>
|
||||
|
||||
<!--Permissions-->
|
||||
<string name="click_to_activate">点击以激活</string>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
<string name="denied">Denied</string>
|
||||
<string name="grant">Grant</string>
|
||||
<string name="deny">Deny</string>
|
||||
<string name="revoke">Revoke</string>
|
||||
<string name="current_state">Current status: %1$s</string>
|
||||
<string name="auto">Auto</string>
|
||||
<string name="password">Password</string>
|
||||
@@ -60,6 +61,7 @@
|
||||
<string name="next">Next</string>
|
||||
<string name="on">On</string>
|
||||
<string name="off">Off</string>
|
||||
<string name="alias">Alias</string>
|
||||
|
||||
<!--Permissions-->
|
||||
<string name="click_to_activate">Click to activate</string>
|
||||
@@ -71,6 +73,7 @@
|
||||
<string name="reset_device_policy">Reset device policy</string>
|
||||
<string name="activate_device_admin">Activate Device admin</string>
|
||||
<string name="activate_device_admin_command" translatable="false">dpm set-active-admin com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver</string>
|
||||
<string name="activate_profile_owner_command" translatable="false">dpm set-profile-owner --user %1$s com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver</string>
|
||||
<string name="activate_device_owner_command" translatable="false">dpm set-device-owner com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver</string>
|
||||
<string name="device_info">Device info</string>
|
||||
<string name="support_device_id_attestation">Support Device ID attestation</string>
|
||||
|
||||
Reference in New Issue
Block a user