mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
Some Wi-Fi operations
Enable/disable Wi-Fi Disconnect/reconnect Wi-Fi View, edit or delete saved networks
This commit is contained in:
@@ -77,6 +77,7 @@ dependencies {
|
|||||||
implementation(libs.androidx.activity.compose)
|
implementation(libs.androidx.activity.compose)
|
||||||
implementation(platform(libs.androidx.compose.bom))
|
implementation(platform(libs.androidx.compose.bom))
|
||||||
implementation(libs.accompanist.drawablepainter)
|
implementation(libs.accompanist.drawablepainter)
|
||||||
|
implementation(libs.accompanist.permissions)
|
||||||
implementation(libs.androidx.material3)
|
implementation(libs.androidx.material3)
|
||||||
implementation(libs.androidx.navigation.compose)
|
implementation(libs.androidx.navigation.compose)
|
||||||
implementation(libs.shizuku.provider)
|
implementation(libs.shizuku.provider)
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
|
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
|
||||||
<uses-permission android:name="android.permission.REQUEST_DELETE_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.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
<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"/>
|
<uses-sdk tools:overrideLibrary="rikka.shizuku.provider,rikka.shizuku.api,rikka.shizuku.shared,rikka.shizuku.aidl"/>
|
||||||
<application
|
<application
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ import androidx.navigation.NavHostController
|
|||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import com.bintianqi.owndroid.dpm.AddNetwork
|
|
||||||
import com.bintianqi.owndroid.dpm.AffiliationID
|
import com.bintianqi.owndroid.dpm.AffiliationID
|
||||||
import com.bintianqi.owndroid.dpm.AlwaysOnVPNPackage
|
import com.bintianqi.owndroid.dpm.AlwaysOnVPNPackage
|
||||||
import com.bintianqi.owndroid.dpm.ApplicationManage
|
import com.bintianqi.owndroid.dpm.ApplicationManage
|
||||||
@@ -111,12 +110,14 @@ import com.bintianqi.owndroid.dpm.SystemManage
|
|||||||
import com.bintianqi.owndroid.dpm.SystemOptions
|
import com.bintianqi.owndroid.dpm.SystemOptions
|
||||||
import com.bintianqi.owndroid.dpm.SystemUpdatePolicy
|
import com.bintianqi.owndroid.dpm.SystemUpdatePolicy
|
||||||
import com.bintianqi.owndroid.dpm.TransferOwnership
|
import com.bintianqi.owndroid.dpm.TransferOwnership
|
||||||
|
import com.bintianqi.owndroid.dpm.UpdateNetwork
|
||||||
import com.bintianqi.owndroid.dpm.UserOperation
|
import com.bintianqi.owndroid.dpm.UserOperation
|
||||||
import com.bintianqi.owndroid.dpm.UserOptions
|
import com.bintianqi.owndroid.dpm.UserOptions
|
||||||
import com.bintianqi.owndroid.dpm.UserRestriction
|
import com.bintianqi.owndroid.dpm.UserRestriction
|
||||||
import com.bintianqi.owndroid.dpm.UserRestrictionItem
|
import com.bintianqi.owndroid.dpm.UserRestrictionItem
|
||||||
import com.bintianqi.owndroid.dpm.UserSessionMessage
|
import com.bintianqi.owndroid.dpm.UserSessionMessage
|
||||||
import com.bintianqi.owndroid.dpm.Users
|
import com.bintianqi.owndroid.dpm.Users
|
||||||
|
import com.bintianqi.owndroid.dpm.Wifi
|
||||||
import com.bintianqi.owndroid.dpm.WifiAuthKeypair
|
import com.bintianqi.owndroid.dpm.WifiAuthKeypair
|
||||||
import com.bintianqi.owndroid.dpm.WifiSecurityLevel
|
import com.bintianqi.owndroid.dpm.WifiSecurityLevel
|
||||||
import com.bintianqi.owndroid.dpm.WifiSsidPolicy
|
import com.bintianqi.owndroid.dpm.WifiSsidPolicy
|
||||||
@@ -236,8 +237,9 @@ fun Home(activity: FragmentActivity, vm: MyViewModel) {
|
|||||||
composable(route = "WipeData") { WipeData(navCtrl) }
|
composable(route = "WipeData") { WipeData(navCtrl) }
|
||||||
|
|
||||||
composable(route = "Network") { Network(navCtrl) }
|
composable(route = "Network") { Network(navCtrl) }
|
||||||
|
composable(route = "Wifi") { Wifi(navCtrl) }
|
||||||
composable(route = "NetworkOptions") { NetworkOptions(navCtrl) }
|
composable(route = "NetworkOptions") { NetworkOptions(navCtrl) }
|
||||||
composable(route = "AddWifi") { AddNetwork(navCtrl) }
|
composable(route = "UpdateNetwork") { UpdateNetwork(it.arguments!!, navCtrl) }
|
||||||
composable(route = "MinWifiSecurityLevel") { WifiSecurityLevel(navCtrl) }
|
composable(route = "MinWifiSecurityLevel") { WifiSecurityLevel(navCtrl) }
|
||||||
composable(route = "WifiSsidPolicy") { WifiSsidPolicy(navCtrl) }
|
composable(route = "WifiSsidPolicy") { WifiSsidPolicy(navCtrl) }
|
||||||
composable(route = "PrivateDNS") { PrivateDNS(navCtrl) }
|
composable(route = "PrivateDNS") { PrivateDNS(navCtrl) }
|
||||||
|
|||||||
@@ -122,3 +122,7 @@ fun parseTimestamp(timestamp: Long): String {
|
|||||||
|
|
||||||
val Long.humanReadableDate: String
|
val Long.humanReadableDate: String
|
||||||
get() = SimpleDateFormat("yyyy/MM/dd", Locale.getDefault()).format(Date(this))
|
get() = SimpleDateFormat("yyyy/MM/dd", Locale.getDefault()).format(Date(this))
|
||||||
|
|
||||||
|
fun Context.showOperationResultToast(success: Boolean) {
|
||||||
|
Toast.makeText(this, if(success) R.string.success else R.string.failed, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.bintianqi.owndroid.dpm
|
package com.bintianqi.owndroid.dpm
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.AlertDialog
|
import android.app.AlertDialog
|
||||||
import android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_OFF
|
import android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_OFF
|
||||||
@@ -29,6 +30,7 @@ import android.net.wifi.WifiConfiguration
|
|||||||
import android.net.wifi.WifiManager
|
import android.net.wifi.WifiManager
|
||||||
import android.net.wifi.WifiSsid
|
import android.net.wifi.WifiSsid
|
||||||
import android.os.Build.VERSION
|
import android.os.Build.VERSION
|
||||||
|
import android.os.Bundle
|
||||||
import android.telephony.TelephonyManager
|
import android.telephony.TelephonyManager
|
||||||
import android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID
|
import android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID
|
||||||
import android.telephony.data.ApnSetting.AUTH_TYPE_CHAP
|
import android.telephony.data.ApnSetting.AUTH_TYPE_CHAP
|
||||||
@@ -47,38 +49,54 @@ import android.telephony.data.ApnSetting.PROTOCOL_NON_IP
|
|||||||
import android.telephony.data.ApnSetting.PROTOCOL_PPP
|
import android.telephony.data.ApnSetting.PROTOCOL_PPP
|
||||||
import android.telephony.data.ApnSetting.PROTOCOL_UNSTRUCTURED
|
import android.telephony.data.ApnSetting.PROTOCOL_UNSTRUCTURED
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.animateContentSize
|
import androidx.compose.animation.animateContentSize
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
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.Delete
|
||||||
|
import androidx.compose.material.icons.outlined.LocationOn
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExposedDropdownMenuBox
|
import androidx.compose.material3.ExposedDropdownMenuBox
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.MaterialTheme.typography
|
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.Switch
|
import androidx.compose.material3.Switch
|
||||||
|
import androidx.compose.material3.Tab
|
||||||
|
import androidx.compose.material3.TabRow
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
|
import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
@@ -88,6 +106,7 @@ import androidx.compose.runtime.mutableLongStateOf
|
|||||||
import androidx.compose.runtime.mutableStateListOf
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
@@ -101,6 +120,7 @@ import androidx.compose.ui.text.input.ImeAction
|
|||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import com.bintianqi.owndroid.MyViewModel
|
import com.bintianqi.owndroid.MyViewModel
|
||||||
import com.bintianqi.owndroid.R
|
import com.bintianqi.owndroid.R
|
||||||
@@ -108,15 +128,21 @@ import com.bintianqi.owndroid.exportFile
|
|||||||
import com.bintianqi.owndroid.exportFilePath
|
import com.bintianqi.owndroid.exportFilePath
|
||||||
import com.bintianqi.owndroid.formatFileSize
|
import com.bintianqi.owndroid.formatFileSize
|
||||||
import com.bintianqi.owndroid.isExportingSecurityOrNetworkLogs
|
import com.bintianqi.owndroid.isExportingSecurityOrNetworkLogs
|
||||||
|
import com.bintianqi.owndroid.showOperationResultToast
|
||||||
import com.bintianqi.owndroid.ui.CheckBoxItem
|
import com.bintianqi.owndroid.ui.CheckBoxItem
|
||||||
import com.bintianqi.owndroid.ui.FunctionItem
|
import com.bintianqi.owndroid.ui.FunctionItem
|
||||||
import com.bintianqi.owndroid.ui.InfoCard
|
import com.bintianqi.owndroid.ui.InfoCard
|
||||||
import com.bintianqi.owndroid.ui.ListItem
|
import com.bintianqi.owndroid.ui.ListItem
|
||||||
import com.bintianqi.owndroid.ui.MyScaffold
|
import com.bintianqi.owndroid.ui.MyScaffold
|
||||||
|
import com.bintianqi.owndroid.ui.NavIcon
|
||||||
import com.bintianqi.owndroid.ui.RadioButtonItem
|
import com.bintianqi.owndroid.ui.RadioButtonItem
|
||||||
import com.bintianqi.owndroid.ui.SwitchItem
|
import com.bintianqi.owndroid.ui.SwitchItem
|
||||||
import com.bintianqi.owndroid.ui.UpOrDownTextFieldTrailingIconButton
|
import com.bintianqi.owndroid.ui.UpOrDownTextFieldTrailingIconButton
|
||||||
import com.bintianqi.owndroid.writeClipBoard
|
import com.bintianqi.owndroid.writeClipBoard
|
||||||
|
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||||
|
import com.google.accompanist.permissions.isGranted
|
||||||
|
import com.google.accompanist.permissions.rememberPermissionState
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.reflect.jvm.jvmErasure
|
import kotlin.reflect.jvm.jvmErasure
|
||||||
@@ -130,25 +156,15 @@ fun Network(navCtrl:NavHostController) {
|
|||||||
val profileOwner = context.isProfileOwner
|
val profileOwner = context.isProfileOwner
|
||||||
val sharedPref = context.getSharedPreferences("data", Context.MODE_PRIVATE)
|
val sharedPref = context.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||||||
val dhizuku = sharedPref.getBoolean("dhizuku", false)
|
val dhizuku = sharedPref.getBoolean("dhizuku", false)
|
||||||
var wifiMacDialog by remember { mutableStateOf(false) }
|
|
||||||
MyScaffold(R.string.network, 0.dp, navCtrl) {
|
MyScaffold(R.string.network, 0.dp, navCtrl) {
|
||||||
if(VERSION.SDK_INT >= 24 && (deviceOwner || dpm.isOrgProfile(receiver))) {
|
if(!dhizuku) FunctionItem(R.string.wifi, "", R.drawable.wifi_fill0) { navCtrl.navigate("Wifi") }
|
||||||
FunctionItem(R.string.wifi_mac_address, "", R.drawable.wifi_fill0) { wifiMacDialog = true }
|
|
||||||
}
|
|
||||||
if(VERSION.SDK_INT >= 30) {
|
if(VERSION.SDK_INT >= 30) {
|
||||||
FunctionItem(R.string.options, "", R.drawable.tune_fill0) { navCtrl.navigate("NetworkOptions") }
|
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") }
|
|
||||||
}
|
|
||||||
if(VERSION.SDK_INT >= 33 && (deviceOwner || dpm.isOrgProfile(receiver))) {
|
|
||||||
FunctionItem(R.string.wifi_ssid_policy, "", R.drawable.wifi_fill0) { navCtrl.navigate("WifiSsidPolicy") }
|
|
||||||
}
|
|
||||||
if(VERSION.SDK_INT >= 29 && deviceOwner) {
|
if(VERSION.SDK_INT >= 29 && deviceOwner) {
|
||||||
FunctionItem(R.string.private_dns, "", R.drawable.dns_fill0) { navCtrl.navigate("PrivateDNS") }
|
FunctionItem(R.string.private_dns, "", R.drawable.dns_fill0) { navCtrl.navigate("PrivateDNS") }
|
||||||
}
|
}
|
||||||
if(VERSION.SDK_INT >= 24 && (deviceOwner || profileOwner)) {
|
if(VERSION.SDK_INT >= 24) {
|
||||||
FunctionItem(R.string.always_on_vpn, "", R.drawable.vpn_key_fill0) { navCtrl.navigate("AlwaysOnVpn") }
|
FunctionItem(R.string.always_on_vpn, "", R.drawable.vpn_key_fill0) { navCtrl.navigate("AlwaysOnVpn") }
|
||||||
}
|
}
|
||||||
if(deviceOwner) {
|
if(deviceOwner) {
|
||||||
@@ -157,39 +173,16 @@ fun Network(navCtrl:NavHostController) {
|
|||||||
if(VERSION.SDK_INT >= 26 && !dhizuku && (deviceOwner || (profileOwner && dpm.isManagedProfile(receiver)))) {
|
if(VERSION.SDK_INT >= 26 && !dhizuku && (deviceOwner || (profileOwner && dpm.isManagedProfile(receiver)))) {
|
||||||
FunctionItem(R.string.network_logging, "", R.drawable.description_fill0) { navCtrl.navigate("NetworkLog") }
|
FunctionItem(R.string.network_logging, "", R.drawable.description_fill0) { navCtrl.navigate("NetworkLog") }
|
||||||
}
|
}
|
||||||
if(VERSION.SDK_INT >= 31 && (deviceOwner || profileOwner)) {
|
if(VERSION.SDK_INT >= 31) {
|
||||||
FunctionItem(R.string.wifi_auth_keypair, "", R.drawable.key_fill0) { navCtrl.navigate("WifiAuthKeypair") }
|
FunctionItem(R.string.wifi_auth_keypair, "", R.drawable.key_fill0) { navCtrl.navigate("WifiAuthKeypair") }
|
||||||
}
|
}
|
||||||
if(VERSION.SDK_INT >= 33 && (deviceOwner || profileOwner)) {
|
if(VERSION.SDK_INT >= 33) {
|
||||||
FunctionItem(R.string.preferential_network_service, "", R.drawable.globe_fill0) { navCtrl.navigate("PreferentialNetworkService") }
|
FunctionItem(R.string.preferential_network_service, "", R.drawable.globe_fill0) { navCtrl.navigate("PreferentialNetworkService") }
|
||||||
}
|
}
|
||||||
if(VERSION.SDK_INT >= 28 && deviceOwner) {
|
if(VERSION.SDK_INT >= 28 && deviceOwner) {
|
||||||
FunctionItem(R.string.override_apn_settings, "", R.drawable.cell_tower_fill0) { navCtrl.navigate("OverrideAPN") }
|
FunctionItem(R.string.override_apn_settings, "", R.drawable.cell_tower_fill0) { navCtrl.navigate("OverrideAPN") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(wifiMacDialog && VERSION.SDK_INT >= 24) {
|
|
||||||
val context = LocalContext.current
|
|
||||||
val dpm = context.getDPM()
|
|
||||||
val receiver = context.getReceiver()
|
|
||||||
AlertDialog(
|
|
||||||
onDismissRequest = { wifiMacDialog = false },
|
|
||||||
confirmButton = { TextButton(onClick = { wifiMacDialog = false }) { Text(stringResource(R.string.confirm)) } },
|
|
||||||
title = { Text(stringResource(R.string.wifi_mac_address)) },
|
|
||||||
text = {
|
|
||||||
val mac = dpm.getWifiMacAddress(receiver)
|
|
||||||
OutlinedTextField(
|
|
||||||
value = mac ?: stringResource(R.string.none),
|
|
||||||
onValueChange = {}, readOnly = true, modifier = Modifier.fillMaxWidth(), textStyle = typography.bodyLarge,
|
|
||||||
trailingIcon = {
|
|
||||||
if(mac != null) IconButton(onClick = { writeClipBoard(context, mac) }) {
|
|
||||||
Icon(painter = painterResource(R.drawable.content_copy_fill0), contentDescription = stringResource(R.string.copy))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -216,16 +209,265 @@ fun NetworkOptions(navCtrl: NavHostController) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun Wifi(navCtrl: NavHostController) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val coroutine = rememberCoroutineScope()
|
||||||
|
val pagerState = rememberPagerState { 3 }
|
||||||
|
var tabIndex by rememberSaveable { mutableIntStateOf(0) }
|
||||||
|
tabIndex = pagerState.currentPage
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopAppBar(
|
||||||
|
title = { Text(stringResource(R.string.wifi)) },
|
||||||
|
navigationIcon = { NavIcon { navCtrl.navigateUp() } }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { paddingValues ->
|
||||||
|
var wifiMacDialog by remember { mutableStateOf(false) }
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxSize().padding(paddingValues)
|
||||||
|
) {
|
||||||
|
TabRow(tabIndex) {
|
||||||
|
Tab(
|
||||||
|
selected = tabIndex == 0, onClick = { tabIndex = 0; coroutine.launch { pagerState.animateScrollToPage(tabIndex) } },
|
||||||
|
text = { Text(stringResource(R.string.overview)) }
|
||||||
|
)
|
||||||
|
Tab(
|
||||||
|
selected = tabIndex == 1, onClick = { tabIndex = 1; coroutine.launch { pagerState.animateScrollToPage(tabIndex) } },
|
||||||
|
text = { Text(stringResource(R.string.saved_networks)) }
|
||||||
|
)
|
||||||
|
Tab(
|
||||||
|
selected = tabIndex == 2, onClick = { tabIndex = 2; coroutine.launch { pagerState.animateScrollToPage(tabIndex) } },
|
||||||
|
text = { Text(stringResource(R.string.add_network)) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
HorizontalPager(state = pagerState, verticalAlignment = Alignment.Top) { page ->
|
||||||
|
if(page == 0) {
|
||||||
|
val wm = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||||
|
val deviceOwner = context.isDeviceOwner
|
||||||
|
val orgProfileOwner = context.getDPM().isOrgProfile(context.getReceiver())
|
||||||
|
@Suppress("DEPRECATION") Column(
|
||||||
|
modifier = Modifier.fillMaxSize().padding(top = 12.dp)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = { context.showOperationResultToast(wm.setWifiEnabled(true)) },
|
||||||
|
modifier = Modifier.padding(end = 8.dp)
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.enable))
|
||||||
|
}
|
||||||
|
Button(onClick = { context.showOperationResultToast(wm.setWifiEnabled(false)) }) {
|
||||||
|
Text(stringResource(R.string.disable))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp)
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = { context.showOperationResultToast(wm.disconnect()) },
|
||||||
|
modifier = Modifier.padding(end = 8.dp)
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.disconnect))
|
||||||
|
}
|
||||||
|
Button(onClick = { context.showOperationResultToast(wm.reconnect()) }) {
|
||||||
|
Text(stringResource(R.string.reconnect))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(VERSION.SDK_INT >= 24 && (deviceOwner || orgProfileOwner)) {
|
||||||
|
FunctionItem(R.string.wifi_mac_address, "", null) { wifiMacDialog = true }
|
||||||
|
}
|
||||||
|
if(VERSION.SDK_INT >= 33 && (deviceOwner || orgProfileOwner)) {
|
||||||
|
FunctionItem(R.string.min_wifi_security_level, "", null) { navCtrl.navigate("MinWifiSecurityLevel") }
|
||||||
|
FunctionItem(R.string.wifi_ssid_policy, "", null) { navCtrl.navigate("WifiSsidPolicy") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(page == 1) {
|
||||||
|
SavedNetworks(navCtrl)
|
||||||
|
} else {
|
||||||
|
AddNetwork()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(wifiMacDialog && VERSION.SDK_INT >= 24) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val dpm = context.getDPM()
|
||||||
|
val receiver = context.getReceiver()
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = { wifiMacDialog = false },
|
||||||
|
confirmButton = { TextButton(onClick = { wifiMacDialog = false }) { Text(stringResource(R.string.confirm)) } },
|
||||||
|
text = {
|
||||||
|
val mac = dpm.getWifiMacAddress(receiver)
|
||||||
|
OutlinedTextField(
|
||||||
|
value = mac ?: stringResource(R.string.none), label = { Text(stringResource(R.string.wifi_mac_address)) },
|
||||||
|
onValueChange = {}, readOnly = true, modifier = Modifier.fillMaxWidth(), textStyle = typography.bodyLarge,
|
||||||
|
trailingIcon = {
|
||||||
|
if(mac != null) IconButton(onClick = { writeClipBoard(context, mac) }) {
|
||||||
|
Icon(painter = painterResource(R.drawable.content_copy_fill0), contentDescription = stringResource(R.string.copy))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
@OptIn(ExperimentalPermissionsApi::class)
|
||||||
|
@Composable
|
||||||
|
private fun SavedNetworks(navCtrl: NavHostController) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val wm = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||||
|
val configuredNetworks = remember { mutableStateListOf<WifiConfiguration>() }
|
||||||
|
var networkDetailsDialog by remember { mutableIntStateOf(-1) } // -1:Hidden, 0+:Index of configuredNetworks
|
||||||
|
fun refresh() {
|
||||||
|
configuredNetworks.clear()
|
||||||
|
wm.configuredNetworks.forEach { network ->
|
||||||
|
if(configuredNetworks.none { it.networkId == network.networkId }) configuredNetworks += network
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LaunchedEffect(Unit) { refresh() }
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(start = 8.dp, end = 8.dp, bottom = 60.dp)
|
||||||
|
) {
|
||||||
|
val locationPermission = rememberPermissionState(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||||
|
val requestPermissionLauncher = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) {
|
||||||
|
if(it) refresh()
|
||||||
|
}
|
||||||
|
if(!locationPermission.status.isGranted) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(12.dp)
|
||||||
|
.clip(RoundedCornerShape(15))
|
||||||
|
.background(MaterialTheme.colorScheme.primaryContainer)
|
||||||
|
.clickable { requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION) }
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Outlined.LocationOn, contentDescription = null,
|
||||||
|
tint = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||||
|
modifier = Modifier.padding(start = 8.dp, end = 4.dp))
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.request_location_permission_description),
|
||||||
|
color = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||||
|
modifier = Modifier.padding(8.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
configuredNetworks.forEachIndexed { index, network ->
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(start = 8.dp, top = 8.dp)
|
||||||
|
) {
|
||||||
|
Text(text = network.SSID.removeSurrounding("\""), style = typography.titleLarge)
|
||||||
|
IconButton(onClick = { networkDetailsDialog = index }) {
|
||||||
|
Icon(painter = painterResource(R.drawable.more_horiz_fill0), contentDescription = null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(networkDetailsDialog != -1) AlertDialog(
|
||||||
|
text = {
|
||||||
|
val network = configuredNetworks[networkDetailsDialog]
|
||||||
|
val statusText = when(network.status) {
|
||||||
|
WifiConfiguration.Status.CURRENT -> R.string.current
|
||||||
|
WifiConfiguration.Status.DISABLED -> R.string.disabled
|
||||||
|
WifiConfiguration.Status.ENABLED -> R.string.enabled
|
||||||
|
else -> R.string.place_holder
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
Text(stringResource(R.string.network_id) + ": " + network.networkId.toString())
|
||||||
|
SelectionContainer {
|
||||||
|
Text("SSID: " + network.SSID)
|
||||||
|
if(network.BSSID != null) Text("BSSID: " + network.BSSID)
|
||||||
|
}
|
||||||
|
Text(stringResource(R.string.status) + ": " + stringResource(statusText))
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(top = 12.dp)
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
val success = wm.enableNetwork(network.networkId, false)
|
||||||
|
Toast.makeText(context, if(success) R.string.success else R.string.failed, Toast.LENGTH_SHORT).show()
|
||||||
|
networkDetailsDialog = -1
|
||||||
|
refresh()
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth(0.49F)
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.enable))
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
val success = wm.disableNetwork(network.networkId)
|
||||||
|
Toast.makeText(context, if(success) R.string.success else R.string.failed, Toast.LENGTH_SHORT).show()
|
||||||
|
networkDetailsDialog = -1
|
||||||
|
refresh()
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth(0.96F)
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.disable))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
networkDetailsDialog = -1
|
||||||
|
val dest = navCtrl.graph.findNode("UpdateNetwork")
|
||||||
|
if(dest != null)
|
||||||
|
navCtrl.navigate(dest.id, bundleOf("wifi_configuration" to network))
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.edit))
|
||||||
|
}
|
||||||
|
TextButton(
|
||||||
|
onClick = {
|
||||||
|
val success = wm.removeNetwork(network.networkId)
|
||||||
|
Toast.makeText(context, if(success) R.string.success else R.string.failed, Toast.LENGTH_SHORT).show()
|
||||||
|
networkDetailsDialog = -1
|
||||||
|
refresh()
|
||||||
|
},
|
||||||
|
colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.error),
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.remove))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = { networkDetailsDialog = -1 }) {
|
||||||
|
Text(stringResource(R.string.confirm))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onDismissRequest = { networkDetailsDialog = -1 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun UpdateNetwork(arguments: Bundle, navCtrl: NavHostController) {
|
||||||
|
MyScaffold(R.string.update_network, 0.dp, navCtrl, false) {
|
||||||
|
AddNetwork(arguments.getParcelable("wifi_configuration"), navCtrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun AddNetwork(navCtrl: NavHostController) {
|
private fun AddNetwork(wifiConfig: WifiConfiguration? = null, navCtrl: NavHostController? = null) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var resultDialog by remember { mutableStateOf(false) }
|
var resultDialog by remember { mutableStateOf(false) }
|
||||||
var createdNetworkId by remember { mutableIntStateOf(-1) }
|
var createdNetworkId by remember { mutableIntStateOf(-1) }
|
||||||
var createNetworkResult by remember {mutableIntStateOf(0)}
|
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 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 status by remember { mutableIntStateOf(WifiConfiguration.Status.ENABLED) }
|
||||||
var ssid by remember { mutableStateOf("") }
|
var ssid by remember { mutableStateOf("") }
|
||||||
var hiddenSsid by remember { mutableStateOf(false) }
|
var hiddenSsid by remember { mutableStateOf(false) }
|
||||||
@@ -240,16 +482,19 @@ fun AddNetwork(navCtrl: NavHostController) {
|
|||||||
var httpProxyHost by remember { mutableStateOf("") }
|
var httpProxyHost by remember { mutableStateOf("") }
|
||||||
var httpProxyPort by remember { mutableStateOf("") }
|
var httpProxyPort by remember { mutableStateOf("") }
|
||||||
var httpProxyExclList by remember { mutableStateOf("") }
|
var httpProxyExclList by remember { mutableStateOf("") }
|
||||||
MyScaffold(R.string.add_wifi, 8.dp, navCtrl) {
|
LaunchedEffect(Unit) {
|
||||||
OutlinedTextField(
|
if(wifiConfig != null) {
|
||||||
value = networkId, onValueChange = { networkId = it }, label = { Text(stringResource(R.string.network_id)) },
|
status = wifiConfig.status
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
if(wifiConfig.status == WifiConfiguration.Status.CURRENT) status = WifiConfiguration.Status.ENABLED
|
||||||
isError = networkId != "" && (try { networkId.toInt(); false } catch(_: NumberFormatException) { true }),
|
ssid = wifiConfig.SSID.removeSurrounding("\"")
|
||||||
modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp)
|
}
|
||||||
)
|
}
|
||||||
|
Column(
|
||||||
|
modifier = (if(wifiConfig == null) Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(bottom = 60.dp) else Modifier)
|
||||||
|
.padding(start = 8.dp, end = 8.dp, top = 12.dp)
|
||||||
|
) {
|
||||||
ExposedDropdownMenuBox(dropdownMenu == 1, { dropdownMenu = if(it) 1 else 0 }) {
|
ExposedDropdownMenuBox(dropdownMenu == 1, { dropdownMenu = if(it) 1 else 0 }) {
|
||||||
val statusText = when(status) {
|
val statusText = when(status) {
|
||||||
WifiConfiguration.Status.CURRENT -> R.string.current
|
|
||||||
WifiConfiguration.Status.DISABLED -> R.string.disabled
|
WifiConfiguration.Status.DISABLED -> R.string.disabled
|
||||||
WifiConfiguration.Status.ENABLED -> R.string.enabled
|
WifiConfiguration.Status.ENABLED -> R.string.enabled
|
||||||
else -> R.string.place_holder
|
else -> R.string.place_holder
|
||||||
@@ -261,13 +506,6 @@ fun AddNetwork(navCtrl: NavHostController) {
|
|||||||
modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth().padding(bottom = 16.dp)
|
modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth().padding(bottom = 16.dp)
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(dropdownMenu == 1, { dropdownMenu = 0 }) {
|
ExposedDropdownMenu(dropdownMenu == 1, { dropdownMenu = 0 }) {
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text(stringResource(R.string.current)) },
|
|
||||||
onClick = {
|
|
||||||
status = WifiConfiguration.Status.CURRENT
|
|
||||||
dropdownMenu = 0
|
|
||||||
}
|
|
||||||
)
|
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.disabled)) },
|
text = { Text(stringResource(R.string.disabled)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -413,7 +651,6 @@ fun AddNetwork(navCtrl: NavHostController) {
|
|||||||
val wm = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
val wm = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||||
try {
|
try {
|
||||||
val config = WifiConfiguration()
|
val config = WifiConfiguration()
|
||||||
if(networkId != "") config.networkId = networkId.toInt()
|
|
||||||
config.status = status
|
config.status = status
|
||||||
config.SSID = '"' + ssid + '"'
|
config.SSID = '"' + ssid + '"'
|
||||||
config.hiddenSSID = hiddenSsid
|
config.hiddenSSID = hiddenSsid
|
||||||
@@ -435,6 +672,10 @@ fun AddNetwork(navCtrl: NavHostController) {
|
|||||||
if(VERSION.SDK_INT >= 26 && useHttpProxy) {
|
if(VERSION.SDK_INT >= 26 && useHttpProxy) {
|
||||||
config.httpProxy = ProxyInfo.buildDirectProxy(httpProxyHost, httpProxyPort.toInt(), httpProxyExclList.lines())
|
config.httpProxy = ProxyInfo.buildDirectProxy(httpProxyHost, httpProxyPort.toInt(), httpProxyExclList.lines())
|
||||||
}
|
}
|
||||||
|
if(wifiConfig != null) {
|
||||||
|
config.networkId = wifiConfig.networkId
|
||||||
|
createdNetworkId = wm.updateNetwork(config)
|
||||||
|
} else {
|
||||||
if(VERSION.SDK_INT >= 31) {
|
if(VERSION.SDK_INT >= 31) {
|
||||||
val result = wm.addNetworkPrivileged(config)
|
val result = wm.addNetworkPrivileged(config)
|
||||||
createdNetworkId = result.networkId
|
createdNetworkId = result.networkId
|
||||||
@@ -442,6 +683,7 @@ fun AddNetwork(navCtrl: NavHostController) {
|
|||||||
} else {
|
} else {
|
||||||
createdNetworkId = wm.addNetwork(config)
|
createdNetworkId = wm.addNetwork(config)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
resultDialog = true
|
resultDialog = true
|
||||||
} catch(e: Exception) {
|
} catch(e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
@@ -454,7 +696,7 @@ fun AddNetwork(navCtrl: NavHostController) {
|
|||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp)
|
modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp)
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.add))
|
Text(stringResource(if(wifiConfig != null) R.string.update else R.string.add))
|
||||||
}
|
}
|
||||||
if(resultDialog) AlertDialog(
|
if(resultDialog) AlertDialog(
|
||||||
text = {
|
text = {
|
||||||
@@ -467,7 +709,12 @@ fun AddNetwork(navCtrl: NavHostController) {
|
|||||||
Text(stringResource(statusText) + "\n" + stringResource(R.string.network_id) + ": " + createdNetworkId)
|
Text(stringResource(statusText) + "\n" + stringResource(R.string.network_id) + ": " + createdNetworkId)
|
||||||
},
|
},
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
TextButton(onClick = { resultDialog = false }) {
|
TextButton(
|
||||||
|
onClick = {
|
||||||
|
resultDialog = false
|
||||||
|
if(createdNetworkId != -1) navCtrl?.navigateUp()
|
||||||
|
}
|
||||||
|
) {
|
||||||
Text(stringResource(R.string.confirm))
|
Text(stringResource(R.string.confirm))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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: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>
|
|
||||||
@@ -217,7 +217,12 @@
|
|||||||
<string name="network">Сеть</string>
|
<string name="network">Сеть</string>
|
||||||
<string name="wifi_mac_address">MAC-адрес Wi-Fi</string>
|
<string name="wifi_mac_address">MAC-адрес Wi-Fi</string>
|
||||||
<!--TODO-->
|
<!--TODO-->
|
||||||
<string name="add_wifi">Add Wi-Fi</string>
|
<string name="disconnect">Disconnect</string>
|
||||||
|
<string name="reconnect">Reconnect</string>
|
||||||
|
<string name="saved_networks">Saved networks</string>
|
||||||
|
<string name="request_location_permission_description">This app need location permission to get saved networks, your geographic location will not be read.\nClick to request the permission.</string>
|
||||||
|
<string name="add_network">Add network</string>
|
||||||
|
<string name="update_network">Update network</string>
|
||||||
<string name="current">Current</string>
|
<string name="current">Current</string>
|
||||||
<string name="hidden_ssid">Hidden SSID</string>
|
<string name="hidden_ssid">Hidden SSID</string>
|
||||||
<string name="ip_settings">IP settings</string>
|
<string name="ip_settings">IP settings</string>
|
||||||
|
|||||||
@@ -218,7 +218,12 @@
|
|||||||
<string name="network">Ağ</string>
|
<string name="network">Ağ</string>
|
||||||
<string name="wifi_mac_address">Wi-Fi MAC adresi</string>
|
<string name="wifi_mac_address">Wi-Fi MAC adresi</string>
|
||||||
<!--TODO-->
|
<!--TODO-->
|
||||||
<string name="add_wifi">Add Wi-Fi</string>
|
<string name="disconnect">Disconnect</string>
|
||||||
|
<string name="reconnect">Reconnect</string>
|
||||||
|
<string name="saved_networks">Saved networks</string>
|
||||||
|
<string name="request_location_permission_description">This app need location permission to get saved networks, your geographic location will not be read.\nClick to request the permission.</string>
|
||||||
|
<string name="add_network">Add network</string>
|
||||||
|
<string name="update_network">Update network</string>
|
||||||
<string name="current">Current</string>
|
<string name="current">Current</string>
|
||||||
<string name="hidden_ssid">Hidden SSID</string>
|
<string name="hidden_ssid">Hidden SSID</string>
|
||||||
<string name="ip_settings">IP settings</string>
|
<string name="ip_settings">IP settings</string>
|
||||||
|
|||||||
@@ -210,7 +210,12 @@
|
|||||||
<!--Network-->
|
<!--Network-->
|
||||||
<string name="network">网络</string>
|
<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="disconnect">断开连接</string>
|
||||||
|
<string name="reconnect">重新连接</string>
|
||||||
|
<string name="saved_networks">已保存的网络</string>
|
||||||
|
<string name="request_location_permission_description">此app需要定位权限以获取已保存的网络,你的地理位置将不会被读取。点击以请求权限</string>
|
||||||
|
<string name="add_network">添加网络</string>
|
||||||
|
<string name="update_network">更新网络</string>
|
||||||
<string name="current">当前</string>
|
<string name="current">当前</string>
|
||||||
<string name="hidden_ssid">隐藏的SSID</string>
|
<string name="hidden_ssid">隐藏的SSID</string>
|
||||||
<string name="ip_settings">IP设置</string>
|
<string name="ip_settings">IP设置</string>
|
||||||
|
|||||||
@@ -67,6 +67,8 @@
|
|||||||
<string name="api" translatable="false">API</string>
|
<string name="api" translatable="false">API</string>
|
||||||
<string name="error">Error</string>
|
<string name="error">Error</string>
|
||||||
<string name="status">Status</string>
|
<string name="status">Status</string>
|
||||||
|
<string name="edit">Edit</string>
|
||||||
|
<string name="overview">Overview</string>
|
||||||
|
|
||||||
<!--Permissions-->
|
<!--Permissions-->
|
||||||
<string name="click_to_activate">Click to activate</string>
|
<string name="click_to_activate">Click to activate</string>
|
||||||
@@ -221,8 +223,14 @@
|
|||||||
|
|
||||||
<!--Network-->
|
<!--Network-->
|
||||||
<string name="network">Network</string>
|
<string name="network">Network</string>
|
||||||
<string name="wifi_mac_address">Wi-Fi Mac address</string>
|
<string name="wifi_mac_address">Wi-Fi MAC address</string>
|
||||||
<string name="add_wifi">Add Wi-Fi</string>
|
<string name="wifi" translatable="false">Wi-Fi</string>
|
||||||
|
<string name="disconnect">Disconnect</string>
|
||||||
|
<string name="reconnect">Reconnect</string>
|
||||||
|
<string name="saved_networks">Saved networks</string>
|
||||||
|
<string name="request_location_permission_description">This app need location permission to get saved networks, your geographic location will not be read.\nClick to request the permission.</string>
|
||||||
|
<string name="add_network">Add network</string>
|
||||||
|
<string name="update_network">Update network</string>
|
||||||
<string name="current">Current</string>
|
<string name="current">Current</string>
|
||||||
<string name="hidden_ssid">Hidden SSID</string>
|
<string name="hidden_ssid">Hidden SSID</string>
|
||||||
<string name="ip_settings">IP settings</string>
|
<string name="ip_settings">IP settings</string>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ kotlin = "2.0.21"
|
|||||||
navigation-compose = "2.8.5"
|
navigation-compose = "2.8.5"
|
||||||
composeBom = "2024.12.01"
|
composeBom = "2024.12.01"
|
||||||
accompanist-drawablepainter = "0.35.0-alpha"
|
accompanist-drawablepainter = "0.35.0-alpha"
|
||||||
|
accompanist-permissions = "0.37.0"
|
||||||
shizuku = "13.1.5"
|
shizuku = "13.1.5"
|
||||||
biometric = "1.2.0-alpha05"
|
biometric = "1.2.0-alpha05"
|
||||||
fragment = "1.8.5"
|
fragment = "1.8.5"
|
||||||
@@ -19,6 +20,7 @@ androidx-material3 = { module = "androidx.compose.material3:material3" }
|
|||||||
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigation-compose" }
|
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigation-compose" }
|
||||||
|
|
||||||
accompanist-drawablepainter = { module = "com.google.accompanist:accompanist-drawablepainter", version.ref = "accompanist-drawablepainter" }
|
accompanist-drawablepainter = { module = "com.google.accompanist:accompanist-drawablepainter", version.ref = "accompanist-drawablepainter" }
|
||||||
|
accompanist-permissions = { group = "com.google.accompanist", name = "accompanist-permissions", version.ref = "accompanist-permissions" }
|
||||||
androidx-biometric = { group = "androidx.biometric", name = "biometric", version.ref = "biometric" }
|
androidx-biometric = { group = "androidx.biometric", name = "biometric", version.ref = "biometric" }
|
||||||
|
|
||||||
shizuku-provider = { module = "dev.rikka.shizuku:provider", version.ref = "shizuku" }
|
shizuku-provider = { module = "dev.rikka.shizuku:provider", version.ref = "shizuku" }
|
||||||
|
|||||||
Reference in New Issue
Block a user