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) }
|
var tab by remember { mutableIntStateOf(0) }
|
||||||
val pagerState = rememberPagerState { 2 }
|
val pagerState = rememberPagerState { 2 }
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
|
tab = pagerState.targetPage
|
||||||
Column(modifier = Modifier.padding(paddingValues)) {
|
Column(modifier = Modifier.padding(paddingValues)) {
|
||||||
TabRow(tab) {
|
TabRow(tab) {
|
||||||
Tab(
|
Tab(
|
||||||
tab == 0,
|
tab == 0,
|
||||||
onClick = {
|
onClick = {
|
||||||
tab = 0
|
|
||||||
coroutine.launch { scrollState.animateScrollTo(0) }
|
coroutine.launch { scrollState.animateScrollTo(0) }
|
||||||
coroutine.launch { pagerState.animateScrollToPage(0) }
|
coroutine.launch { pagerState.animateScrollToPage(0) }
|
||||||
},
|
},
|
||||||
@@ -160,7 +160,6 @@ private fun AppInstaller(
|
|||||||
Tab(
|
Tab(
|
||||||
tab == 1,
|
tab == 1,
|
||||||
onClick = {
|
onClick = {
|
||||||
tab = 1
|
|
||||||
coroutine.launch { scrollState.animateScrollTo(0) }
|
coroutine.launch { scrollState.animateScrollTo(0) }
|
||||||
coroutine.launch { pagerState.animateScrollToPage(1) }
|
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.AddDelegatedAdminScreen
|
||||||
import com.bintianqi.owndroid.dpm.AddNetwork
|
import com.bintianqi.owndroid.dpm.AddNetwork
|
||||||
import com.bintianqi.owndroid.dpm.AddNetworkScreen
|
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.AffiliationId
|
||||||
import com.bintianqi.owndroid.dpm.AffiliationIdScreen
|
import com.bintianqi.owndroid.dpm.AffiliationIdScreen
|
||||||
import com.bintianqi.owndroid.dpm.AlwaysOnVpnPackage
|
import com.bintianqi.owndroid.dpm.AlwaysOnVpnPackage
|
||||||
@@ -340,7 +342,8 @@ fun Home(activity: FragmentActivity, vm: MyViewModel) {
|
|||||||
composable<RecommendedGlobalProxy> { RecommendedGlobalProxyScreen(::navigateUp) }
|
composable<RecommendedGlobalProxy> { RecommendedGlobalProxyScreen(::navigateUp) }
|
||||||
composable<NetworkLogging> { NetworkLoggingScreen(::navigateUp) }
|
composable<NetworkLogging> { NetworkLoggingScreen(::navigateUp) }
|
||||||
composable<WifiAuthKeypair> { WifiAuthKeypairScreen(::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<OverrideApn> { OverrideApnScreen(::navigateUp) }
|
||||||
|
|
||||||
composable<WorkProfile> { WorkProfileScreen(::navigateUp, ::navigate) }
|
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.user_restriction, R.drawable.person_off) { onNavigate(UserRestriction) }
|
||||||
}
|
}
|
||||||
HomePageItem(R.string.users,R.drawable.manage_accounts_fill0) { onNavigate(Users) }
|
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) }
|
HomePageItem(R.string.settings, R.drawable.settings_fill0) { onNavigate(Settings) }
|
||||||
Spacer(Modifier.padding(vertical = 20.dp))
|
Spacer(Modifier.padding(vertical = 20.dp))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build.VERSION
|
import android.os.Build.VERSION
|
||||||
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.biometric.BiometricManager
|
import androidx.biometric.BiometricManager
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
@@ -38,16 +40,27 @@ import com.bintianqi.owndroid.ui.MyScaffold
|
|||||||
import com.bintianqi.owndroid.ui.SwitchItem
|
import com.bintianqi.owndroid.ui.SwitchItem
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
@Serializable object Settings
|
@Serializable object Settings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingsScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
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) {
|
MyScaffold(R.string.settings, 0.dp, onNavigateUp) {
|
||||||
FunctionItem(title = R.string.options, icon = R.drawable.tune_fill0) { onNavigate(SettingsOptions) }
|
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.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.security, icon = R.drawable.lock_fill0) { onNavigate(AuthSettings) }
|
||||||
FunctionItem(title = R.string.api, icon = R.drawable.apps_fill0) { onNavigate(ApiSettings) }
|
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) }
|
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.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Process
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.result.contract.ActivityResultContract
|
import androidx.activity.result.contract.ActivityResultContract
|
||||||
@@ -28,6 +30,7 @@ import java.time.ZoneId
|
|||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.reflect.typeOf
|
import kotlin.reflect.typeOf
|
||||||
|
|
||||||
var zhCN = true
|
var zhCN = true
|
||||||
@@ -122,3 +125,13 @@ class ChoosePackageContract: ActivityResultContract<Nothing?, String?>() {
|
|||||||
override fun parseResult(resultCode: Int, intent: Intent?): String? =
|
override fun parseResult(resultCode: Int, intent: Intent?): String? =
|
||||||
intent?.getStringExtra("package")
|
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.KeyboardArrowLeft
|
||||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
|
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
|
||||||
import androidx.compose.material.icons.filled.Add
|
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.filled.Edit
|
||||||
import androidx.compose.material.icons.outlined.Delete
|
import androidx.compose.material.icons.outlined.Delete
|
||||||
import androidx.compose.material.icons.outlined.LocationOn
|
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.MenuAnchorType
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Scaffold
|
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.Switch
|
||||||
import androidx.compose.material3.Tab
|
import androidx.compose.material3.Tab
|
||||||
import androidx.compose.material3.TabRow
|
import androidx.compose.material3.TabRow
|
||||||
@@ -156,7 +158,6 @@ import kotlinx.coroutines.launch
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.reflect.jvm.jvmErasure
|
import kotlin.reflect.jvm.jvmErasure
|
||||||
|
|
||||||
@Serializable object Network
|
@Serializable object Network
|
||||||
@@ -1714,122 +1715,95 @@ fun WifiAuthKeypairScreen(onNavigateUp: () -> Unit) {
|
|||||||
|
|
||||||
@RequiresApi(33)
|
@RequiresApi(33)
|
||||||
@Composable
|
@Composable
|
||||||
fun PreferentialNetworkServiceScreen(onNavigateUp: () -> Unit) {
|
fun PreferentialNetworkServiceScreen(onNavigateUp: () -> Unit, onNavigate: (AddPreferentialNetworkServiceConfig) -> Unit) {
|
||||||
val focusMgr = LocalFocusManager.current
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val dpm = context.getDPM()
|
val dpm = context.getDPM()
|
||||||
var masterEnabled by remember { mutableStateOf(false) }
|
var masterEnabled by remember { mutableStateOf(false) }
|
||||||
val configs = remember { mutableStateListOf<PreferentialNetworkServiceConfig>() }
|
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() {
|
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
|
masterEnabled = dpm.isPreferentialNetworkServiceEnabled
|
||||||
|
configs.clear()
|
||||||
configs.addAll(dpm.preferentialNetworkServiceConfigs)
|
configs.addAll(dpm.preferentialNetworkServiceConfigs)
|
||||||
index = max(0, configs.size - 1)
|
|
||||||
refresh()
|
|
||||||
}
|
}
|
||||||
LaunchedEffect(Unit) { initialize() }
|
LaunchedEffect(Unit) { refresh() }
|
||||||
MyScaffold(R.string.preferential_network_service, 8.dp, onNavigateUp) {
|
MyScaffold(R.string.preferential_network_service, 0.dp, onNavigateUp, false) {
|
||||||
SwitchItem(R.string.enabled, state = masterEnabled, onCheckedChange = { masterEnabled = it }, padding = false)
|
SwitchItem(R.string.enabled, state = masterEnabled, onCheckedChange = {
|
||||||
|
dpm.isPreferentialNetworkServiceEnabled = it
|
||||||
|
refresh()
|
||||||
|
})
|
||||||
|
Spacer(Modifier.padding(vertical = 4.dp))
|
||||||
|
configs.forEachIndexed { index, config ->
|
||||||
Row(
|
Row(
|
||||||
horizontalArrangement = Arrangement.SpaceAround,
|
Modifier.fillMaxWidth().padding(start = 16.dp, end = 8.dp, top = 4.dp, bottom = 4.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
Arrangement.SpaceBetween, Alignment.CenterVertically
|
||||||
modifier = Modifier.fillMaxWidth().padding(top = 8.dp)
|
|
||||||
) {
|
) {
|
||||||
IconButton(
|
Column {
|
||||||
onClick = {
|
Text(index.toString())
|
||||||
try {
|
|
||||||
saveCurrentConfig()
|
|
||||||
index -= 1
|
|
||||||
refresh()
|
|
||||||
} catch(e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
Toast.makeText(context, R.string.failed_to_save_current_config, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
}
|
||||||
},
|
IconButton({
|
||||||
enabled = index > 0
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Row(
|
||||||
|
Modifier.fillMaxWidth()
|
||||||
|
.padding(top = 4.dp)
|
||||||
|
.clickable { onNavigate(AddPreferentialNetworkServiceConfig()) }
|
||||||
|
.padding(horizontal = 8.dp, vertical = 12.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Icon(imageVector = Icons.AutoMirrored.Default.KeyboardArrowLeft, contentDescription = stringResource(R.string.previous))
|
Icon(Icons.Default.Add, null, Modifier.padding(horizontal = 8.dp))
|
||||||
}
|
Text(stringResource(R.string.add_config))
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) {
|
}
|
||||||
Icon(
|
|
||||||
imageVector = if(index + 1 >= configs.size) Icons.Default.Add else Icons.AutoMirrored.Default.KeyboardArrowRight,
|
@Serializable data class AddPreferentialNetworkServiceConfig(
|
||||||
contentDescription = stringResource(R.string.previous)
|
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)
|
||||||
Row(
|
@Composable
|
||||||
horizontalArrangement = Arrangement.Center,
|
fun AddPreferentialNetworkServiceConfigScreen(route: AddPreferentialNetworkServiceConfig,onNavigateUp: () -> Unit) {
|
||||||
modifier = Modifier.fillMaxWidth()
|
val updateMode = route.index != -1
|
||||||
) {
|
val context = LocalContext.current
|
||||||
IconButton(
|
val dpm = context.getDPM()
|
||||||
onClick = {
|
var enabled by remember { mutableStateOf(route.enabled) }
|
||||||
try {
|
var id by remember { mutableIntStateOf(route.id) }
|
||||||
saveCurrentConfig()
|
var allowFallback by remember { mutableStateOf(route.allowFallback) }
|
||||||
context.showOperationResultToast(true)
|
var blockNonMatching by remember { mutableStateOf(route.blockNonMatching) }
|
||||||
} catch(e: Exception) {
|
var excludedUids by remember { mutableStateOf(route.excludedUids.joinToString("\n")) }
|
||||||
e.printStackTrace()
|
var includedUids by remember { mutableStateOf(route.includedUids.joinToString("\n")) }
|
||||||
Toast.makeText(context, R.string.failed_to_save_current_config, Toast.LENGTH_SHORT).show()
|
MyScaffold(R.string.preferential_network_service, 8.dp, onNavigateUp, false) {
|
||||||
}
|
|
||||||
},
|
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SwitchItem(title = R.string.enabled, state = enabled, onCheckedChange = { enabled = it }, padding = false)
|
SwitchItem(title = R.string.enabled, state = enabled, onCheckedChange = { enabled = it }, padding = false)
|
||||||
OutlinedTextField(
|
AnimatedVisibility(enabled) {
|
||||||
value = networkId, onValueChange = { networkId = it },
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
label = { Text(stringResource(R.string.network_id)) },
|
Text("ID", Modifier.padding(end = 8.dp), style = typography.titleLarge)
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
SingleChoiceSegmentedButtonRow(Modifier.fillMaxWidth()) {
|
||||||
keyboardActions = KeyboardActions { focusMgr.clearFocus() },
|
for(i in 1..5) {
|
||||||
modifier = Modifier.fillMaxWidth().padding(bottom = 6.dp)
|
SegmentedButton(id == i, { id = i }, SegmentedButtonDefaults.itemShape(i - 1, 5)) {
|
||||||
)
|
Text(i.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
SwitchItem(
|
SwitchItem(
|
||||||
title = R.string.allow_fallback_to_default_connection,
|
title = R.string.allow_fallback_to_default_connection,
|
||||||
state = allowFallback, onCheckedChange = { allowFallback = it }, padding = false
|
state = allowFallback, onCheckedChange = { allowFallback = it }, padding = false
|
||||||
@@ -1838,28 +1812,66 @@ fun PreferentialNetworkServiceScreen(onNavigateUp: () -> Unit) {
|
|||||||
title = R.string.block_non_matching_networks,
|
title = R.string.block_non_matching_networks,
|
||||||
state = blockNonMatching, onCheckedChange = { blockNonMatching = it }, padding = false
|
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(
|
OutlinedTextField(
|
||||||
value = includedUids, onValueChange = { includedUids = it }, minLines = 2,
|
value = includedUids, onValueChange = { includedUids = it }, minLines = 2,
|
||||||
label = { Text(stringResource(R.string.included_uids)) },
|
label = { Text(stringResource(R.string.included_uids)) },
|
||||||
supportingText = { Text(stringResource(R.string.one_uid_per_line)) },
|
supportingText = { Text(stringResource(R.string.one_uid_per_line)) },
|
||||||
|
isError = !includedUidsLegal,
|
||||||
modifier = Modifier.fillMaxWidth().padding(bottom = 6.dp)
|
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(
|
OutlinedTextField(
|
||||||
value = excludedUids, onValueChange = { excludedUids = it }, minLines = 2,
|
value = excludedUids, onValueChange = { excludedUids = it }, minLines = 2,
|
||||||
label = { Text(stringResource(R.string.excluded_uids)) },
|
label = { Text(stringResource(R.string.excluded_uids)) },
|
||||||
supportingText = { Text(stringResource(R.string.one_uid_per_line)) },
|
supportingText = { Text(stringResource(R.string.one_uid_per_line)) },
|
||||||
|
isError = !excludedUidsLegal,
|
||||||
modifier = Modifier.fillMaxWidth().padding(bottom = 6.dp)
|
modifier = Modifier.fillMaxWidth().padding(bottom = 6.dp)
|
||||||
)
|
)
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
dpm.isPreferentialNetworkServiceEnabled = masterEnabled
|
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
|
dpm.preferentialNetworkServiceConfigs = configs
|
||||||
initialize()
|
onNavigateUp()
|
||||||
context.showOperationResultToast(true)
|
} 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="export_logs">Экспортировать журналы</string>
|
||||||
<string name="wifi_auth_keypair">Пара ключей Wi-Fi</string>
|
<string name="wifi_auth_keypair">Пара ключей Wi-Fi</string>
|
||||||
<string name="preferential_network_service">Предпочтительная сетевая служба</string>
|
<string name="preferential_network_service">Предпочтительная сетевая служба</string>
|
||||||
|
<string name="add_config">Add config</string> <!--TODO-->
|
||||||
<string name="network_id">Идентификатор сети</string>
|
<string name="network_id">Идентификатор сети</string>
|
||||||
<string name="allow_fallback_to_default_connection">Разрешить переход на соединение по умолчанию</string>
|
<string name="allow_fallback_to_default_connection">Разрешить переход на соединение по умолчанию</string>
|
||||||
<string name="block_non_matching_networks">Блокировать несоответствующие сети</string>
|
<string name="block_non_matching_networks">Блокировать несоответствующие сети</string>
|
||||||
<string name="included_uids">Включенные UID</string>
|
<string name="included_uids">Включенные UID</string>
|
||||||
<string name="excluded_uids">Исключенные UID</string>
|
<string name="excluded_uids">Исключенные UID</string>
|
||||||
<string name="one_uid_per_line">Один 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="override_apn_settings">Настройки APN</string>
|
||||||
<string name="total_apn_amount">Количество настроек APN: %1$s</string>
|
<string name="total_apn_amount">Количество настроек APN: %1$s</string>
|
||||||
<string name="select_a_apn_or_create">Выберите настройку APN для редактирования (1~%1$s) или введите 0, чтобы создать новую настройку APN.</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="export_logs">Export logs</string> <!--TODO-->
|
||||||
<string name="wifi_auth_keypair">Wi-Fi anahtar çifti</string>
|
<string name="wifi_auth_keypair">Wi-Fi anahtar çifti</string>
|
||||||
<string name="preferential_network_service">Tercihli ağ hizmeti</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="network_id">Network ID</string> <!--TODO-->
|
||||||
<string name="allow_fallback_to_default_connection">Allow fallback to default connection</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="block_non_matching_networks">Block non matching networks</string> <!--TODO-->
|
||||||
<string name="included_uids">Included UIDs</string> <!--TODO-->
|
<string name="included_uids">Included UIDs</string> <!--TODO-->
|
||||||
<string name="excluded_uids">Excluded 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="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="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="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>
|
<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="export_logs">导出日志</string>
|
||||||
<string name="wifi_auth_keypair">Wi-Fi密钥对</string>
|
<string name="wifi_auth_keypair">Wi-Fi密钥对</string>
|
||||||
<string name="preferential_network_service">首选网络服务</string>
|
<string name="preferential_network_service">首选网络服务</string>
|
||||||
|
<string name="add_config">添加配置</string>
|
||||||
<string name="network_id">网络ID</string>
|
<string name="network_id">网络ID</string>
|
||||||
<string name="allow_fallback_to_default_connection">允许回落到默认连接</string>
|
<string name="allow_fallback_to_default_connection">允许回落到默认连接</string>
|
||||||
<string name="block_non_matching_networks">阻止不匹配的网络</string>
|
<string name="block_non_matching_networks">阻止不匹配的网络</string>
|
||||||
<string name="included_uids">包含的UID</string>
|
<string name="included_uids">包含的UID</string>
|
||||||
<string name="excluded_uids">排除的UIDs</string>
|
<string name="excluded_uids">排除的UIDs</string>
|
||||||
<string name="one_uid_per_line">一行一个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="override_apn_settings">APN设置</string>
|
||||||
<string name="total_apn_amount">一共有%1$s个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>
|
<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="export_logs">Export logs</string>
|
||||||
<string name="wifi_auth_keypair">Wi-Fi keypair</string>
|
<string name="wifi_auth_keypair">Wi-Fi keypair</string>
|
||||||
<string name="preferential_network_service">Preferential network service</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="network_id">Network ID</string>
|
||||||
<string name="allow_fallback_to_default_connection">Allow fallback to default connection</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="block_non_matching_networks">Block non matching networks</string>
|
||||||
<string name="included_uids">Included UIDs</string>
|
<string name="included_uids">Included UIDs</string>
|
||||||
<string name="excluded_uids">Excluded UIDs</string>
|
<string name="excluded_uids">Excluded UIDs</string>
|
||||||
<string name="one_uid_per_line">One UID per line</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="override_apn_settings">APN settings</string>
|
||||||
<string name="total_apn_amount">APN settings amount: %1$s</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>
|
<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