Some improvement of Create user and User operation

Use User ID in User operation
Add icons to buttons in User operation
Display created user serial number in a dialog
Catch exception when creating user, close #99
Create user in background
This commit is contained in:
BinTianqi
2025-02-08 22:04:35 +08:00
parent 9528d3eb8d
commit 9ecd87da71
6 changed files with 75 additions and 44 deletions

View File

@@ -38,6 +38,10 @@ android {
"proguard-rules.pro" "proguard-rules.pro"
) )
signingConfig = signingConfigs.getByName("defaultSignature") signingConfig = signingConfigs.getByName("defaultSignature")
composeCompiler {
includeSourceInformation = false
includeTraceMarkers = false
}
} }
debug { debug {
signingConfig = signingConfigs.getByName("defaultSignature") signingConfig = signingConfigs.getByName("defaultSignature")

View File

@@ -31,21 +31,30 @@ import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.SegmentedButton
import androidx.compose.material3.SegmentedButtonDefaults
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue 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
@@ -53,10 +62,13 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.asImageBitmap
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.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.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.DialogProperties
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import com.bintianqi.owndroid.R import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.parseTimestamp import com.bintianqi.owndroid.parseTimestamp
@@ -70,6 +82,9 @@ import com.bintianqi.owndroid.ui.MyScaffold
import com.bintianqi.owndroid.ui.SwitchItem import com.bintianqi.owndroid.ui.SwitchItem
import com.bintianqi.owndroid.uriToStream import com.bintianqi.owndroid.uriToStream
import com.bintianqi.owndroid.yesOrNo import com.bintianqi.owndroid.yesOrNo
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@Composable @Composable
fun Users(navCtrl: NavHostController) { fun Users(navCtrl: NavHostController) {
@@ -202,14 +217,14 @@ fun UserOperation(navCtrl: NavHostController) {
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
val dpm = context.getDPM() val dpm = context.getDPM()
val receiver = context.getReceiver() val receiver = context.getReceiver()
var idInput by remember { mutableStateOf("") } var input by remember { mutableStateOf("") }
var useUid by remember { mutableStateOf(false) }
val focusMgr = LocalFocusManager.current val focusMgr = LocalFocusManager.current
var useUserId by remember { mutableStateOf(false) }
fun withUserHandle(operation: (UserHandle) -> Unit) { fun withUserHandle(operation: (UserHandle) -> Unit) {
val userHandle = if(useUid && VERSION.SDK_INT >= 24) { val userHandle = if(useUserId && VERSION.SDK_INT >= 24) {
UserHandle.getUserHandleForUid(idInput.toInt()) UserHandle.getUserHandleForUid(input.toInt() * 100000)
} else { } else {
userManager.getUserForSerialNumber(idInput.toLong()) userManager.getUserForSerialNumber(input.toLong())
} }
if(userHandle == null) { if(userHandle == null) {
Toast.makeText(context, R.string.user_not_exist, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.user_not_exist, Toast.LENGTH_SHORT).show()
@@ -217,27 +232,24 @@ fun UserOperation(navCtrl: NavHostController) {
operation(userHandle) operation(userHandle)
} }
} }
val legalInput = try { val legalInput = input.toIntOrNull() != null
idInput.toInt()
true
} catch(_: Exception) {
false
}
MyScaffold(R.string.user_operation, 8.dp, navCtrl) { MyScaffold(R.string.user_operation, 8.dp, navCtrl) {
if(VERSION.SDK_INT >= 24) SingleChoiceSegmentedButtonRow(modifier = Modifier.fillMaxWidth()) {
SegmentedButton(!useUserId, { useUserId = false }, SegmentedButtonDefaults.itemShape(0, 2)) {
Text(stringResource(R.string.serial_number))
}
SegmentedButton(useUserId, { useUserId = true }, SegmentedButtonDefaults.itemShape(1, 2)) {
Text(stringResource(R.string.user_id))
}
}
OutlinedTextField( OutlinedTextField(
value = idInput, value = input,
onValueChange = { onValueChange = { input = it },
idInput = it label = { Text(stringResource(if(useUserId) R.string.user_id else R.string.serial_number)) },
}, modifier = Modifier.fillMaxWidth().padding(top = 4.dp, bottom = 8.dp),
label = { Text(if(useUid) "UID" else stringResource(R.string.serial_number)) },
modifier = Modifier.fillMaxWidth(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = { focusMgr.clearFocus() }) keyboardActions = KeyboardActions(onDone = { focusMgr.clearFocus() })
) )
Spacer(Modifier.padding(vertical = 3.dp))
if(VERSION.SDK_INT >= 24) {
CheckBoxItem(text = R.string.use_uid, checked = useUid, operation = { idInput=""; useUid = it })
}
if(VERSION.SDK_INT >= 28) { if(VERSION.SDK_INT >= 28) {
Button( Button(
onClick = { onClick = {
@@ -250,6 +262,7 @@ fun UserOperation(navCtrl: NavHostController) {
enabled = legalInput, enabled = legalInput,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
Icon(Icons.Default.PlayArrow, null, Modifier.padding(end = 4.dp))
Text(stringResource(R.string.start_in_background)) Text(stringResource(R.string.start_in_background))
} }
} }
@@ -261,6 +274,7 @@ fun UserOperation(navCtrl: NavHostController) {
enabled = legalInput, enabled = legalInput,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
Icon(painterResource(R.drawable.sync_alt_fill0), null, Modifier.padding(end = 4.dp))
Text(stringResource(R.string.user_operation_switch)) Text(stringResource(R.string.user_operation_switch))
} }
if(VERSION.SDK_INT >= 28) { if(VERSION.SDK_INT >= 28) {
@@ -275,6 +289,7 @@ fun UserOperation(navCtrl: NavHostController) {
enabled = legalInput, enabled = legalInput,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
Icon(Icons.Default.Close, null, Modifier.padding(end = 4.dp))
Text(stringResource(R.string.stop)) Text(stringResource(R.string.stop))
} }
} }
@@ -284,7 +299,7 @@ fun UserOperation(navCtrl: NavHostController) {
withUserHandle { withUserHandle {
if(dpm.removeUser(receiver, it)) { if(dpm.removeUser(receiver, it)) {
context.showOperationResultToast(true) context.showOperationResultToast(true)
idInput = "" input = ""
} else { } else {
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show()
} }
@@ -293,9 +308,9 @@ fun UserOperation(navCtrl: NavHostController) {
enabled = legalInput, enabled = legalInput,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
Icon(Icons.Default.Delete, null, Modifier.padding(end = 4.dp))
Text(stringResource(R.string.delete)) Text(stringResource(R.string.delete))
} }
InfoCard(R.string.info_user_operation)
} }
} }
@@ -308,7 +323,10 @@ fun CreateUser(navCtrl: NavHostController) {
val receiver = context.getReceiver() val receiver = context.getReceiver()
val focusMgr = LocalFocusManager.current val focusMgr = LocalFocusManager.current
var userName by remember { mutableStateOf("") } var userName by remember { mutableStateOf("") }
var creating by remember { mutableStateOf(false) }
var createdUserSerialNumber by remember { mutableLongStateOf(-1) }
var flag by remember { mutableIntStateOf(0) } var flag by remember { mutableIntStateOf(0) }
val coroutine = rememberCoroutineScope()
MyScaffold(R.string.create_user, 8.dp, navCtrl) { MyScaffold(R.string.create_user, 8.dp, navCtrl) {
OutlinedTextField( OutlinedTextField(
value = userName, value = userName,
@@ -333,20 +351,39 @@ fun CreateUser(navCtrl: NavHostController) {
flag and DevicePolicyManager.LEAVE_ALL_SYSTEM_APPS_ENABLED != 0 flag and DevicePolicyManager.LEAVE_ALL_SYSTEM_APPS_ENABLED != 0
) { flag = flag xor DevicePolicyManager.LEAVE_ALL_SYSTEM_APPS_ENABLED } ) { flag = flag xor DevicePolicyManager.LEAVE_ALL_SYSTEM_APPS_ENABLED }
} }
var newUserHandle: UserHandle? by remember { mutableStateOf(null) }
Spacer(Modifier.padding(vertical = 5.dp)) Spacer(Modifier.padding(vertical = 5.dp))
Button( Button(
onClick = { onClick = {
focusMgr.clearFocus() focusMgr.clearFocus()
newUserHandle = dpm.createAndManageUser(receiver, userName, receiver, null, flag) creating = true
context.showOperationResultToast(newUserHandle != null) coroutine.launch(Dispatchers.IO) {
println(Thread.currentThread().name)
try {
val uh = dpm.createAndManageUser(receiver, userName, receiver, null, flag)
withContext(Dispatchers.Main) {
createdUserSerialNumber = userManager.getSerialNumberForUser(uh)
}
} catch(_: Exception) {
context.showOperationResultToast(false)
}
withContext(Dispatchers.Main) { creating = false }
}
}, },
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
Text(stringResource(R.string.create)) Text(stringResource(R.string.create))
} }
Spacer(Modifier.padding(vertical = 5.dp)) if(createdUserSerialNumber != -1L) AlertDialog(
if(newUserHandle != null) { Text(text = stringResource(R.string.serial_number_of_new_user_is, userManager.getSerialNumberForUser(newUserHandle))) } title = { Text(stringResource(R.string.success)) },
text = { Text(stringResource(R.string.serial_number_of_new_user_is, createdUserSerialNumber)) },
confirmButton = {
TextButton({ createdUserSerialNumber = -1 }) { Text(stringResource(R.string.confirm)) }
},
onDismissRequest = { createdUserSerialNumber = -1 }
)
if(creating) Dialog({}, DialogProperties(false, false)) {
CircularProgressIndicator()
}
} }
} }

View File

@@ -508,14 +508,12 @@
<string name="logout_enabled">Выход из системы разрешен</string> <string name="logout_enabled">Выход из системы разрешен</string>
<string name="ephemeral_user">Временный пользователь</string> <string name="ephemeral_user">Временный пользователь</string>
<string name="affiliated_user">Аффилированный пользователь</string> <string name="affiliated_user">Аффилированный пользователь</string>
<string name="user_id">Идентификатор пользователя</string>
<string name="user_serial_number">Серийный номер пользователя</string> <string name="user_serial_number">Серийный номер пользователя</string>
<string name="user_operation">Операция с пользователем</string> <string name="user_operation">Операция с пользователем</string>
<string name="user_not_exist">Пользователь не существует</string> <string name="user_not_exist">Пользователь не существует</string>
<string name="serial_number">Серийный номер</string> <string name="serial_number">Серийный номер</string>
<string name="secondary_users">Вторичные пользователи</string> <string name="secondary_users">Вторичные пользователи</string>
<string name="no_secondary_users">Нет вторичных пользователей</string> <string name="no_secondary_users">Нет вторичных пользователей</string>
<string name="use_uid">Использовать UID</string>
<string name="logout_current_user">Выйти из текущего пользователя</string> <string name="logout_current_user">Выйти из текущего пользователя</string>
<string name="start_in_background">Запустить в фоновом режиме</string> <string name="start_in_background">Запустить в фоновом режиме</string>
<string name="user_operation_switch">Переключиться</string> <string name="user_operation_switch">Переключиться</string>
@@ -524,7 +522,7 @@
<string name="create_user_skip_wizard">Пропустить мастер настройки</string> <string name="create_user_skip_wizard">Пропустить мастер настройки</string>
<string name="create_user_ephemeral_user">Временный пользователь</string> <string name="create_user_ephemeral_user">Временный пользователь</string>
<string name="create_user_enable_all_system_app">Включить все системные приложения</string> <string name="create_user_enable_all_system_app">Включить все системные приложения</string>
<string name="serial_number_of_new_user_is">Серийный номер этого пользователя: %1$s</string> <string name="serial_number_of_new_user_is">Серийный номер этого пользователя: %1$d</string>
<string name="affiliation_id">Аффилированный идентификатор</string> <string name="affiliation_id">Аффилированный идентификатор</string>
<string name="change_user_icon">Изменить значок пользователя</string> <string name="change_user_icon">Изменить значок пользователя</string>
<string name="file_picker_instead_gallery">Использовать выборщик файлов вместо галереи</string> <string name="file_picker_instead_gallery">Использовать выборщик файлов вместо галереи</string>
@@ -702,7 +700,6 @@
<string name="info_disable_user_control">Пользователь не сможет очищать данные приложений или принудительно останавливать пакеты.</string> <string name="info_disable_user_control">Пользователь не сможет очищать данные приложений или принудительно останавливать пакеты.</string>
<string name="info_keep_uninstalled_apps">Установить список приложений, которые нужно сохранить в виде APK-файлов, даже если ни у одного пользователя в данный момент они не установлены.</string> <string name="info_keep_uninstalled_apps">Установить список приложений, которые нужно сохранить в виде APK-файлов, даже если ни у одного пользователя в данный момент они не установлены.</string>
<string name="info_headless_system_user_mode">Режим "безголового" системного пользователя означает, что системный пользователь запускает системные службы и некоторый системный интерфейс, но он не связан с каким-либо реальным человеком, и для связи с реальными людьми должны быть созданы дополнительные пользователи.</string> <string name="info_headless_system_user_mode">Режим "безголового" системного пользователя означает, что системный пользователь запускает системные службы и некоторый системный интерфейс, но он не связан с каким-либо реальным человеком, и для связи с реальными людьми должны быть созданы дополнительные пользователи.</string>
<string name="info_user_operation">Рекомендуется указать пользователя по серийному номеру, также можно использовать UID, UID должен принадлежать любому из приложений целевого пользователя.</string>
<string name="info_affiliated_id">Когда владелец устройства создает управляемого пользователя, управляемый пользователь не является аффилированным. Чтобы сделать управляемого пользователя аффилированным с владельцем устройства, вам следует установить одинаковые аффилированные идентификаторы в основном и управляемом пользователях.</string> <string name="info_affiliated_id">Когда владелец устройства создает управляемого пользователя, управляемый пользователь не является аффилированным. Чтобы сделать управляемого пользователя аффилированным с владельцем устройства, вам следует установить одинаковые аффилированные идентификаторы в основном и управляемом пользователях.</string>
<string name="info_reset_password">Установить новый пароль блокировки экрана. Длина этого пароля должна быть не менее 4 цифр. Оставьте поле пустым, чтобы удалить пароль.\nЕсли вы установите цифровой пароль длиной 6 символов или меньше, он будет установлен как PIN-код.</string> <string name="info_reset_password">Установить новый пароль блокировки экрана. Длина этого пароля должна быть не менее 4 цифр. Оставьте поле пустым, чтобы удалить пароль.\nЕсли вы установите цифровой пароль длиной 6 символов или меньше, он будет установлен как PIN-код.</string>
<string name="info_screen_timeout">Установить максимальное время бездействия пользователя, по истечении которого устройство будет заблокировано. Это ограничивает время, которое может установить пользователь.\nЗначение 0 означает отсутствие ограничений.</string> <string name="info_screen_timeout">Установить максимальное время бездействия пользователя, по истечении которого устройство будет заблокировано. Это ограничивает время, которое может установить пользователь.\nЗначение 0 означает отсутствие ограничений.</string>

View File

@@ -512,14 +512,12 @@
<string name="logout_enabled">Logout enabled</string> <!--TODO--> <string name="logout_enabled">Logout enabled</string> <!--TODO-->
<string name="ephemeral_user">Geçici kullanıcı</string> <string name="ephemeral_user">Geçici kullanıcı</string>
<string name="affiliated_user">Bağlı kullanıcı</string> <string name="affiliated_user">Bağlı kullanıcı</string>
<string name="user_id">Kullanıcı ID</string>
<string name="user_serial_number">Kullanıcı seri numarası</string> <string name="user_serial_number">Kullanıcı seri numarası</string>
<string name="secondary_users">Secondary users</string> <!--TODO--> <string name="secondary_users">Secondary users</string> <!--TODO-->
<string name="no_secondary_users">No secondary users</string> <!--TODO--> <string name="no_secondary_users">No secondary users</string> <!--TODO-->
<string name="user_operation">Kullanıcı işlemi</string> <string name="user_operation">Kullanıcı işlemi</string>
<string name="user_not_exist">User does not exist</string> <!--TODO--> <string name="user_not_exist">User does not exist</string> <!--TODO-->
<string name="serial_number">Seri numarası</string> <string name="serial_number">Seri numarası</string>
<string name="use_uid">UID kullan</string>
<string name="logout_current_user">Mevcut kullanıcıyı çıkış yap</string> <string name="logout_current_user">Mevcut kullanıcıyı çıkış yap</string>
<string name="start_in_background">Arka planda başlat</string> <string name="start_in_background">Arka planda başlat</string>
<string name="user_operation_switch">Değiştir</string> <string name="user_operation_switch">Değiştir</string>
@@ -528,7 +526,7 @@
<string name="create_user_skip_wizard">Sihirbazı atla</string> <string name="create_user_skip_wizard">Sihirbazı atla</string>
<string name="create_user_ephemeral_user">Geçici kullanıcı</string> <string name="create_user_ephemeral_user">Geçici kullanıcı</string>
<string name="create_user_enable_all_system_app">Tüm sistem uygulamalarını etkinleştir</string> <string name="create_user_enable_all_system_app">Tüm sistem uygulamalarını etkinleştir</string>
<string name="serial_number_of_new_user_is">Bu kullanıcının seri numarası: %1$s</string> <string name="serial_number_of_new_user_is">Bu kullanıcının seri numarası: %1$d</string>
<string name="affiliation_id">Bağlılık ID</string> <string name="affiliation_id">Bağlılık ID</string>
<string name="change_user_icon">Kullanıcı simgesini değiştir</string> <string name="change_user_icon">Kullanıcı simgesini değiştir</string>
<string name="file_picker_instead_gallery">Galeri yerine dosya seçici kullan</string> <string name="file_picker_instead_gallery">Galeri yerine dosya seçici kullan</string>

View File

@@ -499,14 +499,12 @@
<string name="logout_enabled">用户可登出</string> <string name="logout_enabled">用户可登出</string>
<string name="ephemeral_user">临时用户</string> <string name="ephemeral_user">临时用户</string>
<string name="affiliated_user">附属用户</string> <string name="affiliated_user">附属用户</string>
<string name="user_id">当前UserID</string>
<string name="user_serial_number">当前用户序列号</string> <string name="user_serial_number">当前用户序列号</string>
<string name="secondary_users">次要用户</string> <string name="secondary_users">次要用户</string>
<string name="no_secondary_users">无次要用户</string> <string name="no_secondary_users">无次要用户</string>
<string name="user_operation">用户操作</string> <string name="user_operation">用户操作</string>
<string name="user_not_exist">用户不存在</string> <string name="user_not_exist">用户不存在</string>
<string name="serial_number">序列号</string> <string name="serial_number">序列号</string>
<string name="use_uid">使用UID</string>
<string name="logout_current_user">登出当前用户</string> <string name="logout_current_user">登出当前用户</string>
<string name="start_in_background">在后台启动</string> <string name="start_in_background">在后台启动</string>
<string name="user_operation_switch">切换</string> <string name="user_operation_switch">切换</string>
@@ -515,7 +513,7 @@
<string name="create_user_skip_wizard">跳过创建用户向导</string> <string name="create_user_skip_wizard">跳过创建用户向导</string>
<string name="create_user_ephemeral_user">临时用户</string> <string name="create_user_ephemeral_user">临时用户</string>
<string name="create_user_enable_all_system_app">启用所有系统应用</string> <string name="create_user_enable_all_system_app">启用所有系统应用</string>
<string name="serial_number_of_new_user_is">新用户的序列号:%1$s</string> <string name="serial_number_of_new_user_is">新用户的序列号:%1$d</string>
<string name="affiliation_id">附属用户ID</string> <string name="affiliation_id">附属用户ID</string>
<string name="change_user_icon">更换用户头像</string> <string name="change_user_icon">更换用户头像</string>
<string name="file_picker_instead_gallery">使用文件选择器而不是相册</string> <string name="file_picker_instead_gallery">使用文件选择器而不是相册</string>
@@ -689,7 +687,6 @@
<string name="info_disable_user_control">用户无法清除这些应用的存储空间,也无法强制停止应用</string> <string name="info_disable_user_control">用户无法清除这些应用的存储空间,也无法强制停止应用</string>
<string name="info_keep_uninstalled_apps">这个列表中的应用的APK将会一直保留即使没有任何用户安装这个应用</string> <string name="info_keep_uninstalled_apps">这个列表中的应用的APK将会一直保留即使没有任何用户安装这个应用</string>
<string name="info_headless_system_user_mode">无头系统用户模式意味着系统用户运行系统服务和一些系统UI但它不与任何真实的人相关联必须创建额外的用户才能与真实的人相关联。</string> <string name="info_headless_system_user_mode">无头系统用户模式意味着系统用户运行系统服务和一些系统UI但它不与任何真实的人相关联必须创建额外的用户才能与真实的人相关联。</string>
<string name="info_user_operation">推荐使用用户序列号来标识用户如果要使用UIDUID可以是运行在目标用户中任意应用的UID</string>
<string name="info_affiliated_id">当Device owner创建并管理用户时新的用户不是附属用户。Device owner设置和受管理用户完全相同的附属用户ID后受管理用户成为附属于Device owner的用户</string> <string name="info_affiliated_id">当Device owner创建并管理用户时新的用户不是附属用户。Device owner设置和受管理用户完全相同的附属用户ID后受管理用户成为附属于Device owner的用户</string>
<string name="info_reset_password">设置一个新的密码密码的长度需要4位或以上不输入密码将会清除现有的密码。长度在6位或以下的纯数字密码将会设置为PIN码。</string> <string name="info_reset_password">设置一个新的密码密码的长度需要4位或以上不输入密码将会清除现有的密码。长度在6位或以下的纯数字密码将会设置为PIN码。</string>
<string name="info_screen_timeout">设置设备锁定前用户活动的最大时间。这限制了用户可以设置的时间长度。\n值为0表示不做限制。</string> <string name="info_screen_timeout">设置设备锁定前用户活动的最大时间。这限制了用户可以设置的时间长度。\n值为0表示不做限制。</string>

View File

@@ -537,14 +537,13 @@
<string name="logout_enabled">Logout enabled</string> <string name="logout_enabled">Logout enabled</string>
<string name="ephemeral_user">Ephemeral user</string> <string name="ephemeral_user">Ephemeral user</string>
<string name="affiliated_user">Affiliated user</string> <string name="affiliated_user">Affiliated user</string>
<string name="user_id">UserID</string> <string name="user_id" translatable="false">User ID</string>
<string name="user_serial_number">User serial number</string> <string name="user_serial_number">User serial number</string>
<string name="secondary_users">Secondary users</string> <string name="secondary_users">Secondary users</string>
<string name="no_secondary_users">No secondary users</string> <string name="no_secondary_users">No secondary users</string>
<string name="user_operation">User operation</string> <string name="user_operation">User operation</string>
<string name="user_not_exist">User does not exist</string> <string name="user_not_exist">User does not exist</string>
<string name="serial_number">Serial number</string> <string name="serial_number">Serial number</string>
<string name="use_uid">Use UID</string>
<string name="logout_current_user">Logout current user</string> <string name="logout_current_user">Logout current user</string>
<string name="start_in_background">Start in background</string> <string name="start_in_background">Start in background</string>
<string name="user_operation_switch">Switch</string> <string name="user_operation_switch">Switch</string>
@@ -553,7 +552,7 @@
<string name="create_user_skip_wizard">Skip wizard</string> <string name="create_user_skip_wizard">Skip wizard</string>
<string name="create_user_ephemeral_user">Ephemeral user</string> <string name="create_user_ephemeral_user">Ephemeral user</string>
<string name="create_user_enable_all_system_app">Enable all system app</string> <string name="create_user_enable_all_system_app">Enable all system app</string>
<string name="serial_number_of_new_user_is">Serial number of this user: %1$s</string> <string name="serial_number_of_new_user_is">Serial number of this user: %1$d</string>
<string name="affiliation_id">Affiliation ID</string> <string name="affiliation_id">Affiliation ID</string>
<string name="change_user_icon">Change user icon</string> <string name="change_user_icon">Change user icon</string>
<string name="file_picker_instead_gallery">Use file picker instead of gallery</string> <string name="file_picker_instead_gallery">Use file picker instead of gallery</string>
@@ -727,7 +726,6 @@
<string name="info_disable_user_control">User will not be able to clear app data or force-stop packages.</string> <string name="info_disable_user_control">User will not be able to clear app data or force-stop packages.</string>
<string name="info_keep_uninstalled_apps">Set a list of apps to keep around as APKs even if no user has currently installed it. </string> <string name="info_keep_uninstalled_apps">Set a list of apps to keep around as APKs even if no user has currently installed it. </string>
<string name="info_headless_system_user_mode">Headless system user mode means the system user runs system services and some system UI, but it is not associated with any real person and additional users must be created to be associated with real persons.</string> <string name="info_headless_system_user_mode">Headless system user mode means the system user runs system services and some system UI, but it is not associated with any real person and additional users must be created to be associated with real persons.</string>
<string name="info_user_operation">It is recommended to specify a user with serial number, you can also use UID, the UID should be any of the apps in the target user.</string>
<string name="info_affiliated_id">When Device owner create a managed user, the managed user isn\'t affiliated. In order to make the managed user affiliated with the Device owner, you should set same affiliated IDs in main user and managed user</string> <string name="info_affiliated_id">When Device owner create a managed user, the managed user isn\'t affiliated. In order to make the managed user affiliated with the Device owner, you should set same affiliated IDs in main user and managed user</string>
<string name="info_reset_password">Set a new lockscreen password. The length of this password must be at least 4 digits. Keep it empty to remove password.\nIf you set a numeric password that length is 6 or lower, it will set as PIN</string> <string name="info_reset_password">Set a new lockscreen password. The length of this password must be at least 4 digits. Keep it empty to remove password.\nIf you set a numeric password that length is 6 or lower, it will set as PIN</string>
<string name="info_screen_timeout">Set the maximum time for user activity until the device will lock. This limits the length that the user can set.\nA value of 0 means there is no restriction.</string> <string name="info_screen_timeout">Set the maximum time for user activity until the device will lock. This limits the length that the user can set.\nA value of 0 means there is no restriction.</string>