mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
Export logs in settings
Set Preferential network config in a new screen Hide Password entry from home if OwnDroid is not activated, fix #105
This commit is contained in:
@@ -146,12 +146,12 @@ private fun AppInstaller(
|
||||
var tab by remember { mutableIntStateOf(0) }
|
||||
val pagerState = rememberPagerState { 2 }
|
||||
val scrollState = rememberScrollState()
|
||||
tab = pagerState.targetPage
|
||||
Column(modifier = Modifier.padding(paddingValues)) {
|
||||
TabRow(tab) {
|
||||
Tab(
|
||||
tab == 0,
|
||||
onClick = {
|
||||
tab = 0
|
||||
coroutine.launch { scrollState.animateScrollTo(0) }
|
||||
coroutine.launch { pagerState.animateScrollToPage(0) }
|
||||
},
|
||||
@@ -160,7 +160,6 @@ private fun AppInstaller(
|
||||
Tab(
|
||||
tab == 1,
|
||||
onClick = {
|
||||
tab = 1
|
||||
coroutine.launch { scrollState.animateScrollTo(0) }
|
||||
coroutine.launch { pagerState.animateScrollToPage(1) }
|
||||
},
|
||||
|
||||
@@ -66,6 +66,8 @@ import com.bintianqi.owndroid.dpm.AddDelegatedAdmin
|
||||
import com.bintianqi.owndroid.dpm.AddDelegatedAdminScreen
|
||||
import com.bintianqi.owndroid.dpm.AddNetwork
|
||||
import com.bintianqi.owndroid.dpm.AddNetworkScreen
|
||||
import com.bintianqi.owndroid.dpm.AddPreferentialNetworkServiceConfig
|
||||
import com.bintianqi.owndroid.dpm.AddPreferentialNetworkServiceConfigScreen
|
||||
import com.bintianqi.owndroid.dpm.AffiliationId
|
||||
import com.bintianqi.owndroid.dpm.AffiliationIdScreen
|
||||
import com.bintianqi.owndroid.dpm.AlwaysOnVpnPackage
|
||||
@@ -340,7 +342,8 @@ fun Home(activity: FragmentActivity, vm: MyViewModel) {
|
||||
composable<RecommendedGlobalProxy> { RecommendedGlobalProxyScreen(::navigateUp) }
|
||||
composable<NetworkLogging> { NetworkLoggingScreen(::navigateUp) }
|
||||
composable<WifiAuthKeypair> { WifiAuthKeypairScreen(::navigateUp) }
|
||||
composable<PreferentialNetworkService> { PreferentialNetworkServiceScreen(::navigateUp) }
|
||||
composable<PreferentialNetworkService> { PreferentialNetworkServiceScreen(::navigateUp, ::navigate) }
|
||||
composable<AddPreferentialNetworkServiceConfig> { AddPreferentialNetworkServiceConfigScreen(it.toRoute(), ::navigateUp) }
|
||||
composable<OverrideApn> { OverrideApnScreen(::navigateUp) }
|
||||
|
||||
composable<WorkProfile> { WorkProfileScreen(::navigateUp, ::navigate) }
|
||||
@@ -507,7 +510,7 @@ private fun HomeScreen(onNavigate: (Any) -> Unit) {
|
||||
HomePageItem(R.string.user_restriction, R.drawable.person_off) { onNavigate(UserRestriction) }
|
||||
}
|
||||
HomePageItem(R.string.users,R.drawable.manage_accounts_fill0) { onNavigate(Users) }
|
||||
HomePageItem(R.string.password_and_keyguard, R.drawable.password_fill0) { onNavigate(Password) }
|
||||
if(deviceOwner || profileOwner) HomePageItem(R.string.password_and_keyguard, R.drawable.password_fill0) { onNavigate(Password) }
|
||||
HomePageItem(R.string.settings, R.drawable.settings_fill0) { onNavigate(Settings) }
|
||||
Spacer(Modifier.padding(vertical = 20.dp))
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build.VERSION
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.biometric.BiometricManager
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
@@ -38,16 +40,27 @@ import com.bintianqi.owndroid.ui.MyScaffold
|
||||
import com.bintianqi.owndroid.ui.SwitchItem
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.security.SecureRandom
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
@Serializable object Settings
|
||||
|
||||
@Composable
|
||||
fun SettingsScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val exportLogsLauncher = rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument("text/plain")) {
|
||||
if(it != null) exportLogs(context, it)
|
||||
}
|
||||
MyScaffold(R.string.settings, 0.dp, onNavigateUp) {
|
||||
FunctionItem(title = R.string.options, icon = R.drawable.tune_fill0) { onNavigate(SettingsOptions) }
|
||||
FunctionItem(title = R.string.appearance, icon = R.drawable.format_paint_fill0) { onNavigate(Appearance) }
|
||||
FunctionItem(title = R.string.security, icon = R.drawable.lock_fill0) { onNavigate(AuthSettings) }
|
||||
FunctionItem(title = R.string.api, icon = R.drawable.apps_fill0) { onNavigate(ApiSettings) }
|
||||
FunctionItem(title = R.string.export_logs, icon = R.drawable.description_fill0) {
|
||||
val time = SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).format(Date(System.currentTimeMillis()))
|
||||
exportLogsLauncher.launch("owndroid_log_$time")
|
||||
}
|
||||
FunctionItem(title = R.string.about, icon = R.drawable.info_fill0) { onNavigate(About) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@ import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Process
|
||||
import android.widget.Toast
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.result.contract.ActivityResultContract
|
||||
@@ -28,6 +30,7 @@ import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
var zhCN = true
|
||||
@@ -122,3 +125,13 @@ class ChoosePackageContract: ActivityResultContract<Nothing?, String?>() {
|
||||
override fun parseResult(resultCode: Int, intent: Intent?): String? =
|
||||
intent?.getStringExtra("package")
|
||||
}
|
||||
|
||||
fun exportLogs(context: Context, uri: Uri) {
|
||||
context.contentResolver.openOutputStream(uri)?.use { output ->
|
||||
val proc = Runtime.getRuntime().exec("logcat -d")
|
||||
proc.inputStream.copyTo(output)
|
||||
if(Build.VERSION.SDK_INT >= 26) proc.waitFor(2L, TimeUnit.SECONDS)
|
||||
else proc.waitFor()
|
||||
context.showOperationResultToast(proc.exitValue() == 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,6 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowLeft
|
||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material.icons.filled.Edit
|
||||
import androidx.compose.material.icons.outlined.Delete
|
||||
import androidx.compose.material.icons.outlined.LocationOn
|
||||
@@ -99,6 +98,9 @@ import androidx.compose.material3.MaterialTheme.typography
|
||||
import androidx.compose.material3.MenuAnchorType
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.SegmentedButton
|
||||
import androidx.compose.material3.SegmentedButtonDefaults
|
||||
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Tab
|
||||
import androidx.compose.material3.TabRow
|
||||
@@ -156,7 +158,6 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.net.InetAddress
|
||||
import kotlin.math.max
|
||||
import kotlin.reflect.jvm.jvmErasure
|
||||
|
||||
@Serializable object Network
|
||||
@@ -1714,122 +1715,95 @@ fun WifiAuthKeypairScreen(onNavigateUp: () -> Unit) {
|
||||
|
||||
@RequiresApi(33)
|
||||
@Composable
|
||||
fun PreferentialNetworkServiceScreen(onNavigateUp: () -> Unit) {
|
||||
val focusMgr = LocalFocusManager.current
|
||||
fun PreferentialNetworkServiceScreen(onNavigateUp: () -> Unit, onNavigate: (AddPreferentialNetworkServiceConfig) -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
var masterEnabled by remember { mutableStateOf(false) }
|
||||
val configs = remember { mutableStateListOf<PreferentialNetworkServiceConfig>() }
|
||||
var index by remember { mutableIntStateOf(-1) }
|
||||
var enabled by remember { mutableStateOf(false) }
|
||||
var networkId by remember { mutableStateOf("") }
|
||||
var allowFallback by remember { mutableStateOf(false) }
|
||||
var blockNonMatching by remember { mutableStateOf(false) }
|
||||
var excludedUids by remember { mutableStateOf("") }
|
||||
var includedUids by remember { mutableStateOf("") }
|
||||
fun refresh() {
|
||||
val config = configs.getOrNull(index)
|
||||
enabled = config?.isEnabled == true
|
||||
networkId = config?.networkId?.toString() ?: ""
|
||||
allowFallback = config?.isFallbackToDefaultConnectionAllowed == true
|
||||
if(VERSION.SDK_INT >= 34) blockNonMatching = config?.shouldBlockNonMatchingNetworks() == true
|
||||
includedUids = config?.includedUids?.joinToString("\n") ?: ""
|
||||
excludedUids = config?.excludedUids?.joinToString("\n") ?: ""
|
||||
}
|
||||
fun saveCurrentConfig() {
|
||||
val builder = PreferentialNetworkServiceConfig.Builder()
|
||||
builder.setEnabled(enabled)
|
||||
builder.setNetworkId(networkId.toInt())
|
||||
builder.setFallbackToDefaultConnectionAllowed(allowFallback)
|
||||
if(VERSION.SDK_INT >= 34) builder.setShouldBlockNonMatchingNetworks(blockNonMatching)
|
||||
builder.setIncludedUids(includedUids.lines().dropWhile { it == "" }.map { it.toInt() }.toIntArray())
|
||||
builder.setExcludedUids(excludedUids.lines().dropWhile { it == "" }.map { it.toInt() }.toIntArray())
|
||||
if(index < configs.size) configs[index] = builder.build() else configs += builder.build()
|
||||
}
|
||||
fun initialize() {
|
||||
masterEnabled = dpm.isPreferentialNetworkServiceEnabled
|
||||
configs.clear()
|
||||
configs.addAll(dpm.preferentialNetworkServiceConfigs)
|
||||
index = max(0, configs.size - 1)
|
||||
refresh()
|
||||
}
|
||||
LaunchedEffect(Unit) { initialize() }
|
||||
MyScaffold(R.string.preferential_network_service, 8.dp, onNavigateUp) {
|
||||
SwitchItem(R.string.enabled, state = masterEnabled, onCheckedChange = { masterEnabled = it }, padding = false)
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceAround,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth().padding(top = 8.dp)
|
||||
) {
|
||||
IconButton(
|
||||
onClick = {
|
||||
try {
|
||||
saveCurrentConfig()
|
||||
index -= 1
|
||||
refresh()
|
||||
} catch(e: Exception) {
|
||||
e.printStackTrace()
|
||||
Toast.makeText(context, R.string.failed_to_save_current_config, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
},
|
||||
enabled = index > 0
|
||||
LaunchedEffect(Unit) { refresh() }
|
||||
MyScaffold(R.string.preferential_network_service, 0.dp, onNavigateUp, false) {
|
||||
SwitchItem(R.string.enabled, state = masterEnabled, onCheckedChange = {
|
||||
dpm.isPreferentialNetworkServiceEnabled = it
|
||||
refresh()
|
||||
})
|
||||
Spacer(Modifier.padding(vertical = 4.dp))
|
||||
configs.forEachIndexed { index, config ->
|
||||
Row(
|
||||
Modifier.fillMaxWidth().padding(start = 16.dp, end = 8.dp, top = 4.dp, bottom = 4.dp),
|
||||
Arrangement.SpaceBetween, Alignment.CenterVertically
|
||||
) {
|
||||
Icon(imageVector = Icons.AutoMirrored.Default.KeyboardArrowLeft, contentDescription = stringResource(R.string.previous))
|
||||
}
|
||||
Text("${index + 1} / ${configs.size}")
|
||||
IconButton(
|
||||
onClick = {
|
||||
try {
|
||||
saveCurrentConfig()
|
||||
index += 1
|
||||
refresh()
|
||||
} catch(e: Exception) {
|
||||
e.printStackTrace()
|
||||
Toast.makeText(context, R.string.failed_to_save_current_config, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
Column {
|
||||
Text(index.toString())
|
||||
}
|
||||
IconButton({
|
||||
onNavigate(AddPreferentialNetworkServiceConfig(
|
||||
enabled = config.isEnabled,
|
||||
id = config.networkId,
|
||||
allowFallback = config.isFallbackToDefaultConnectionAllowed,
|
||||
blockNonMatching = if(VERSION.SDK_INT >= 34) config.shouldBlockNonMatchingNetworks() else false,
|
||||
excludedUids = config.excludedUids.toList(),
|
||||
includedUids = config.includedUids.toList(),
|
||||
index = index
|
||||
))
|
||||
}) {
|
||||
Icon(Icons.Default.Edit, stringResource(R.string.edit))
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
imageVector = if(index + 1 >= configs.size) Icons.Default.Add else Icons.AutoMirrored.Default.KeyboardArrowRight,
|
||||
contentDescription = stringResource(R.string.previous)
|
||||
)
|
||||
}
|
||||
}
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
Modifier.fillMaxWidth()
|
||||
.padding(top = 4.dp)
|
||||
.clickable { onNavigate(AddPreferentialNetworkServiceConfig()) }
|
||||
.padding(horizontal = 8.dp, vertical = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
IconButton(
|
||||
onClick = {
|
||||
try {
|
||||
saveCurrentConfig()
|
||||
context.showOperationResultToast(true)
|
||||
} catch(e: Exception) {
|
||||
e.printStackTrace()
|
||||
Toast.makeText(context, R.string.failed_to_save_current_config, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
},
|
||||
modifier = Modifier.padding(end = 10.dp)
|
||||
) {
|
||||
Icon(painter = painterResource(R.drawable.save_fill0), contentDescription = stringResource(R.string.save_current_config))
|
||||
}
|
||||
IconButton(
|
||||
onClick = {
|
||||
if(index < configs.size) configs.removeAt(index)
|
||||
if(index > 0) index -= 1
|
||||
refresh()
|
||||
}
|
||||
) {
|
||||
Icon(imageVector = Icons.Default.Delete, contentDescription = stringResource(R.string.delete_current_config))
|
||||
}
|
||||
Icon(Icons.Default.Add, null, Modifier.padding(horizontal = 8.dp))
|
||||
Text(stringResource(R.string.add_config))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable data class AddPreferentialNetworkServiceConfig(
|
||||
val enabled: Boolean = true,
|
||||
val id: Int = -1,
|
||||
val allowFallback: Boolean = false,
|
||||
val blockNonMatching: Boolean = false,
|
||||
val excludedUids: List<Int> = emptyList(),
|
||||
val includedUids: List<Int> = emptyList(),
|
||||
val index: Int = -1
|
||||
)
|
||||
|
||||
@RequiresApi(33)
|
||||
@Composable
|
||||
fun AddPreferentialNetworkServiceConfigScreen(route: AddPreferentialNetworkServiceConfig,onNavigateUp: () -> Unit) {
|
||||
val updateMode = route.index != -1
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
var enabled by remember { mutableStateOf(route.enabled) }
|
||||
var id by remember { mutableIntStateOf(route.id) }
|
||||
var allowFallback by remember { mutableStateOf(route.allowFallback) }
|
||||
var blockNonMatching by remember { mutableStateOf(route.blockNonMatching) }
|
||||
var excludedUids by remember { mutableStateOf(route.excludedUids.joinToString("\n")) }
|
||||
var includedUids by remember { mutableStateOf(route.includedUids.joinToString("\n")) }
|
||||
MyScaffold(R.string.preferential_network_service, 8.dp, onNavigateUp, false) {
|
||||
SwitchItem(title = R.string.enabled, state = enabled, onCheckedChange = { enabled = it }, padding = false)
|
||||
OutlinedTextField(
|
||||
value = networkId, onValueChange = { networkId = it },
|
||||
label = { Text(stringResource(R.string.network_id)) },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
||||
keyboardActions = KeyboardActions { focusMgr.clearFocus() },
|
||||
modifier = Modifier.fillMaxWidth().padding(bottom = 6.dp)
|
||||
)
|
||||
AnimatedVisibility(enabled) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text("ID", Modifier.padding(end = 8.dp), style = typography.titleLarge)
|
||||
SingleChoiceSegmentedButtonRow(Modifier.fillMaxWidth()) {
|
||||
for(i in 1..5) {
|
||||
SegmentedButton(id == i, { id = i }, SegmentedButtonDefaults.itemShape(i - 1, 5)) {
|
||||
Text(i.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SwitchItem(
|
||||
title = R.string.allow_fallback_to_default_connection,
|
||||
state = allowFallback, onCheckedChange = { allowFallback = it }, padding = false
|
||||
@@ -1838,28 +1812,66 @@ fun PreferentialNetworkServiceScreen(onNavigateUp: () -> Unit) {
|
||||
title = R.string.block_non_matching_networks,
|
||||
state = blockNonMatching, onCheckedChange = { blockNonMatching = it }, padding = false
|
||||
)
|
||||
val includedUidsLegal = includedUids.lines().filter { it.isNotBlank() }.let {
|
||||
it.isEmpty() || (it.all { it.toIntOrNull() != null } && excludedUids.isBlank())
|
||||
}
|
||||
OutlinedTextField(
|
||||
value = includedUids, onValueChange = { includedUids = it }, minLines = 2,
|
||||
label = { Text(stringResource(R.string.included_uids)) },
|
||||
supportingText = { Text(stringResource(R.string.one_uid_per_line)) },
|
||||
isError = !includedUidsLegal,
|
||||
modifier = Modifier.fillMaxWidth().padding(bottom = 6.dp)
|
||||
)
|
||||
val excludedUidsLegal = excludedUids.lines().filter { it.isNotBlank() }.let {
|
||||
it.isEmpty() || (it.all { it.toIntOrNull() != null } && includedUids.isBlank())
|
||||
}
|
||||
OutlinedTextField(
|
||||
value = excludedUids, onValueChange = { excludedUids = it }, minLines = 2,
|
||||
label = { Text(stringResource(R.string.excluded_uids)) },
|
||||
supportingText = { Text(stringResource(R.string.one_uid_per_line)) },
|
||||
isError = !excludedUidsLegal,
|
||||
modifier = Modifier.fillMaxWidth().padding(bottom = 6.dp)
|
||||
)
|
||||
Button(
|
||||
onClick = {
|
||||
dpm.isPreferentialNetworkServiceEnabled = masterEnabled
|
||||
dpm.preferentialNetworkServiceConfigs = configs
|
||||
initialize()
|
||||
context.showOperationResultToast(true)
|
||||
try {
|
||||
val config = PreferentialNetworkServiceConfig.Builder().apply {
|
||||
setEnabled(enabled)
|
||||
if(enabled) setNetworkId(id.toInt())
|
||||
setFallbackToDefaultConnectionAllowed(allowFallback)
|
||||
setExcludedUids(excludedUids.lines().filter { it.isNotBlank() }.map { it.toInt() }.toIntArray())
|
||||
setIncludedUids(includedUids.lines().filter { it.isNotBlank() }.map { it.toInt() }.toIntArray())
|
||||
if(VERSION.SDK_INT >= 34) setShouldBlockNonMatchingNetworks(blockNonMatching)
|
||||
}.build()
|
||||
val configs = dpm.preferentialNetworkServiceConfigs
|
||||
if(updateMode) configs[route.index] = config
|
||||
else configs += config
|
||||
dpm.preferentialNetworkServiceConfigs = configs
|
||||
onNavigateUp()
|
||||
} catch(e: Exception) {
|
||||
context.showOperationResultToast(false)
|
||||
e.printStackTrace()
|
||||
}
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth().padding(top = 12.dp)
|
||||
enabled = includedUidsLegal && excludedUidsLegal,
|
||||
modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp)
|
||||
) {
|
||||
Text(stringResource(R.string.apply))
|
||||
Text(stringResource(if(updateMode) R.string.update else R.string.add))
|
||||
}
|
||||
if(updateMode) Button(
|
||||
onClick = {
|
||||
try {
|
||||
dpm.preferentialNetworkServiceConfigs = dpm.preferentialNetworkServiceConfigs.drop(route.index)
|
||||
onNavigateUp()
|
||||
} catch(e: Exception) {
|
||||
context.showOperationResultToast(false)
|
||||
e.printStackTrace()
|
||||
}
|
||||
},
|
||||
colors = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.error, MaterialTheme.colorScheme.onError),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(stringResource(R.string.delete))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="m313,520 l224,224 -57,56 -320,-320 320,-320 57,56 -224,224h487v80L313,520Z"/>
|
||||
</vector>
|
||||
@@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M222,760 L80,618l56,-56 85,85 170,-170 56,57 -225,226ZM222,440L80,298l56,-56 85,85 170,-170 56,57 -225,226ZM520,680v-80h360v80L520,680ZM520,360v-80h360v80L520,360Z"/>
|
||||
</vector>
|
||||
@@ -311,15 +311,13 @@
|
||||
<string name="export_logs">Экспортировать журналы</string>
|
||||
<string name="wifi_auth_keypair">Пара ключей Wi-Fi</string>
|
||||
<string name="preferential_network_service">Предпочтительная сетевая служба</string>
|
||||
<string name="add_config">Add config</string> <!--TODO-->
|
||||
<string name="network_id">Идентификатор сети</string>
|
||||
<string name="allow_fallback_to_default_connection">Разрешить переход на соединение по умолчанию</string>
|
||||
<string name="block_non_matching_networks">Блокировать несоответствующие сети</string>
|
||||
<string name="included_uids">Включенные UID</string>
|
||||
<string name="excluded_uids">Исключенные UID</string>
|
||||
<string name="one_uid_per_line">Один UID на строку</string>
|
||||
<string name="failed_to_save_current_config">Не удалось сохранить текущую конфигурацию</string>
|
||||
<string name="save_current_config">Сохранить текущую конфигурацию</string>
|
||||
<string name="delete_current_config">Удалить текущую конфигурацию</string>
|
||||
<string name="override_apn_settings">Настройки APN</string>
|
||||
<string name="total_apn_amount">Количество настроек APN: %1$s</string>
|
||||
<string name="select_a_apn_or_create">Выберите настройку APN для редактирования (1~%1$s) или введите 0, чтобы создать новую настройку APN.</string>
|
||||
|
||||
@@ -318,15 +318,13 @@
|
||||
<string name="export_logs">Export logs</string> <!--TODO-->
|
||||
<string name="wifi_auth_keypair">Wi-Fi anahtar çifti</string>
|
||||
<string name="preferential_network_service">Tercihli ağ hizmeti</string>
|
||||
<string name="add_config">Add config</string> <!--TODO-->
|
||||
<string name="network_id">Network ID</string> <!--TODO-->
|
||||
<string name="allow_fallback_to_default_connection">Allow fallback to default connection</string> <!--TODO-->
|
||||
<string name="block_non_matching_networks">Block non matching networks</string> <!--TODO-->
|
||||
<string name="included_uids">Included UIDs</string> <!--TODO-->
|
||||
<string name="excluded_uids">Excluded UIDs</string> <!--TODO-->
|
||||
<string name="one_uid_per_line">One UID per line</string> <!--TODO-->
|
||||
<string name="failed_to_save_current_config">Failed to save current config</string> <!--TODO-->
|
||||
<string name="save_current_config">Save current config</string> <!--TODO-->
|
||||
<string name="delete_current_config">Delete current config</string> <!--TODO-->
|
||||
<string name="override_apn_settings">APN ayarlarını geçersiz kıl</string>
|
||||
<string name="total_apn_amount">APN ayarlarının toplamı: %1$s</string>
|
||||
<string name="select_a_apn_or_create">Düzenlemek istediğiniz APN ayarını seçin (1~%1$s) veya yeni bir APN ayarı oluşturmak için 0 girin.</string>
|
||||
|
||||
@@ -306,15 +306,13 @@
|
||||
<string name="export_logs">导出日志</string>
|
||||
<string name="wifi_auth_keypair">Wi-Fi密钥对</string>
|
||||
<string name="preferential_network_service">首选网络服务</string>
|
||||
<string name="add_config">添加配置</string>
|
||||
<string name="network_id">网络ID</string>
|
||||
<string name="allow_fallback_to_default_connection">允许回落到默认连接</string>
|
||||
<string name="block_non_matching_networks">阻止不匹配的网络</string>
|
||||
<string name="included_uids">包含的UID</string>
|
||||
<string name="excluded_uids">排除的UIDs</string>
|
||||
<string name="one_uid_per_line">一行一个UID</string>
|
||||
<string name="failed_to_save_current_config">保存当前配置失败</string>
|
||||
<string name="save_current_config">保存当前配置</string>
|
||||
<string name="delete_current_config">删除当前配置</string>
|
||||
<string name="override_apn_settings">APN设置</string>
|
||||
<string name="total_apn_amount">一共有%1$s个APN设置</string>
|
||||
<string name="select_a_apn_or_create">选择一个你要修改的APN设置(1~%1$s)或者输入0以新建APN设置</string>
|
||||
|
||||
@@ -339,15 +339,13 @@
|
||||
<string name="export_logs">Export logs</string>
|
||||
<string name="wifi_auth_keypair">Wi-Fi keypair</string>
|
||||
<string name="preferential_network_service">Preferential network service</string>
|
||||
<string name="add_config">Add config</string>
|
||||
<string name="network_id">Network ID</string>
|
||||
<string name="allow_fallback_to_default_connection">Allow fallback to default connection</string>
|
||||
<string name="block_non_matching_networks">Block non matching networks</string>
|
||||
<string name="included_uids">Included UIDs</string>
|
||||
<string name="excluded_uids">Excluded UIDs</string>
|
||||
<string name="one_uid_per_line">One UID per line</string>
|
||||
<string name="failed_to_save_current_config">Failed to save current config</string>
|
||||
<string name="save_current_config">Save current config</string>
|
||||
<string name="delete_current_config">Delete current config</string>
|
||||
<string name="override_apn_settings">APN settings</string>
|
||||
<string name="total_apn_amount">APN settings amount: %1$s</string>
|
||||
<string name="select_a_apn_or_create">Select an APN setting you want to edit (1~%1$s) or enter 0 to create a new APN setting. </string>
|
||||
|
||||
Reference in New Issue
Block a user