Refactor Applications, add app list view

This commit is contained in:
BinTianqi
2025-03-22 09:45:55 +08:00
parent 52a29331be
commit 1212a40e7a
11 changed files with 1025 additions and 811 deletions

View File

@@ -74,8 +74,12 @@ import com.bintianqi.owndroid.dpm.AffiliationId
import com.bintianqi.owndroid.dpm.AffiliationIdScreen
import com.bintianqi.owndroid.dpm.AlwaysOnVpnPackage
import com.bintianqi.owndroid.dpm.AlwaysOnVpnPackageScreen
import com.bintianqi.owndroid.dpm.Applications
import com.bintianqi.owndroid.dpm.ApplicationsScreen
import com.bintianqi.owndroid.dpm.ApplicationDetails
import com.bintianqi.owndroid.dpm.ApplicationDetailsScreen
import com.bintianqi.owndroid.dpm.ApplicationsFeatures
import com.bintianqi.owndroid.dpm.ApplicationsFeaturesScreen
import com.bintianqi.owndroid.dpm.BlockUninstall
import com.bintianqi.owndroid.dpm.BlockUninstallScreen
import com.bintianqi.owndroid.dpm.CaCert
import com.bintianqi.owndroid.dpm.CaCertScreen
import com.bintianqi.owndroid.dpm.ChangeTime
@@ -84,14 +88,22 @@ import com.bintianqi.owndroid.dpm.ChangeTimeZone
import com.bintianqi.owndroid.dpm.ChangeTimeZoneScreen
import com.bintianqi.owndroid.dpm.ChangeUsername
import com.bintianqi.owndroid.dpm.ChangeUsernameScreen
import com.bintianqi.owndroid.dpm.ClearAppStorage
import com.bintianqi.owndroid.dpm.ClearAppStorageScreen
import com.bintianqi.owndroid.dpm.ContentProtectionPolicy
import com.bintianqi.owndroid.dpm.ContentProtectionPolicyScreen
import com.bintianqi.owndroid.dpm.CreateUser
import com.bintianqi.owndroid.dpm.CreateUserScreen
import com.bintianqi.owndroid.dpm.CreateWorkProfile
import com.bintianqi.owndroid.dpm.CreateWorkProfileScreen
import com.bintianqi.owndroid.dpm.CredentialManagerPolicy
import com.bintianqi.owndroid.dpm.CredentialManagerPolicyScreen
import com.bintianqi.owndroid.dpm.CrossProfileIntentFilter
import com.bintianqi.owndroid.dpm.CrossProfileIntentFilterScreen
import com.bintianqi.owndroid.dpm.CrossProfilePackages
import com.bintianqi.owndroid.dpm.CrossProfilePackagesScreen
import com.bintianqi.owndroid.dpm.CrossProfileWidgetProviders
import com.bintianqi.owndroid.dpm.CrossProfileWidgetProvidersScreen
import com.bintianqi.owndroid.dpm.DelegatedAdmins
import com.bintianqi.owndroid.dpm.DelegatedAdminsScreen
import com.bintianqi.owndroid.dpm.DeleteWorkProfile
@@ -104,12 +116,24 @@ import com.bintianqi.owndroid.dpm.DeviceOwner
import com.bintianqi.owndroid.dpm.DeviceOwnerScreen
import com.bintianqi.owndroid.dpm.DisableAccountManagement
import com.bintianqi.owndroid.dpm.DisableAccountManagementScreen
import com.bintianqi.owndroid.dpm.DisableMeteredData
import com.bintianqi.owndroid.dpm.DisableMeteredDataScreen
import com.bintianqi.owndroid.dpm.DisableUserControl
import com.bintianqi.owndroid.dpm.DisableUserControlScreen
import com.bintianqi.owndroid.dpm.EnableSystemApp
import com.bintianqi.owndroid.dpm.EnableSystemAppScreen
import com.bintianqi.owndroid.dpm.FrpPolicy
import com.bintianqi.owndroid.dpm.FrpPolicyScreen
import com.bintianqi.owndroid.dpm.HardwareMonitor
import com.bintianqi.owndroid.dpm.HardwareMonitorScreen
import com.bintianqi.owndroid.dpm.Hide
import com.bintianqi.owndroid.dpm.HideScreen
import com.bintianqi.owndroid.dpm.InstallExistingApp
import com.bintianqi.owndroid.dpm.InstallExistingAppScreen
import com.bintianqi.owndroid.dpm.InstallSystemUpdate
import com.bintianqi.owndroid.dpm.InstallSystemUpdateScreen
import com.bintianqi.owndroid.dpm.KeepUninstalledPackages
import com.bintianqi.owndroid.dpm.KeepUninstalledPackagesScreen
import com.bintianqi.owndroid.dpm.Keyguard
import com.bintianqi.owndroid.dpm.KeyguardDisabledFeatures
import com.bintianqi.owndroid.dpm.KeyguardDisabledFeaturesScreen
@@ -142,7 +166,13 @@ import com.bintianqi.owndroid.dpm.PasswordScreen
import com.bintianqi.owndroid.dpm.PermissionPolicy
import com.bintianqi.owndroid.dpm.PermissionPolicyScreen
import com.bintianqi.owndroid.dpm.Permissions
import com.bintianqi.owndroid.dpm.PermissionsManager
import com.bintianqi.owndroid.dpm.PermissionsManagerScreen
import com.bintianqi.owndroid.dpm.PermissionsScreen
import com.bintianqi.owndroid.dpm.PermittedAccessibilityServices
import com.bintianqi.owndroid.dpm.PermittedAccessibilityServicesScreen
import com.bintianqi.owndroid.dpm.PermittedInputMethods
import com.bintianqi.owndroid.dpm.PermittedInputMethodsScreen
import com.bintianqi.owndroid.dpm.PreferentialNetworkService
import com.bintianqi.owndroid.dpm.PreferentialNetworkServiceScreen
import com.bintianqi.owndroid.dpm.PrivateDns
@@ -163,12 +193,16 @@ import com.bintianqi.owndroid.dpm.ResetPasswordTokenScreen
import com.bintianqi.owndroid.dpm.Restriction
import com.bintianqi.owndroid.dpm.SecurityLogging
import com.bintianqi.owndroid.dpm.SecurityLoggingScreen
import com.bintianqi.owndroid.dpm.SetDefaultDialer
import com.bintianqi.owndroid.dpm.SetDefaultDialerScreen
import com.bintianqi.owndroid.dpm.SetSystemUpdatePolicy
import com.bintianqi.owndroid.dpm.ShizukuScreen
import com.bintianqi.owndroid.dpm.SupportMessage
import com.bintianqi.owndroid.dpm.SupportMessageScreen
import com.bintianqi.owndroid.dpm.Suspend
import com.bintianqi.owndroid.dpm.SuspendPersonalApp
import com.bintianqi.owndroid.dpm.SuspendPersonalAppScreen
import com.bintianqi.owndroid.dpm.SuspendScreen
import com.bintianqi.owndroid.dpm.SystemManager
import com.bintianqi.owndroid.dpm.SystemManagerScreen
import com.bintianqi.owndroid.dpm.SystemOptions
@@ -176,6 +210,8 @@ import com.bintianqi.owndroid.dpm.SystemOptionsScreen
import com.bintianqi.owndroid.dpm.SystemUpdatePolicyScreen
import com.bintianqi.owndroid.dpm.TransferOwnership
import com.bintianqi.owndroid.dpm.TransferOwnershipScreen
import com.bintianqi.owndroid.dpm.UninstallApp
import com.bintianqi.owndroid.dpm.UninstallAppScreen
import com.bintianqi.owndroid.dpm.UserInfo
import com.bintianqi.owndroid.dpm.UserInfoScreen
import com.bintianqi.owndroid.dpm.UserOperation
@@ -348,7 +384,42 @@ fun Home(vm: MyViewModel) {
composable<CrossProfileIntentFilter> { CrossProfileIntentFilterScreen(::navigateUp) }
composable<DeleteWorkProfile> { DeleteWorkProfileScreen(::navigateUp) }
composable<Applications> { ApplicationsScreen(::navigateUp) }
composable<ApplicationsList> {
AppChooserScreen(it.toRoute(), {
if(it == null) navigateUp() else navigate(ApplicationDetails(it))
}, {
SharedPrefs(context).applicationsListView = false
navController.navigate(ApplicationsFeatures) {
popUpTo(Home)
}
})
}
composable<ApplicationsFeatures> {
ApplicationsFeaturesScreen(::navigateUp, ::navigate) {
SharedPrefs(context).applicationsListView = true
navController.navigate(ApplicationsList(true)) {
popUpTo(Home)
}
}
}
composable<ApplicationDetails> { ApplicationDetailsScreen(it.toRoute(), ::navigateUp, ::navigate) }
composable<Suspend> { SuspendScreen(::navigateUp) }
composable<Hide> { HideScreen(::navigateUp) }
composable<BlockUninstall> { BlockUninstallScreen(::navigateUp) }
composable<DisableUserControl> { DisableUserControlScreen(::navigateUp) }
composable<PermissionsManager> { PermissionsManagerScreen(::navigateUp, it.toRoute()) }
composable<DisableMeteredData> { DisableMeteredDataScreen(::navigateUp) }
composable<ClearAppStorage> { ClearAppStorageScreen(::navigateUp) }
composable<UninstallApp> { UninstallAppScreen(::navigateUp) }
composable<KeepUninstalledPackages> { KeepUninstalledPackagesScreen(::navigateUp) }
composable<InstallExistingApp> { InstallExistingAppScreen(::navigateUp) }
composable<CrossProfilePackages> { CrossProfilePackagesScreen(::navigateUp) }
composable<CrossProfileWidgetProviders> { CrossProfileWidgetProvidersScreen(::navigateUp) }
composable<CredentialManagerPolicy> { CredentialManagerPolicyScreen(::navigateUp) }
composable<PermittedAccessibilityServices> { PermittedAccessibilityServicesScreen(::navigateUp) }
composable<PermittedInputMethods> { PermittedInputMethodsScreen(::navigateUp) }
composable<EnableSystemApp> { EnableSystemAppScreen(::navigateUp) }
composable<SetDefaultDialer> { SetDefaultDialerScreen(::navigateUp) }
composable<UserRestriction> {
LaunchedEffect(Unit) {
@@ -493,7 +564,9 @@ private fun HomeScreen(onNavigate: (Any) -> Unit) {
) {
HomePageItem(R.string.work_profile, R.drawable.work_fill0) { onNavigate(WorkProfile) }
}
if(deviceOwner || profileOwner) HomePageItem(R.string.applications, R.drawable.apps_fill0) { onNavigate(Applications) }
if(deviceOwner || profileOwner) HomePageItem(R.string.applications, R.drawable.apps_fill0) {
onNavigate(if(SharedPrefs(context).applicationsListView) ApplicationsList(true) else ApplicationsFeatures)
}
if(VERSION.SDK_INT >= 24 && (profileOwner || deviceOwner)) {
HomePageItem(R.string.user_restriction, R.drawable.person_off) { onNavigate(UserRestriction) }
}

View File

@@ -1,5 +1,6 @@
package com.bintianqi.owndroid
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
@@ -27,6 +28,7 @@ import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.List
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@@ -41,8 +43,10 @@ import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
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.Modifier
@@ -56,77 +60,64 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import com.bintianqi.owndroid.ui.theme.OwnDroidTheme
import com.google.accompanist.drawablepainter.rememberDrawablePainter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable
class PackageChooserActivity: ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val vm by viewModels<MyViewModel>()
if(getPackagesProgress.value < 1F) getPackages()
setContent {
val theme by vm.theme.collectAsStateWithLifecycle()
OwnDroidTheme(theme) {
val packages by installedPackages.collectAsStateWithLifecycle()
val progress by getPackagesProgress.collectAsStateWithLifecycle()
PackageChooserScreen(packages, progress, ::getPackages) {
AppChooserScreen(ApplicationsList(false), {
setResult(0, Intent().putExtra("package", it))
finish()
}
}, {})
}
}
}
val flags = if(Build.VERSION.SDK_INT >= 24) PackageManager.MATCH_DISABLED_COMPONENTS or PackageManager.MATCH_UNINSTALLED_PACKAGES else 0
fun getPackages() {
installedPackages.value = emptyList()
lifecycleScope.launch(Dispatchers.IO) {
val pm = packageManager
val apps = pm.getInstalledApplications(flags)
for(pkg in apps) {
installedPackages.update {
it + PackageInfo(
pkg.packageName, pkg.loadLabel(pm).toString(), pkg.loadIcon(pm),
(pkg.flags and ApplicationInfo.FLAG_SYSTEM) != 0
)
}
withContext(Dispatchers.Main) { getPackagesProgress.value = installedPackages.value.size.toFloat() / apps.size }
}
}
}
companion object {
val installedPackages = MutableStateFlow(emptyList<PackageInfo>())
val getPackagesProgress = MutableStateFlow(0F)
}
}
data class PackageInfo(
val installedApps = MutableStateFlow(emptyList<AppInfo>())
data class AppInfo(
val name: String,
val label: String,
val icon: Drawable,
val system: Boolean
val flags: Int
)
private fun searchInString(query: String, content: String)
= query.split(' ').all { content.contains(it, true) }
@Serializable data class ApplicationsList(val canSwitchView: Boolean)
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@Composable
private fun PackageChooserScreen(
packages: List<PackageInfo>, progress: Float, onRefresh: () -> Unit, onChoosePackage: (String?) -> Unit
) {
fun AppChooserScreen(params: ApplicationsList, onChoosePackage: (String?) -> Unit, onSwitchView: () -> Unit) {
val packages by installedApps.collectAsStateWithLifecycle()
val coroutine = rememberCoroutineScope()
val context = LocalContext.current
var progress by remember { mutableFloatStateOf(1F) }
var system by remember { mutableStateOf(false) }
var search by remember { mutableStateOf("") }
var query by remember { mutableStateOf("") }
var searchMode by remember { mutableStateOf(false) }
val filteredPackages = packages.filter {
system == it.system &&
(if(search.isEmpty()) true
else it.name.contains(search, ignoreCase = true) || it.label.contains(search, ignoreCase = true))
system == (it.flags and ApplicationInfo.FLAG_SYSTEM != 0) &&
(query.isEmpty() || (searchInString(query, it.label) || searchInString(query, it.name)))
}
val focusMgr = LocalFocusManager.current
LaunchedEffect(Unit) {
if(packages.size <= 1) getInstalledApps(coroutine, context) { progress = it }
}
Scaffold(
topBar = {
TopAppBar(
@@ -141,9 +132,15 @@ private fun PackageChooserScreen(
}) {
Icon(painter = painterResource(R.drawable.filter_alt_fill0), contentDescription = null)
}
IconButton(onRefresh) {
IconButton(
{ getInstalledApps(coroutine, context) { progress = it } },
enabled = progress == 1F
) {
Icon(painter = painterResource(R.drawable.refresh_fill0), contentDescription = null)
}
if(params.canSwitchView) IconButton(onSwitchView) {
Icon(Icons.AutoMirrored.Default.List, null)
}
}
},
title = {
@@ -151,8 +148,8 @@ private fun PackageChooserScreen(
val fr = FocusRequester()
LaunchedEffect(Unit) { fr.requestFocus() }
OutlinedTextField(
value = search,
onValueChange = { search = it },
value = query,
onValueChange = { query = it },
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
keyboardActions = KeyboardActions { focusMgr.clearFocus() },
placeholder = { Text(stringResource(R.string.search)) },
@@ -162,7 +159,7 @@ private fun PackageChooserScreen(
contentDescription = null,
modifier = Modifier.clickable {
focusMgr.clearFocus()
search = ""
query = ""
searchMode = false
}
)
@@ -170,8 +167,6 @@ private fun PackageChooserScreen(
textStyle = typography.bodyLarge,
modifier = Modifier.fillMaxWidth().focusRequester(fr)
)
} else {
Text(stringResource(R.string.package_chooser))
}
},
navigationIcon = {
@@ -182,11 +177,8 @@ private fun PackageChooserScreen(
colors = TopAppBarDefaults.topAppBarColors(MaterialTheme.colorScheme.surfaceContainer)
)
}
) { paddingValues->
LazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize().padding(top = paddingValues.calculateTopPadding())
) {
) { paddingValues ->
LazyColumn(Modifier.fillMaxSize().padding(paddingValues)) {
stickyHeader {
AnimatedVisibility(progress < 1F) {
LinearProgressIndicator(progress = { progress }, modifier = Modifier.fillMaxWidth())
@@ -215,3 +207,24 @@ private fun PackageChooserScreen(
}
}
}
fun getInstalledApps(scope: CoroutineScope, context: Context, onProgressUpdated: (Float) -> Unit) {
installedApps.value = emptyList()
scope.launch(Dispatchers.IO) {
val pm = context.packageManager
val apps = pm.getInstalledApplications(getInstalledAppsFlags)
for(pkg in apps) {
val label = pkg.loadLabel(pm).toString()
val icon = pkg.loadIcon(pm)
withContext(Dispatchers.Main) {
installedApps.update {
it + AppInfo(pkg.packageName, label, icon, pkg.flags)
}
onProgressUpdated(installedApps.value.size.toFloat() / apps.size)
}
}
}
}
val getInstalledAppsFlags =
if(Build.VERSION.SDK_INT >= 24) PackageManager.MATCH_DISABLED_COMPONENTS or PackageManager.MATCH_UNINSTALLED_PACKAGES else 0

View File

@@ -20,6 +20,7 @@ class SharedPrefs(context: Context) {
var blackTheme by BooleanSharedPref("theme.black")
var lockPassword by StringSharedPref("lock.password")
var biometricsUnlock by BooleanSharedPref("lock.biometrics")
var applicationsListView by BooleanSharedPref("applications.list_view")
}
private class BooleanSharedPref(val key: String, val defValue: Boolean = false): ReadWriteProperty<SharedPrefs, Boolean> {

File diff suppressed because it is too large Load Diff

View File

@@ -602,9 +602,17 @@ fun AddDelegatedAdminScreen(data: AddDelegatedAdmin, onNavigateUp: () -> Unit) {
readOnly = updateMode,
modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp, horizontal = HorizontalPadding)
)
DelegatedScope.entries.filter { VERSION.SDK_INT >= it.requiresApi }.forEach {scope ->
FullWidthCheckBoxItem(scope.string, scope in scopes) {
if(it) scopes += scope else scopes -= scope
DelegatedScope.entries.filter { VERSION.SDK_INT >= it.requiresApi }.forEach { scope ->
val checked = scope in scopes
Row(
Modifier.fillMaxWidth().clickable { if(!checked) scopes += scope else scopes -= scope }.padding(vertical = 4.dp),
verticalAlignment = Alignment.CenterVertically
) {
Checkbox(checked, { if(it) scopes += scope else scopes -= scope }, modifier = Modifier.padding(horizontal = 4.dp))
Column {
Text(stringResource(scope.string))
Text(scope.id, style = typography.bodyMedium, color = colorScheme.onSurfaceVariant)
}
}
}
Button(

View File

@@ -9,6 +9,8 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.selection.SelectionContainer
@@ -319,6 +321,28 @@ fun MyScaffold(
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MyLazyScaffold(
@StringRes title: Int,
onNavIconClicked: () -> Unit,
content: LazyListScope.() -> Unit
) {
val sb = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
Scaffold(
Modifier.nestedScroll(sb.nestedScrollConnection),
topBar = {
LargeTopAppBar(
{ Text(stringResource(title)) },
navigationIcon = { NavIcon(onNavIconClicked) },
scrollBehavior = sb
)
}
) { paddingValues ->
LazyColumn(Modifier.fillMaxSize().padding(paddingValues), content = content)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MySmallTitleScaffold(

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:pathData="M480,880q-139,-35 -229.5,-159.5T160,444v-244l320,-120 320,120v244q0,152 -90.5,276.5T480,880ZM480,796q104,-33 172,-132t68,-220v-189l-240,-90 -240,90v189q0,121 68,220t172,132ZM480,480Z"
android:fillColor="#000000"/>
</vector>

View File

@@ -377,39 +377,27 @@
<string name="enable_lockdown">Включить блокировку</string>
<string name="clear_current_config">Очистить текущую конфигурацию</string>
<string name="permissions">Разрешение</string>
<string name="scope_is_work_profile">Область действия: рабочий профиль</string>
<string name="app_info">Информация о приложении</string>
<string name="not_installed">Не установлено</string>
<string name="block_uninstall">Блокировать удаление</string>
<string name="enable_system_app">Включить системное приложение</string>
<string name="enable_system_app_desc">Повторно включить системное приложение, отключенное по умолчанию</string>
<!--ucd: управление пользователем отключено-->
<string name="ucd">Отключить управление пользователем</string>
<string name="ucd_desc">Если вы установите этот флажок, вы не сможете очистить хранилище этих приложений или принудительно остановить их.</string>
<string name="app_list_is">Список приложений:</string>
<string name="disable_user_control">Отключить управление пользователем</string>
<string name="disable_metered_data">Disable metered data</string> <!--TODO-->
<string name="cross_profile_package">Кросс-профильный пакет</string>
<string name="cross_profile_apps">Cross profile apps</string> <!--TODO-->
<string name="cross_profile_widget">Кросс-профильный виджет</string>
<string name="credential_manager_policy">Credential manager policy</string> <!--TODO-->
<string name="whitelist_and_system_app">Белый список и системные приложения</string>
<string name="permitted_packages_is">Разрешенные пакеты: \n</string>
<string name="permitted_accessibility_services">Разрешенные службы доступности</string>
<string name="only_system_accessibility_allowed">Разрешены только системные службы доступности</string>
<string name="system_accessibility_always_allowed">Системные службы доступности всегда разрешены.</string>
<string name="only_system_ime_allowed">Разрешены только системные методы ввода</string>
<string name="system_ime_always_allowed">Системные методы ввода всегда разрешены.</string>
<string name="permitted_ime">Разрешенный метод ввода</string>
<string name="keep_uninstalled_packages">Сохранять удаленные пакеты</string>
<string name="clear_data">Очистить данные</string>
<string name="clear_app_storage">Очистить хранилище приложения</string>
<string name="app_storage_will_be_cleared">Хранилище этого приложения будет очищено</string>
<string name="set_default_dialer">Установить приложение для звонков по умолчанию</string>
<string name="app_will_be_default_dialer">Это приложение будет установлено в качестве приложения для звонков по умолчанию.</string>
<string name="uninstall_app">Удалить приложение</string>
<string name="install_app">Установить приложение</string>
<!--TODO: 2 strings-->
<string name="choose_apk_file">Choose an APK file</string>
<string name="install_existing_app">Install existing app</string>
<string name="install_existing_app">Install existing app</string> <!--TODO-->
<string name="keep_after_uninstall">Keep after uninstall</string> <!--TODO-->
<string name="search">Поиск</string>
<!--Ограничения пользователя-->
@@ -699,6 +687,7 @@
<string name="info_disable_user_control">Пользователь не сможет очищать данные приложений или принудительно останавливать пакеты.</string>
<string name="info_keep_uninstalled_apps">Установить список приложений, которые нужно сохранить в виде APK-файлов, даже если ни у одного пользователя в данный момент они не установлены.</string>
<!--TODO--><string name="info_install_existing_app">Install an existing package that has been installed in another user, or has been kept after uninstall.</string>
<!--TODO--><string name="info_enable_system_app">Re-enable a system app that was disabled by default when the user was initialized.</string>
<string name="info_headless_system_user_mode">Режим "безголового" системного пользователя означает, что системный пользователь запускает системные службы и некоторый системный интерфейс, но он не связан с каким-либо реальным человеком, и для связи с реальными людьми должны быть созданы дополнительные пользователи.</string>
<string name="info_logout">If the current user is not switched by OwnDroid, this function cannot be used.</string> <!--TODO-->
<string name="info_affiliation_id">Когда владелец устройства создает управляемого пользователя, управляемый пользователь не является аффилированным. Чтобы сделать управляемого пользователя аффилированным с владельцем устройства, вам следует установить одинаковые аффилированные идентификаторы в основном и управляемом пользователях.</string>

View File

@@ -385,38 +385,27 @@
<string name="enable_lockdown">Kilitlemeyi Etkinleştir</string>
<string name="clear_current_config">Mevcut Yapılandırmayı Temizle</string>
<string name="permissions">İzinler</string>
<string name="scope_is_work_profile">Kapsam: İş Profili</string>
<string name="app_info">Uygulama Bilgisi</string>
<string name="not_installed">Yüklenmedi</string>
<string name="block_uninstall">Kaldırmayı Engelle</string>
<string name="enable_system_app">Sistem Uygulamasını Etkinleştir</string>
<string name="enable_system_app_desc">Varsayılan olarak devre dışı bırakılmış bir sistem uygulamasını yeniden etkinleştir</string>
<!--ucd: user control disabled-->
<string name="ucd">Kullanıcı Kontrolünü Devre Dışı Bırak</string>
<string name="ucd_desc">Bunu ayarlarsanız, bu uygulamaların depolamasını temizleyemez veya zorla durduramazsınız.</string>
<string name="app_list_is">Uygulama listesi:</string>
<string name="disable_user_control">Kullanıcı Kontrolünü Devre Dışı Bırak</string>
<string name="disable_metered_data">Disable metered data</string> <!--TODO-->
<string name="cross_profile_package">Çapraz Profil Paketi</string>
<string name="cross_profile_apps">Cross profile apps</string> <!--TODO-->
<string name="cross_profile_widget">Çapraz Profil Widget\'ı</string>
<string name="credential_manager_policy">Credential manager policy</string> <!--TODO-->
<string name="whitelist_and_system_app">Beyaz Liste ve Sistem Uygulaması</string>
<string name="permitted_packages_is">İzin Verilen Paketler: \n</string>
<string name="permitted_accessibility_services">İzin Verilen Erişilebilirlik Servisleri</string>
<string name="only_system_accessibility_allowed">Yalnızca sistem erişilebilirlik servislerine izin verilir</string>
<string name="system_accessibility_always_allowed">Sistem erişilebilirlik servisleri her zaman izinlidir.</string>
<string name="only_system_ime_allowed">Yalnızca sistem giriş yöntemlerine izin verilir</string>
<string name="system_ime_always_allowed">Sistem giriş yöntemleri her zaman izinlidir.</string>
<string name="permitted_ime">İzin Verilen IME</string>
<string name="keep_uninstalled_packages">Kaldırılmış Paketleri Koru</string>
<string name="clear_data">Verileri Temizle</string>
<string name="clear_app_storage">Uygulama Depolamasını Temizle</string>
<string name="app_storage_will_be_cleared">Bu uygulamanın depolaması temizlenecek</string>
<string name="set_default_dialer">Varsayılan Arama Uygulamasını Ayarla</string>
<string name="app_will_be_default_dialer">Bu uygulama varsayılan arama uygulaması olarak ayarlanacak.</string>
<string name="uninstall_app">Uygulamayı Kaldır</string>
<string name="install_app">Uygulama Yükle</string>
<string name="choose_apk_file">Bir APK Dosyası Seç</string>
<string name="install_existing_app">Mevcut Uygulamayı Yükle</string>
<string name="keep_after_uninstall">Keep after uninstall</string> <!--TODO-->
<string name="search">Ara</string>
<!--UserRestriction-->
@@ -702,6 +691,7 @@
<string name="info_disable_user_control">Kullanıcı uygulama verilerini temizleyemez veya paketleri zorla durduramaz.</string>
<string name="info_keep_uninstalled_apps">Hiçbir kullanıcının şu anda yüklemediği uygulamaları APK olarak saklanacak bir liste ayarlar.</string>
<string name="info_install_existing_app">Başka bir kullanıcıda yüklenmiş veya kaldırıldıktan sonra saklanmış mevcut bir paketi yükler.</string>
<!--TODO--><string name="info_enable_system_app">Re-enable a system app that was disabled by default when the user was initialized.</string>
<string name="info_headless_system_user_mode">Başıboş sistem kullanıcı modu, sistem kullanıcısının sistem servislerini ve bazı sistem kullanıcı arayüzlerini çalıştırdığı, ancak herhangi bir gerçek kişiyle ilişkilendirilmediği ve gerçek kişilerle ilişkilendirilecek ek kullanıcıların oluşturulması gerektiği anlamına gelir.</string>
<string name="info_logout">Mevcut kullanıcı OwnDroid tarafından değiştirilmediyse bu işlev kullanılamaz.</string>
<string name="info_affiliation_id">Cihaz Sahibi bir yönetilen kullanıcı oluşturduğunda, yönetilen kullanıcı bağlı değildir. Yönetilen kullanıcının Cihaz Sahibi ile bağlı hale getirilmesi için ana kullanıcı ve yönetilen kullanıcıda aynı bağlılık kimlikleri ayarlanmalıdır.</string>

View File

@@ -368,37 +368,26 @@
<string name="enable_lockdown">启用锁定</string>
<string name="clear_current_config">清除当前配置</string>
<string name="permissions">权限</string>
<string name="scope_is_work_profile">作用域: 工作资料</string>
<string name="app_info">应用详情</string>
<string name="not_installed">未安装</string>
<string name="block_uninstall">阻止卸载</string>
<string name="ucd">禁止用户控制</string>
<string name="ucd_desc">用户将无法清除这些应用的存储空间或强制停止这些应用</string>
<string name="app_list_is">应用列表:</string>
<string name="disable_user_control">禁止用户控制</string>
<string name="disable_metered_data">禁用计量数据</string>
<string name="cross_profile_package">跨资料应用</string>
<string name="cross_profile_apps">跨资料应用</string>
<string name="cross_profile_widget">跨资料微件</string>
<string name="credential_manager_policy">凭据管理器策略</string>
<string name="whitelist_and_system_app">白名单和系统应用</string>
<string name="permitted_packages_is">许可的应用:\n</string>
<string name="permitted_accessibility_services">许可的无障碍服务</string>
<string name="only_system_accessibility_allowed">只允许系统无障碍服务</string>
<string name="system_accessibility_always_allowed">系统的无障碍服务不受影响</string>
<string name="only_system_ime_allowed">只允许系统输入法</string>
<string name="system_ime_always_allowed">系统输入法不受影响</string>
<string name="permitted_ime">许可的输入法</string>
<string name="keep_uninstalled_packages">卸载后保留的应用</string>
<string name="clear_data">数据清除</string>
<string name="clear_app_storage">清除应用存储</string>
<string name="app_storage_will_be_cleared">这个应用的存储空间将被清空</string>
<string name="set_default_dialer">设为默认拨号应用</string>
<string name="app_will_be_default_dialer">这个应用将被设为默认拨号应用</string>
<string name="set_default_dialer">设置默认拨号器</string>
<string name="uninstall_app">卸载应用</string>
<string name="install_app">安装应用</string>
<string name="choose_apk_file">选择一个APK文件</string>
<string name="install_existing_app">安装已存在的应用</string>
<string name="enable_system_app">启用系统应用</string>
<string name="enable_system_app_desc">重新启用一个默认被禁用的系统应用</string>
<string name="keep_after_uninstall">卸载后保留</string>
<string name="search">搜索</string>
<!--UserRestriction-->
@@ -698,6 +687,7 @@
<string name="info_disable_user_control">用户无法清除这些应用的存储空间,也无法强制停止应用</string>
<string name="info_keep_uninstalled_apps">这个列表中的应用的APK将会一直保留即使没有任何用户安装这个应用</string>
<string name="info_install_existing_app">安装一个已经在其他用户中安装或在卸载后保留的app。</string>
<string name="info_enable_system_app">重新启用一个在用户初始化时默认被禁用的系统app</string>
<string name="info_headless_system_user_mode">无头系统用户模式意味着系统用户运行系统服务和一些系统UI但它不与任何真实的人相关联必须创建额外的用户才能与真实的人相关联。</string>
<string name="info_logout">如果当前用户不是由OwnDroid切换的无法使用此功能。</string>
<string name="info_affiliation_id">当Device owner创建并管理用户时新的用户不是附属用户。Device owner设置和受管理用户完全相同的附属用户ID后受管理用户成为附属于Device owner的用户</string>

View File

@@ -404,38 +404,26 @@
<string name="enable_lockdown">Enable lockdown</string>
<string name="clear_current_config">Clear current config</string>
<string name="permissions">Permissions</string>
<string name="scope_is_work_profile">Scope: work profile</string>
<string name="app_info">App info</string>
<string name="not_installed">Not installed</string>
<string name="block_uninstall">Block uninstall</string>
<string name="enable_system_app">Enable system app</string>
<string name="enable_system_app_desc">Re-enable a system app that was disabled by default</string>
<!--ucd: user control disabled-->
<string name="ucd">Disable user control</string>
<string name="ucd_desc">If you set this, you cannot clear these apps\' storage or force stop them. </string>
<string name="app_list_is">App list:</string>
<string name="disable_user_control">Disable user control</string>
<string name="disable_metered_data">Disable metered data</string>
<string name="cross_profile_package">Cross profile package</string>
<string name="cross_profile_apps">Cross profile apps</string>
<string name="cross_profile_widget">Cross profile widget</string>
<string name="credential_manager_policy">Credential manager policy</string>
<string name="whitelist_and_system_app">Whitelist and system app</string>
<string name="permitted_packages_is">Permitted packages: \n</string>
<string name="permitted_accessibility_services">Permitted accessibility services</string>
<string name="only_system_accessibility_allowed">Only system accessibility services are allowed</string>
<string name="system_accessibility_always_allowed">System accessibility services are always allowed.</string>
<string name="only_system_ime_allowed">Only system input methods are allowed</string>
<string name="system_ime_always_allowed">System input methods are always allowed.</string>
<string name="permitted_ime">Permitted IME</string>
<string name="keep_uninstalled_packages">Keep uninstalled packages</string>
<string name="clear_data">Clear data</string>
<string name="clear_app_storage">Clear app storage</string>
<string name="app_storage_will_be_cleared">This app\'s storage will be cleared</string>
<string name="set_default_dialer">Set default dialer</string>
<string name="app_will_be_default_dialer">This app will be set as the default dialer application.</string>
<string name="uninstall_app">Uninstall app</string>
<string name="install_app">Install app</string>
<string name="choose_apk_file">Choose an APK file</string>
<string name="install_existing_app">Install existing app</string>
<string name="keep_after_uninstall">Keep after uninstall</string>
<string name="search">Search</string>
<!--UserRestriction-->
@@ -738,6 +726,7 @@
<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_install_existing_app">Install an existing package that has been installed in another user, or has been kept after uninstall.</string>
<string name="info_enable_system_app">Re-enable a system app that was disabled by default when the user was initialized.</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_logout">If the current user is not switched by OwnDroid, this function cannot be used.</string>
<string name="info_affiliation_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>