mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
Add Wi-Fi
This commit is contained in:
@@ -86,4 +86,5 @@ dependencies {
|
||||
implementation(libs.androidx.fragment)
|
||||
implementation(libs.hiddenApiBypass)
|
||||
implementation(libs.serialization)
|
||||
implementation(kotlin("reflect"))
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
|
||||
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/>
|
||||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||
<uses-sdk tools:overrideLibrary="rikka.shizuku.provider,rikka.shizuku.api,rikka.shizuku.shared,rikka.shizuku.aidl"/>
|
||||
<application
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
|
||||
@@ -59,6 +59,7 @@ import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.bintianqi.owndroid.dpm.AddNetwork
|
||||
import com.bintianqi.owndroid.dpm.AffiliationID
|
||||
import com.bintianqi.owndroid.dpm.AlwaysOnVPNPackage
|
||||
import com.bintianqi.owndroid.dpm.ApplicationManage
|
||||
@@ -236,6 +237,7 @@ fun Home(activity: FragmentActivity, vm: MyViewModel) {
|
||||
|
||||
composable(route = "Network") { Network(navCtrl) }
|
||||
composable(route = "NetworkOptions") { NetworkOptions(navCtrl) }
|
||||
composable(route = "AddWifi") { AddNetwork(navCtrl) }
|
||||
composable(route = "MinWifiSecurityLevel") { WifiSecurityLevel(navCtrl) }
|
||||
composable(route = "WifiSsidPolicy") { WifiSsidPolicy(navCtrl) }
|
||||
composable(route = "PrivateDNS") { PrivateDNS(navCtrl) }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.bintianqi.owndroid.dpm
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlertDialog
|
||||
import android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_OFF
|
||||
import android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_OPPORTUNISTIC
|
||||
import android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME
|
||||
@@ -19,8 +20,13 @@ import android.app.admin.WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_DENYLIST
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager.NameNotFoundException
|
||||
import android.net.IpConfiguration
|
||||
import android.net.LinkAddress
|
||||
import android.net.ProxyInfo
|
||||
import android.net.StaticIpConfiguration
|
||||
import android.net.Uri
|
||||
import android.net.wifi.WifiConfiguration
|
||||
import android.net.wifi.WifiManager
|
||||
import android.net.wifi.WifiSsid
|
||||
import android.os.Build.VERSION
|
||||
import android.telephony.TelephonyManager
|
||||
@@ -61,9 +67,13 @@ import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExposedDropdownMenuBox
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme.typography
|
||||
import androidx.compose.material3.MenuAnchorType
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
@@ -105,8 +115,11 @@ import com.bintianqi.owndroid.ui.ListItem
|
||||
import com.bintianqi.owndroid.ui.MyScaffold
|
||||
import com.bintianqi.owndroid.ui.RadioButtonItem
|
||||
import com.bintianqi.owndroid.ui.SwitchItem
|
||||
import com.bintianqi.owndroid.ui.UpOrDownTextFieldTrailingIconButton
|
||||
import com.bintianqi.owndroid.writeClipBoard
|
||||
import java.net.InetAddress
|
||||
import kotlin.math.max
|
||||
import kotlin.reflect.jvm.jvmErasure
|
||||
|
||||
@Composable
|
||||
fun Network(navCtrl:NavHostController) {
|
||||
@@ -125,6 +138,7 @@ fun Network(navCtrl:NavHostController) {
|
||||
if(VERSION.SDK_INT >= 30) {
|
||||
FunctionItem(R.string.options, "", R.drawable.tune_fill0) { navCtrl.navigate("NetworkOptions") }
|
||||
}
|
||||
FunctionItem(R.string.add_wifi, "", R.drawable.wifi_add_fill0) { navCtrl.navigate("AddWifi") }
|
||||
if(VERSION.SDK_INT >= 33 && (deviceOwner || dpm.isOrgProfile(receiver))) {
|
||||
FunctionItem(R.string.min_wifi_security_level, "", R.drawable.wifi_password_fill0) { navCtrl.navigate("MinWifiSecurityLevel") }
|
||||
}
|
||||
@@ -202,6 +216,266 @@ fun NetworkOptions(navCtrl: NavHostController) {
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AddNetwork(navCtrl: NavHostController) {
|
||||
val context = LocalContext.current
|
||||
var resultDialog by remember { mutableStateOf(false) }
|
||||
var createdNetworkId by remember { mutableIntStateOf(-1) }
|
||||
var createNetworkResult by remember {mutableIntStateOf(0)}
|
||||
var dropdownMenu by remember { mutableIntStateOf(0) } // 0: None, 1:Status, 2:Security, 3:MAC randomization, 4:Static IP, 5:Proxy
|
||||
var networkId by remember { mutableStateOf("") }
|
||||
var status by remember { mutableIntStateOf(WifiConfiguration.Status.ENABLED) }
|
||||
var ssid by remember { mutableStateOf("") }
|
||||
var hiddenSsid by remember { mutableStateOf(false) }
|
||||
var securityType by remember { mutableIntStateOf(WifiConfiguration.SECURITY_TYPE_OPEN) }
|
||||
var password by remember { mutableStateOf("") }
|
||||
var macRandomizationSetting by remember { mutableIntStateOf(WifiConfiguration.RANDOMIZATION_AUTO) }
|
||||
var useStaticIp by remember { mutableStateOf(false) }
|
||||
var ipAddress by remember { mutableStateOf("") }
|
||||
var gatewayAddress by remember { mutableStateOf("") }
|
||||
var dnsServers by remember { mutableStateOf("") }
|
||||
var useHttpProxy by remember { mutableStateOf(false) }
|
||||
var httpProxyHost by remember { mutableStateOf("") }
|
||||
var httpProxyPort by remember { mutableStateOf("") }
|
||||
var httpProxyExclList by remember { mutableStateOf("") }
|
||||
MyScaffold(R.string.add_wifi, 8.dp, navCtrl) {
|
||||
OutlinedTextField(
|
||||
value = networkId, onValueChange = { networkId = it }, label = { Text(stringResource(R.string.network_id)) },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
isError = networkId != "" && (try { networkId.toInt(); false } catch(_: NumberFormatException) { true }),
|
||||
modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp)
|
||||
)
|
||||
ExposedDropdownMenuBox(dropdownMenu == 1, { dropdownMenu = if(it) 1 else 0 }) {
|
||||
val statusText = when(status) {
|
||||
WifiConfiguration.Status.CURRENT -> R.string.current
|
||||
WifiConfiguration.Status.DISABLED -> R.string.disabled
|
||||
WifiConfiguration.Status.ENABLED -> R.string.enabled
|
||||
else -> R.string.place_holder
|
||||
}
|
||||
OutlinedTextField(
|
||||
value = stringResource(statusText), onValueChange = {}, readOnly = true,
|
||||
label = { Text(stringResource(R.string.status)) },
|
||||
trailingIcon = { UpOrDownTextFieldTrailingIconButton(dropdownMenu == 1) {} },
|
||||
modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth().padding(bottom = 16.dp)
|
||||
)
|
||||
ExposedDropdownMenu(dropdownMenu == 1, { dropdownMenu = 0 }) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.current)) },
|
||||
onClick = {
|
||||
status = WifiConfiguration.Status.CURRENT
|
||||
dropdownMenu = 0
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.disabled)) },
|
||||
onClick = {
|
||||
status = WifiConfiguration.Status.DISABLED
|
||||
dropdownMenu = 0
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.enabled)) },
|
||||
onClick = {
|
||||
status = WifiConfiguration.Status.ENABLED
|
||||
dropdownMenu = 0
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
OutlinedTextField(
|
||||
value = ssid, onValueChange = { ssid = it }, label = { Text("SSID") },
|
||||
modifier = Modifier.fillMaxWidth().padding(bottom = 4.dp)
|
||||
)
|
||||
CheckBoxItem(R.string.hidden_ssid, hiddenSsid, { hiddenSsid = it })
|
||||
if(VERSION.SDK_INT >= 30) {
|
||||
// TODO: more protocols
|
||||
val securityTypeTextMap = mutableMapOf(
|
||||
WifiConfiguration.SECURITY_TYPE_OPEN to stringResource(R.string.wifi_security_open),
|
||||
WifiConfiguration.SECURITY_TYPE_PSK to "PSK"
|
||||
)
|
||||
ExposedDropdownMenuBox(dropdownMenu == 2, { dropdownMenu = if(it) 2 else 0 }) {
|
||||
OutlinedTextField(
|
||||
value = securityTypeTextMap[securityType] ?: "", onValueChange = {}, label = { Text(stringResource(R.string.security)) },
|
||||
trailingIcon = { UpOrDownTextFieldTrailingIconButton(dropdownMenu == 1) {} }, readOnly = true,
|
||||
modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth().padding(vertical = 4.dp)
|
||||
)
|
||||
ExposedDropdownMenu(dropdownMenu == 2, { dropdownMenu = 0 }) {
|
||||
securityTypeTextMap.forEach {
|
||||
DropdownMenuItem(text = { Text(it.value) }, onClick = { securityType = it.key; dropdownMenu = 0 })
|
||||
}
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(securityType == WifiConfiguration.SECURITY_TYPE_PSK) {
|
||||
OutlinedTextField(
|
||||
value = password, onValueChange = { password = it }, label = { Text(stringResource(R.string.password)) },
|
||||
modifier = Modifier.fillMaxWidth().padding(bottom = 12.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 33) {
|
||||
val macRandomizationSettingTextMap = mapOf(
|
||||
WifiConfiguration.RANDOMIZATION_NONE to R.string.none,
|
||||
WifiConfiguration.RANDOMIZATION_PERSISTENT to R.string.persistent,
|
||||
WifiConfiguration.RANDOMIZATION_NON_PERSISTENT to R.string.non_persistent,
|
||||
WifiConfiguration.RANDOMIZATION_AUTO to R.string.auto
|
||||
)
|
||||
ExposedDropdownMenuBox(dropdownMenu == 3, { dropdownMenu = if(it) 3 else 0 }) {
|
||||
OutlinedTextField(
|
||||
value = stringResource(macRandomizationSettingTextMap[macRandomizationSetting] ?: R.string.place_holder),
|
||||
onValueChange = {}, readOnly = true,
|
||||
label = { Text(stringResource(R.string.mac_randomization)) },
|
||||
trailingIcon = { UpOrDownTextFieldTrailingIconButton(dropdownMenu == 3) {} },
|
||||
modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth().padding(bottom = 8.dp)
|
||||
)
|
||||
ExposedDropdownMenu(dropdownMenu == 3, { dropdownMenu = 0 }) {
|
||||
macRandomizationSettingTextMap.forEach {
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(it.value)) },
|
||||
onClick = {
|
||||
macRandomizationSetting = it.key
|
||||
dropdownMenu = 0
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 33) {
|
||||
ExposedDropdownMenuBox(dropdownMenu == 4, { dropdownMenu = if(it) 4 else 0 }) {
|
||||
OutlinedTextField(
|
||||
value = if(useStaticIp) stringResource(R.string.static_str) else "DHCP",
|
||||
onValueChange = {}, readOnly = true,
|
||||
label = { Text(stringResource(R.string.ip_settings)) },
|
||||
trailingIcon = { UpOrDownTextFieldTrailingIconButton(dropdownMenu == 4) {} },
|
||||
modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth().padding(bottom = 4.dp)
|
||||
)
|
||||
ExposedDropdownMenu(dropdownMenu == 4, { dropdownMenu = 0 }) {
|
||||
DropdownMenuItem(text = { Text("DHCP") }, onClick = { useStaticIp = false; dropdownMenu = 0 })
|
||||
DropdownMenuItem(text = { Text(stringResource(R.string.static_str)) }, onClick = { useStaticIp = true; dropdownMenu = 0 })
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(visible = useStaticIp, modifier = Modifier.padding(bottom = 8.dp)) {
|
||||
Column {
|
||||
OutlinedTextField(
|
||||
value = ipAddress, onValueChange = { ipAddress = it },
|
||||
placeholder = { Text("192.168.1.2/24") }, label = { Text(stringResource(R.string.ip_address)) },
|
||||
modifier = Modifier.fillMaxWidth().padding(bottom = 4.dp)
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = gatewayAddress, onValueChange = { gatewayAddress = it },
|
||||
placeholder = { Text("192.168.1.1") }, label = { Text(stringResource(R.string.gateway_address)) },
|
||||
modifier = Modifier.fillMaxWidth().padding(bottom = 4.dp)
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = dnsServers, onValueChange = { dnsServers = it },
|
||||
label = { Text(stringResource(R.string.dns_servers)) }, minLines = 2,
|
||||
modifier = Modifier.fillMaxWidth().padding(bottom = 4.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 26) {
|
||||
ExposedDropdownMenuBox(dropdownMenu == 5, { dropdownMenu = if(it) 5 else 0 }) {
|
||||
OutlinedTextField(
|
||||
value = if(useHttpProxy) "HTTP" else stringResource(R.string.none),
|
||||
onValueChange = {}, readOnly = true,
|
||||
label = { Text(stringResource(R.string.proxy)) },
|
||||
trailingIcon = { UpOrDownTextFieldTrailingIconButton(dropdownMenu == 5) {} },
|
||||
modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth().padding(bottom = 4.dp)
|
||||
)
|
||||
ExposedDropdownMenu(dropdownMenu == 5, { dropdownMenu = 0 }) {
|
||||
DropdownMenuItem(text = { Text(stringResource(R.string.none)) }, onClick = { useHttpProxy = false; dropdownMenu = 0 })
|
||||
DropdownMenuItem(text = { Text("HTTP") }, onClick = { useHttpProxy = true; dropdownMenu = 0 })
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(visible = useHttpProxy, modifier = Modifier.padding(bottom = 8.dp)) {
|
||||
Column {
|
||||
OutlinedTextField(
|
||||
value = httpProxyHost, onValueChange = { httpProxyHost = it }, label = { Text(stringResource(R.string.host)) },
|
||||
modifier = Modifier.fillMaxWidth().padding(bottom = 4.dp)
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = httpProxyPort, onValueChange = { httpProxyPort = it }, label = { Text(stringResource(R.string.port)) },
|
||||
modifier = Modifier.fillMaxWidth().padding(bottom = 4.dp)
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = httpProxyExclList, onValueChange = { httpProxyExclList = it }, label = { Text(stringResource(R.string.excluded_hosts)) },
|
||||
minLines = 2, placeholder = { Text("example.com\n*.example.com") },
|
||||
modifier = Modifier.fillMaxWidth().padding(bottom = 4.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Button(
|
||||
onClick = {
|
||||
val wm = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||
try {
|
||||
val config = WifiConfiguration()
|
||||
if(networkId != "") config.networkId = networkId.toInt()
|
||||
config.status = status
|
||||
config.SSID = '"' + ssid + '"'
|
||||
config.hiddenSSID = hiddenSsid
|
||||
if(VERSION.SDK_INT >= 30) config.setSecurityParams(securityType)
|
||||
if(securityType == WifiConfiguration.SECURITY_TYPE_PSK) config.preSharedKey = '"' + password + '"'
|
||||
if(VERSION.SDK_INT >= 33) config.macRandomizationSetting = macRandomizationSetting
|
||||
if(VERSION.SDK_INT >= 33 && useStaticIp) {
|
||||
val ipConf = IpConfiguration.Builder()
|
||||
val staticIpConf = StaticIpConfiguration.Builder()
|
||||
val la: LinkAddress
|
||||
val con = LinkAddress::class.constructors.find { it.parameters.size == 1 && it.parameters[0].type.jvmErasure == String::class }
|
||||
la = con!!.call(ipAddress)
|
||||
staticIpConf.setIpAddress(la)
|
||||
staticIpConf.setGateway(InetAddress.getByName(gatewayAddress))
|
||||
staticIpConf.setDnsServers(dnsServers.lines().map { InetAddress.getByName(it) })
|
||||
ipConf.setStaticIpConfiguration(staticIpConf.build())
|
||||
config.setIpConfiguration(ipConf.build())
|
||||
}
|
||||
if(VERSION.SDK_INT >= 26 && useHttpProxy) {
|
||||
config.httpProxy = ProxyInfo.buildDirectProxy(httpProxyHost, httpProxyPort.toInt(), httpProxyExclList.lines())
|
||||
}
|
||||
if(VERSION.SDK_INT >= 31) {
|
||||
val result = wm.addNetworkPrivileged(config)
|
||||
createdNetworkId = result.networkId
|
||||
createNetworkResult = result.statusCode
|
||||
} else {
|
||||
createdNetworkId = wm.addNetwork(config)
|
||||
}
|
||||
resultDialog = true
|
||||
} catch(e: Exception) {
|
||||
e.printStackTrace()
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(R.string.error)
|
||||
.setPositiveButton(R.string.confirm) { dialog, _ -> dialog.cancel() }
|
||||
.setMessage(e.message ?: "")
|
||||
.show()
|
||||
}
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp)
|
||||
) {
|
||||
Text(stringResource(R.string.add))
|
||||
}
|
||||
if(resultDialog) AlertDialog(
|
||||
text = {
|
||||
val statusText = when(createNetworkResult) {
|
||||
WifiManager.AddNetworkResult.STATUS_SUCCESS -> R.string.success
|
||||
//WifiManager.AddNetworkResult.STATUS_ADD_WIFI_CONFIG_FAILURE -> R.string.failed
|
||||
WifiManager.AddNetworkResult.STATUS_INVALID_CONFIGURATION -> R.string.add_network_result_invalid_configuration
|
||||
else -> R.string.failed
|
||||
}
|
||||
Text(stringResource(statusText) + "\n" + stringResource(R.string.network_id) + ": " + createdNetworkId)
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = { resultDialog = false }) {
|
||||
Text(stringResource(R.string.confirm))
|
||||
}
|
||||
},
|
||||
onDismissRequest = { resultDialog = false }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Composable
|
||||
fun WifiSecurityLevel(navCtrl: NavHostController) {
|
||||
@@ -513,7 +787,7 @@ fun RecommendedGlobalProxy(navCtrl: NavHostController) {
|
||||
OutlinedTextField(
|
||||
value = exclList,
|
||||
onValueChange = { exclList = it },
|
||||
label = { Text(stringResource(R.string.exclude_hosts)) },
|
||||
label = { Text(stringResource(R.string.excluded_hosts)) },
|
||||
maxLines = 5,
|
||||
minLines = 2,
|
||||
modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp)
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.widget.Toast
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
@@ -13,6 +14,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowDropDown
|
||||
import androidx.compose.material.icons.outlined.Info
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||
@@ -22,6 +24,7 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
@@ -315,3 +318,17 @@ fun MyScaffold(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun UpOrDownTextFieldTrailingIconButton(active: Boolean, onClick: () -> Unit) {
|
||||
val degrees by animateFloatAsState(if(active) 180F else 0F)
|
||||
IconButton(
|
||||
onClick = onClick,
|
||||
modifier = Modifier.clip(RoundedCornerShape(50))
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ArrowDropDown, contentDescription = null,
|
||||
modifier = Modifier.rotate(degrees)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
9
app/src/main/res/drawable/wifi_add_fill0.xml
Normal file
9
app/src/main/res/drawable/wifi_add_fill0.xml
Normal 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="M720,840v-120L600,720v-80h120v-120h80v120h120v80L800,720v120h-80ZM480,840L0,360q95,-97 219.5,-148.5T480,160q136,0 260.5,51.5T960,360L822,497q-14,-14 -28,-28.5T766,440l78,-78q-79,-60 -172,-91t-192,-31q-99,0 -192,31t-172,91l364,364 40,-40 28.5,28.5L577,743l-97,97ZM480,483Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
@@ -64,6 +64,7 @@
|
||||
<string name="unknown_error">Unknown error</string>
|
||||
<string name="permission_denied">Permission denied</string>
|
||||
<string name="error">Error</string>
|
||||
<string name="status">Status</string>
|
||||
|
||||
|
||||
<!--Разрешения-->
|
||||
@@ -215,6 +216,19 @@
|
||||
<!--Сеть-->
|
||||
<string name="network">Сеть</string>
|
||||
<string name="wifi_mac_address">MAC-адрес Wi-Fi</string>
|
||||
<!--TODO-->
|
||||
<string name="add_wifi">Add Wi-Fi</string>
|
||||
<string name="current">Current</string>
|
||||
<string name="hidden_ssid">Hidden SSID</string>
|
||||
<string name="ip_settings">IP settings</string>
|
||||
<string name="static_str">Static</string>
|
||||
<string name="ip_address">IP address</string>
|
||||
<string name="gateway_address">Gateway address</string>
|
||||
<string name="dns_servers">DNS servers</string>
|
||||
<string name="mac_randomization">MAC randomization</string>
|
||||
<string name="non_persistent">Non persistent</string>
|
||||
<string name="host">Host</string>
|
||||
<string name="add_network_result_invalid_configuration">Invalid configuration</string>
|
||||
<string name="min_wifi_security_level">Минимальный уровень безопасности Wi-Fi</string>
|
||||
<string name="wifi_security_open">Открытая</string>
|
||||
<string name="lockdown_admin_configured_network">Блокировка ети, настроенной администратором</string>
|
||||
@@ -235,7 +249,7 @@
|
||||
<string name="proxy_type_direct">Прямой прокси</string>
|
||||
<string name="specify_port">Указать порт</string>
|
||||
<string name="invalid_config">Неверная конфигурация</string>
|
||||
<string name="exclude_hosts">Исключить хосты</string>
|
||||
<string name="excluded_hosts">Исключить хосты</string> <!--TODO-->
|
||||
<string name="network_logging">Network logging</string> <!--TODO-->
|
||||
<string name="log_file_size_is">Размер файла журнала: %1$s</string>
|
||||
<string name="delete_logs">Удалить журналы</string>
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
<string name="unknown_error">Unknown error</string>
|
||||
<string name="permission_denied">Permission denied</string>
|
||||
<string name="error">Error</string>
|
||||
<string name="status">Status</string>
|
||||
|
||||
<!--Permissions-->
|
||||
<string name="click_to_activate">Etkinleştirmek İçin Tıklayın</string>
|
||||
@@ -216,6 +217,19 @@
|
||||
<!--Network-->
|
||||
<string name="network">Ağ</string>
|
||||
<string name="wifi_mac_address">Wi-Fi MAC adresi</string>
|
||||
<!--TODO-->
|
||||
<string name="add_wifi">Add Wi-Fi</string>
|
||||
<string name="current">Current</string>
|
||||
<string name="hidden_ssid">Hidden SSID</string>
|
||||
<string name="ip_settings">IP settings</string>
|
||||
<string name="static_str">Static</string>
|
||||
<string name="ip_address">IP address</string>
|
||||
<string name="gateway_address">Gateway address</string>
|
||||
<string name="dns_servers">DNS servers</string>
|
||||
<string name="mac_randomization">MAC randomization</string>
|
||||
<string name="non_persistent">Non persistent</string>
|
||||
<string name="host">Host</string>
|
||||
<string name="add_network_result_invalid_configuration">Invalid configuration</string>
|
||||
<string name="min_wifi_security_level">Minimum Wi-Fi güvenlik seviyesi</string>
|
||||
<string name="wifi_security_open">Açık</string>
|
||||
<string name="lockdown_admin_configured_network">Yönetici tarafından yapılandırılmış ağı kilitle</string>
|
||||
@@ -236,7 +250,7 @@
|
||||
<string name="proxy_type_direct">Direct proxy</string> <!--TODO-->
|
||||
<string name="specify_port">Specify port</string> <!--TODO-->
|
||||
<string name="invalid_config">Invalid config</string> <!--TODO-->
|
||||
<string name="exclude_hosts">Exclude hosts</string> <!--TODO-->
|
||||
<string name="excluded_hosts">Excluded hosts</string> <!--TODO-->
|
||||
<string name="network_logging">Network logging</string> <!--TODO-->
|
||||
<string name="log_file_size_is">Log file size: %1$s</string> <!--TODO-->
|
||||
<string name="delete_logs">Delete logs</string> <!--TODO-->
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
<string name="unknown_error">未知错误</string>
|
||||
<string name="permission_denied">无权限</string>
|
||||
<string name="error">错误</string>
|
||||
<string name="status">状态</string>
|
||||
|
||||
<!--Permissions-->
|
||||
<string name="click_to_activate">点击以激活</string>
|
||||
@@ -208,7 +209,19 @@
|
||||
|
||||
<!--Network-->
|
||||
<string name="network">网络</string>
|
||||
<string name="wifi_mac_address">Wi-Fi Mac地址</string>
|
||||
<string name="wifi_mac_address">Wi-Fi MAC地址</string>
|
||||
<string name="add_wifi">添加Wi-Fi</string>
|
||||
<string name="current">当前</string>
|
||||
<string name="hidden_ssid">隐藏的SSID</string>
|
||||
<string name="ip_settings">IP设置</string>
|
||||
<string name="static_str">静态</string>
|
||||
<string name="ip_address">IP地址</string>
|
||||
<string name="gateway_address">网关地址</string>
|
||||
<string name="dns_servers">DNS服务器</string>
|
||||
<string name="mac_randomization">MAC随机化</string>
|
||||
<string name="non_persistent">非持久</string>
|
||||
<string name="host">主机</string>
|
||||
<string name="add_network_result_invalid_configuration">Invalid configuration</string>
|
||||
<string name="min_wifi_security_level">最低Wi-Fi安全等级</string>
|
||||
<string name="wifi_security_open">开放</string>
|
||||
<string name="lockdown_admin_configured_network">锁定由管理员配置的网络</string>
|
||||
@@ -229,7 +242,7 @@
|
||||
<string name="proxy_type_direct">直连代理</string>
|
||||
<string name="specify_port">指定端口</string>
|
||||
<string name="invalid_config">无效配置</string>
|
||||
<string name="exclude_hosts">排除列表</string>
|
||||
<string name="excluded_hosts">排除的主机</string>
|
||||
<string name="network_logging">网络日志</string>
|
||||
<string name="log_file_size_is">日志文件大小:%1$s</string>
|
||||
<string name="delete_logs">删除日志</string>
|
||||
@@ -534,7 +547,7 @@
|
||||
<string name="project_homepage">项目主页</string>
|
||||
<string name="appearance">外观</string>
|
||||
|
||||
<string name="security">安全</string>
|
||||
<string name="security">安全性</string>
|
||||
<string name="lock_owndroid">锁定OwnDroid</string>
|
||||
<string name="enable_bio_auth">使用生物识别</string>
|
||||
<string name="authenticate">验证</string>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!--Global-->
|
||||
<string name="app_name" translatable="false">OwnDroid</string>
|
||||
<string name="place_holder" translatable="false"/>
|
||||
<string name="disabled">Disabled</string>
|
||||
<string name="enabled">Enabled</string>
|
||||
<string name="disable">Disable</string>
|
||||
@@ -65,6 +66,7 @@
|
||||
<string name="permission_denied">Permission denied</string>
|
||||
<string name="api" translatable="false">API</string>
|
||||
<string name="error">Error</string>
|
||||
<string name="status">Status</string>
|
||||
|
||||
<!--Permissions-->
|
||||
<string name="click_to_activate">Click to activate</string>
|
||||
@@ -220,6 +222,18 @@
|
||||
<!--Network-->
|
||||
<string name="network">Network</string>
|
||||
<string name="wifi_mac_address">Wi-Fi Mac address</string>
|
||||
<string name="add_wifi">Add Wi-Fi</string>
|
||||
<string name="current">Current</string>
|
||||
<string name="hidden_ssid">Hidden SSID</string>
|
||||
<string name="ip_settings">IP settings</string>
|
||||
<string name="static_str">Static</string>
|
||||
<string name="ip_address">IP address</string>
|
||||
<string name="gateway_address">Gateway address</string>
|
||||
<string name="dns_servers">DNS servers</string>
|
||||
<string name="mac_randomization">MAC randomization</string>
|
||||
<string name="non_persistent">Non persistent</string>
|
||||
<string name="host">Host</string>
|
||||
<string name="add_network_result_invalid_configuration">Invalid configuration</string>
|
||||
<string name="min_wifi_security_level">Minimum Wi-Fi security level</string>
|
||||
<string name="wifi_security_open">Open</string>
|
||||
<string name="lockdown_admin_configured_network">Lockdown admin configured network</string>
|
||||
@@ -240,7 +254,7 @@
|
||||
<string name="proxy_type_direct">Direct proxy</string>
|
||||
<string name="specify_port">Specify port</string>
|
||||
<string name="invalid_config">Invalid config</string>
|
||||
<string name="exclude_hosts">Exclude hosts</string>
|
||||
<string name="excluded_hosts">Excluded hosts</string>
|
||||
<string name="network_logging">Network logging</string>
|
||||
<string name="log_file_size_is">Log file size: %1$s</string>
|
||||
<string name="delete_logs">Delete logs</string>
|
||||
|
||||
Reference in New Issue
Block a user