Manage delegated admins

Upgrade AGP and gradle wrapper version
Fix navigation bug of Shizuku
Fix Action build
This commit is contained in:
BinTianqi
2025-01-23 21:21:51 +08:00
parent 0b90d7c0f3
commit a8392adb42
12 changed files with 223 additions and 38 deletions

View File

@@ -61,9 +61,9 @@ jobs:
upload-telegram: upload-telegram:
name: Upload Builds name: Upload Builds
if: github.ref_name == 'dev'
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: ["build"] needs: build
if: github.ref == 'refs/heads/dev'
steps: steps:
- name: Download Artifacts - name: Download Artifacts
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4

View File

@@ -6,4 +6,5 @@ interface IUserService {
String execute(String command) = 1; String execute(String command) = 1;
int getUid() = 2; int getUid() = 2;
Account[] listAccounts() = 3; Account[] listAccounts() = 3;
void destroy() = 16777114;
} }

View File

@@ -71,6 +71,7 @@ import com.bintianqi.owndroid.dpm.ChangeUsername
import com.bintianqi.owndroid.dpm.CreateUser import com.bintianqi.owndroid.dpm.CreateUser
import com.bintianqi.owndroid.dpm.CreateWorkProfile import com.bintianqi.owndroid.dpm.CreateWorkProfile
import com.bintianqi.owndroid.dpm.CurrentUserInfo import com.bintianqi.owndroid.dpm.CurrentUserInfo
import com.bintianqi.owndroid.dpm.DelegatedAdmins
import com.bintianqi.owndroid.dpm.DeleteWorkProfile import com.bintianqi.owndroid.dpm.DeleteWorkProfile
import com.bintianqi.owndroid.dpm.DeviceAdmin import com.bintianqi.owndroid.dpm.DeviceAdmin
import com.bintianqi.owndroid.dpm.DeviceInfo import com.bintianqi.owndroid.dpm.DeviceInfo
@@ -219,6 +220,7 @@ fun Home(activity: FragmentActivity, vm: MyViewModel) {
composable(route = "DeviceAdmin") { DeviceAdmin(navCtrl) } composable(route = "DeviceAdmin") { DeviceAdmin(navCtrl) }
composable(route = "ProfileOwner") { ProfileOwner(navCtrl) } composable(route = "ProfileOwner") { ProfileOwner(navCtrl) }
composable(route = "DeviceOwner") { DeviceOwner(navCtrl) } composable(route = "DeviceOwner") { DeviceOwner(navCtrl) }
composable(route = "DelegatedAdmins") { DelegatedAdmins(navCtrl, vm) }
composable(route = "DeviceInfo") { DeviceInfo(navCtrl) } composable(route = "DeviceInfo") { DeviceInfo(navCtrl) }
composable(route = "LockScreenInfo") { LockScreenInfo(navCtrl) } composable(route = "LockScreenInfo") { LockScreenInfo(navCtrl) }
composable(route = "SupportMessages") { SupportMessages(navCtrl) } composable(route = "SupportMessages") { SupportMessages(navCtrl) }

View File

@@ -9,29 +9,42 @@ import android.content.Intent
import android.content.pm.PackageManager 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.Bundle import android.os.IBinder
import android.os.RemoteException import android.os.RemoteException
import android.os.UserManager import android.os.UserManager
import android.widget.Toast import android.widget.Toast
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.annotation.StringRes
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
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.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.material3.MaterialTheme.colorScheme import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.MaterialTheme.typography import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
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.platform.LocalFocusManager
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
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.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.Dialog
import androidx.core.os.bundleOf
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.NavOptions
import com.bintianqi.owndroid.MyViewModel
import com.bintianqi.owndroid.R import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.backToHomeStateFlow import com.bintianqi.owndroid.backToHomeStateFlow
import com.bintianqi.owndroid.showOperationResultToast import com.bintianqi.owndroid.showOperationResultToast
@@ -87,39 +100,38 @@ fun Permissions(navCtrl: NavHostController) {
try { try {
if(Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) { if(Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) {
bindingShizuku = true bindingShizuku = true
val destination = navCtrl.graph.findNode("Shizuku")!!.id fun onBind(binder: IBinder) {
bindShizukuService(context, { binder -> val destinationId = navCtrl.graph.findNode("Shizuku")!!.id
val args = Bundle()
args.putBinder("binder", binder)
bindingShizuku = false bindingShizuku = false
navCtrl.navigate(destination, args) navCtrl.navigate(destinationId, bundleOf("binder" to binder), NavOptions.Builder().setLaunchSingleTop(true).build())
}, { }
Toast.makeText(context, R.string.shizuku_service_disconnected, Toast.LENGTH_SHORT).show() try {
controlShizukuService(context, ::onBind, { bindingShizuku = false }, true)
} catch(e: Exception) {
e.printStackTrace()
bindingShizuku = false bindingShizuku = false
}) }
} else if(Shizuku.shouldShowRequestPermissionRationale()) { } else if(Shizuku.shouldShowRequestPermissionRationale()) {
Toast.makeText(context, R.string.permission_denied, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.permission_denied, Toast.LENGTH_SHORT).show()
} else { } else {
Sui.init(context.packageName) Sui.init(context.packageName)
val listener = object: Shizuku.OnRequestPermissionResultListener { fun requestPermissionResultListener(requestCode: Int, grantResult: Int) {
override fun onRequestPermissionResult(requestCode: Int, grantResult: Int) { if(grantResult != PackageManager.PERMISSION_GRANTED) {
if(grantResult == PackageManager.PERMISSION_GRANTED) { Toast.makeText(context, R.string.permission_denied, Toast.LENGTH_SHORT).show()
navCtrl.navigate("Shizuku")
} else {
Toast.makeText(context, R.string.permission_denied, Toast.LENGTH_SHORT).show()
}
Shizuku.removeRequestPermissionResultListener(this)
} }
Shizuku.removeRequestPermissionResultListener(::requestPermissionResultListener)
} }
Shizuku.addRequestPermissionResultListener(listener) Shizuku.addRequestPermissionResultListener(::requestPermissionResultListener)
Shizuku.requestPermission(0) Shizuku.requestPermission(0)
} }
} catch(_: IllegalStateException) { } catch(_: IllegalStateException) {
Toast.makeText(context, R.string.shizuku_not_started, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.shizuku_not_started, Toast.LENGTH_SHORT).show()
} }
} }
if(VERSION.SDK_INT >= 26 && (deviceOwner || profileOwner))
FunctionItem(R.string.delegated_admins) { navCtrl.navigate("DelegatedAdmins") }
FunctionItem(R.string.device_info, icon = R.drawable.perm_device_information_fill0) { navCtrl.navigate("DeviceInfo") } FunctionItem(R.string.device_info, icon = R.drawable.perm_device_information_fill0) { navCtrl.navigate("DeviceInfo") }
if((VERSION.SDK_INT >= 26 && deviceOwner) || (VERSION.SDK_INT>=24 && profileOwner)) { if((VERSION.SDK_INT >= 26 && deviceOwner) || (VERSION.SDK_INT >= 24 && profileOwner)) {
FunctionItem(R.string.org_name, icon = R.drawable.corporate_fare_fill0) { dialog = 2 } FunctionItem(R.string.org_name, icon = R.drawable.corporate_fare_fill0) { dialog = 2 }
} }
if(VERSION.SDK_INT >= 31 && (profileOwner || deviceOwner)) { if(VERSION.SDK_INT >= 31 && (profileOwner || deviceOwner)) {
@@ -476,6 +488,133 @@ fun DeviceOwner(navCtrl: NavHostController) {
} }
} }
@Suppress("InlinedApi")
private enum class DelegatedScope(val id: String, @StringRes val string: Int, val requiresApi: Int = 0) {
AppRestrictions(DevicePolicyManager.DELEGATION_APP_RESTRICTIONS, R.string.manage_application_restrictions),
BlockUninstall(DevicePolicyManager.DELEGATION_BLOCK_UNINSTALL, R.string.block_uninstall),
CertInstall(DevicePolicyManager.DELEGATION_CERT_INSTALL, R.string.manage_certificates),
CertSelection(DevicePolicyManager.DELEGATION_CERT_SELECTION, R.string.select_keychain_certificates, 29),
EnableSystemApp(DevicePolicyManager.DELEGATION_ENABLE_SYSTEM_APP, R.string.enable_system_app),
InstallExistingPackage(DevicePolicyManager.DELEGATION_INSTALL_EXISTING_PACKAGE, R.string.install_existing_packages, 28),
KeepUninstalledPackages(DevicePolicyManager.DELEGATION_KEEP_UNINSTALLED_PACKAGES, R.string.manage_uninstalled_packages, 28),
NetworkLogging(DevicePolicyManager.DELEGATION_NETWORK_LOGGING, R.string.network_logging, 29),
PackageAccess(DevicePolicyManager.DELEGATION_PACKAGE_ACCESS, R.string.change_package_state),
PermissionGrant(DevicePolicyManager.DELEGATION_PERMISSION_GRANT, R.string.grant_permissions),
SecurityLogging(DevicePolicyManager.DELEGATION_SECURITY_LOGGING, R.string.security_logging, 31)
}
@RequiresApi(26)
@Composable
fun DelegatedAdmins(navCtrl: NavHostController, vm: MyViewModel) {
val context = LocalContext.current
val dpm = context.getDPM()
val receiver = context.getReceiver()
var dialog by rememberSaveable { mutableIntStateOf(0) } // 0:None, 1:Edit, 2:Add
var inputPackageName by rememberSaveable { mutableStateOf("") }
var selectedScopes by rememberSaveable { mutableStateOf(listOf<String>()) }
val packages = remember { mutableStateMapOf<String, MutableList<DelegatedScope>>() }
fun refresh() {
val list = mutableMapOf<String, MutableList<DelegatedScope>>()
DelegatedScope.entries.forEach { ds ->
if(VERSION.SDK_INT >= ds.requiresApi) {
dpm.getDelegatePackages(receiver, ds.id)?.forEach { pkg ->
if(list[pkg] != null) {
list[pkg]!!.add(ds)
} else {
list[pkg] = mutableListOf(ds)
}
}
}
}
packages.clear()
packages.putAll(list)
}
LaunchedEffect(Unit) { refresh() }
MyScaffold(R.string.delegated_admins, 0.dp, navCtrl) {
packages.forEach { (pkg, scopes) ->
Column(
modifier = Modifier
.fillMaxWidth()
.clickable { inputPackageName = pkg; selectedScopes = scopes.map { it.id }; dialog = 1 }
.padding(horizontal = 12.dp, vertical = 8.dp)
) {
Text(pkg, style = typography.titleLarge)
Text(scopes.size.toString() + " " + stringResource(R.string.delegated_scope))
}
}
if(packages.isEmpty())
Text(
stringResource(R.string.none),
color = colorScheme.onSurfaceVariant,
modifier = Modifier.align(Alignment.CenterHorizontally).padding(vertical = 4.dp)
)
Row(
modifier = Modifier
.fillMaxWidth()
.clickable { inputPackageName = ""; selectedScopes = emptyList(); dialog = 2 }
.padding(vertical = 10.dp, horizontal = 12.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(Icons.Default.Add, null, modifier = Modifier.padding(end = 12.dp))
Text(stringResource(R.string.add_delegated_admin), style = typography.titleLarge)
}
if(dialog != 0) {
val selectedPackage by vm.selectedPackage.collectAsStateWithLifecycle()
LaunchedEffect(selectedPackage) {
if(selectedPackage != "") {
inputPackageName = selectedPackage
vm.selectedPackage.value = ""
}
}
AlertDialog(
text = {
val fm = LocalFocusManager.current
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
OutlinedTextField(
value = inputPackageName, onValueChange = { inputPackageName = it },
label = { Text(stringResource(R.string.package_name)) },
trailingIcon = {
if(dialog == 2) IconButton({ navCtrl.navigate("PackageSelector") }) {
Icon(painterResource(R.drawable.list_fill0), null)
}
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Ascii, imeAction = ImeAction.Done),
keyboardActions = KeyboardActions { fm.clearFocus() },
readOnly = dialog == 1,
modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp)
)
DelegatedScope.entries.forEach { scope ->
if(VERSION.SDK_INT >= scope.requiresApi) {
CheckBoxItem(scope.string, scope.id in selectedScopes) {
if(it) selectedScopes += scope.id else selectedScopes -= scope.id
}
}
}
}
},
confirmButton = {
TextButton(
onClick = {
dpm.setDelegatedScopes(receiver, inputPackageName, selectedScopes)
refresh()
dialog = 0
},
enabled = inputPackageName.isNotBlank()
) {
Text(stringResource(if(dialog == 1) R.string.apply else R.string.add))
}
},
dismissButton = {
TextButton({ dialog = 0 }) {
Text(stringResource(R.string.cancel))
}
},
onDismissRequest = { dialog = 0 }
)
}
}
}
@Composable @Composable
fun DeviceInfo(navCtrl: NavHostController) { fun DeviceInfo(navCtrl: NavHostController) {
val context = LocalContext.current val context = LocalContext.current

View File

@@ -151,10 +151,11 @@ fun Shizuku(navCtrl: NavHostController, navArgs: Bundle) {
} }
} }
fun bindShizukuService( fun controlShizukuService(
context: Context, context: Context,
onServiceConnected: (IBinder) -> Unit, onServiceConnected: (IBinder) -> Unit,
onServiceDisconnected: () -> Unit onServiceDisconnected: () -> Unit,
state: Boolean
) { ) {
val userServiceConnection = object : ServiceConnection { val userServiceConnection = object : ServiceConnection {
override fun onServiceConnected(componentName: ComponentName, binder: IBinder) { override fun onServiceConnected(componentName: ComponentName, binder: IBinder) {
@@ -169,11 +170,8 @@ fun bindShizukuService(
.processNameSuffix("shizuku-service") .processNameSuffix("shizuku-service")
.debuggable(false) .debuggable(false)
.version(26) .version(26)
try { if(state) Shizuku.bindUserService(userServiceArgs, userServiceConnection)
Shizuku.bindUserService(userServiceArgs, userServiceConnection) else Shizuku.unbindUserService(userServiceArgs, userServiceConnection, true)
} catch(e: Exception) {
e.printStackTrace()
}
} }
@Composable @Composable

View File

@@ -4,15 +4,11 @@ import android.accounts.Account
import android.accounts.AccountManager import android.accounts.AccountManager
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.os.Parcelable
import android.os.UserManager
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 com.bintianqi.owndroid.getContext import com.bintianqi.owndroid.getContext
import java.io.BufferedReader import kotlin.system.exitProcess
import java.io.InputStreamReader
import java.lang.Class
@Keep @Keep
class ShizukuService: IUserService.Stub() { class ShizukuService: IUserService.Stub() {
@@ -28,10 +24,10 @@ class ShizukuService: IUserService.Stub() {
return e.toString() return e.toString()
} }
try { try {
val outputReader = BufferedReader(InputStreamReader(process.inputStream)) val outputReader = process.inputStream.bufferedReader()
var outputLine: String var outputLine: String
while(outputReader.readLine().also {outputLine = it} != null) { result += "$outputLine\n" } while(outputReader.readLine().also {outputLine = it} != null) { result += "$outputLine\n" }
val errorReader = BufferedReader(InputStreamReader(process.errorStream)) val errorReader = process.errorStream.bufferedReader()
var errorLine: String var errorLine: String
while(errorReader.readLine().also {errorLine = it} != null) { result += "$errorLine\n" } while(errorReader.readLine().also {errorLine = it} != null) { result += "$errorLine\n" }
} catch(e: NullPointerException) { } catch(e: NullPointerException) {
@@ -47,4 +43,8 @@ class ShizukuService: IUserService.Stub() {
val am = getContext().getSystemService(Context.ACCOUNT_SERVICE) as AccountManager val am = getContext().getSystemService(Context.ACCOUNT_SERVICE) as AccountManager
return am.accounts return am.accounts
} }
override fun destroy() {
exitProcess(0)
}
} }

View File

@@ -68,6 +68,7 @@
<string name="edit">Edit</string> <string name="edit">Edit</string>
<string name="overview">Overview</string> <string name="overview">Overview</string>
<string name="features">Features</string> <string name="features">Features</string>
<string name="default_str">Default</string>
<!--Разрешения--> <!--Разрешения-->
@@ -76,6 +77,17 @@
<string name="activate_jump" tools:ignore="TypographyEllipsis">Активировать...</string> <string name="activate_jump" tools:ignore="TypographyEllipsis">Активировать...</string>
<string name="profile_owner">Владелец профиля</string> <string name="profile_owner">Владелец профиля</string>
<string name="device_owner">Владелец устройства</string> <string name="device_owner">Владелец устройства</string>
<!--TODO: translate the following 10 strings-->
<string name="delegated_admins">Delegated admins</string>
<string name="delegated_scope">delegated scope</string>
<string name="manage_application_restrictions">Manage application restrictions</string>
<string name="manage_certificates">Manage certificates</string>
<string name="select_keychain_certificates">Select KeyChain certificate</string>
<string name="install_existing_packages">Install existing packages</string>
<string name="manage_uninstalled_packages">Manage uninstalled packages</string>
<string name="change_package_state">Change package state</string>
<string name="grant_permissions">Grant permissions</string>
<string name="add_delegated_admin">Add delegated admin</string>
<string name="dhizuku_will_be_deactivated">Dhizuku будет деактивирован</string> <string name="dhizuku_will_be_deactivated">Dhizuku будет деактивирован</string>
<string name="reset_device_policy">Сбросить политику устройства</string> <string name="reset_device_policy">Сбросить политику устройства</string>
<string name="activate_device_admin">Активировать администратора устройства</string> <string name="activate_device_admin">Активировать администратора устройства</string>

View File

@@ -69,6 +69,7 @@
<string name="edit">Edit</string> <string name="edit">Edit</string>
<string name="overview">Overview</string> <string name="overview">Overview</string>
<string name="features">Features</string> <string name="features">Features</string>
<string name="default_str">Default</string>
<!--Permissions--> <!--Permissions-->
<string name="click_to_activate">Etkinleştirmek İçin Tıklayın</string> <string name="click_to_activate">Etkinleştirmek İçin Tıklayın</string>
@@ -76,6 +77,17 @@
<string name="activate_jump" tools:ignore="TypographyEllipsis">Etkinleştir...</string> <string name="activate_jump" tools:ignore="TypographyEllipsis">Etkinleştir...</string>
<string name="profile_owner">Profil Sahibi</string> <string name="profile_owner">Profil Sahibi</string>
<string name="device_owner">Cihaz Sahibi</string> <string name="device_owner">Cihaz Sahibi</string>
<!--TODO: translate the following 10 strings-->
<string name="delegated_admins">Delegated admins</string>
<string name="delegated_scope">delegated scope</string>
<string name="manage_application_restrictions">Manage application restrictions</string>
<string name="manage_certificates">Manage certificates</string>
<string name="select_keychain_certificates">Select KeyChain certificate</string>
<string name="install_existing_packages">Install existing packages</string>
<string name="manage_uninstalled_packages">Manage uninstalled packages</string>
<string name="change_package_state">Change package state</string>
<string name="grant_permissions">Grant permissions</string>
<string name="add_delegated_admin">Add delegated admin</string>
<string name="dhizuku_will_be_deactivated">Dhizuku will be deactivated</string> <!--TODO--> <string name="dhizuku_will_be_deactivated">Dhizuku will be deactivated</string> <!--TODO-->
<string name="reset_device_policy">Reset device policy</string> <!--TODO--> <string name="reset_device_policy">Reset device policy</string> <!--TODO-->
<string name="activate_device_admin">Cihaz Yöneticisini Etkinleştir</string> <string name="activate_device_admin">Cihaz Yöneticisini Etkinleştir</string>

View File

@@ -65,6 +65,7 @@
<string name="edit">编辑</string> <string name="edit">编辑</string>
<string name="overview">概览</string> <string name="overview">概览</string>
<string name="features">功能</string> <string name="features">功能</string>
<string name="default_str">默认</string>
<!--Permissions--> <!--Permissions-->
<string name="click_to_activate">点击以激活</string> <string name="click_to_activate">点击以激活</string>
@@ -72,6 +73,16 @@
<string name="activate_jump" tools:ignore="TypographyEllipsis">激活...</string> <string name="activate_jump" tools:ignore="TypographyEllipsis">激活...</string>
<string name="profile_owner">Profile owner</string> <string name="profile_owner">Profile owner</string>
<string name="device_owner">Device owner</string> <string name="device_owner">Device owner</string>
<string name="delegated_admins">委托管理员</string>
<string name="delegated_scope">委托作用域</string>
<string name="manage_application_restrictions">管理应用限制</string>
<string name="manage_certificates">管理证书</string>
<string name="select_keychain_certificates">选择密钥链证书</string>
<string name="install_existing_packages">安装存在的软件包</string>
<string name="manage_uninstalled_packages">管理已被卸载的软件包</string>
<string name="change_package_state">修改软件包状态</string>
<string name="grant_permissions">授予权限</string>
<string name="add_delegated_admin">添加委托管理员</string>
<string name="reset_device_policy">重置设备策略</string> <string name="reset_device_policy">重置设备策略</string>
<string name="dhizuku_will_be_deactivated">Dhizuku将被停用</string> <string name="dhizuku_will_be_deactivated">Dhizuku将被停用</string>
<string name="activate_device_admin">激活Device admin</string> <string name="activate_device_admin">激活Device admin</string>
@@ -365,7 +376,7 @@
<string name="scope_is_work_profile">作用域: 工作资料</string> <string name="scope_is_work_profile">作用域: 工作资料</string>
<string name="app_info">应用详情</string> <string name="app_info">应用详情</string>
<string name="not_installed">未安装</string> <string name="not_installed">未安装</string>
<string name="block_uninstall">防卸载</string> <string name="block_uninstall">阻止</string>
<string name="ucd">禁止用户控制</string> <string name="ucd">禁止用户控制</string>
<string name="ucd_desc">用户将无法清除这些应用的存储空间或强制停止这些应用</string> <string name="ucd_desc">用户将无法清除这些应用的存储空间或强制停止这些应用</string>
<string name="app_list_is">应用列表:</string> <string name="app_list_is">应用列表:</string>

View File

@@ -78,6 +78,16 @@
<string name="activate_jump" tools:ignore="TypographyEllipsis">Activate...</string> <string name="activate_jump" tools:ignore="TypographyEllipsis">Activate...</string>
<string name="profile_owner">Profile owner</string> <string name="profile_owner">Profile owner</string>
<string name="device_owner">Device owner</string> <string name="device_owner">Device owner</string>
<string name="delegated_admins">Delegated admins</string>
<string name="delegated_scope">delegated scope</string>
<string name="manage_application_restrictions">Manage application restrictions</string>
<string name="manage_certificates">Manage certificates</string>
<string name="select_keychain_certificates">Select KeyChain certificate</string>
<string name="install_existing_packages">Install existing packages</string>
<string name="manage_uninstalled_packages">Manage uninstalled packages</string>
<string name="change_package_state">Change package state</string>
<string name="grant_permissions">Grant permissions</string>
<string name="add_delegated_admin">Add delegated admin</string>
<string name="dhizuku_will_be_deactivated">Dhizuku will be deactivated</string> <string name="dhizuku_will_be_deactivated">Dhizuku will be deactivated</string>
<string name="reset_device_policy">Reset device policy</string> <string name="reset_device_policy">Reset device policy</string>
<string name="activate_device_admin">Activate Device admin</string> <string name="activate_device_admin">Activate Device admin</string>

View File

@@ -1,5 +1,5 @@
[versions] [versions]
agp = "8.7.3" agp = "8.8.0"
kotlin = "2.0.21" kotlin = "2.0.21"
navigation-compose = "2.8.5" navigation-compose = "2.8.5"

View File

@@ -1,6 +1,6 @@
#Fri Jan 12 20:22:20 CST 2024 #Fri Jan 12 20:22:20 CST 2024
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists