Fix WIFI state permission again

This commit is contained in:
世界
2024-02-16 14:35:11 +08:00
parent 4504447a2c
commit f8ebfaabe2
5 changed files with 89 additions and 38 deletions

View File

@@ -12,7 +12,7 @@
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission <uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES" android:name="android.permission.QUERY_ALL_PACKAGES"
@@ -144,7 +144,7 @@
<service <service
android:name=".bg.VPNService" android:name=".bg.VPNService"
android:exported="false" android:exported="false"
android:foregroundServiceType="specialUse|location" android:foregroundServiceType="specialUse"
android:permission="android.permission.BIND_VPN_SERVICE"> android:permission="android.permission.BIND_VPN_SERVICE">
<intent-filter> <intent-filter>
<action android:name="android.net.VpnService" /> <action android:name="android.net.VpnService" />
@@ -156,7 +156,7 @@
<service <service
android:name=".bg.ProxyService" android:name=".bg.ProxyService"
android:exported="false" android:exported="false"
android:foregroundServiceType="specialUse|location"> android:foregroundServiceType="specialUse">
<property <property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE" android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="proxy" /> android:value="proxy" />

View File

@@ -5,6 +5,7 @@ import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.content.pm.PackageManager
import android.os.Build import android.os.Build
import android.os.IBinder import android.os.IBinder
import android.os.ParcelFileDescriptor import android.os.ParcelFileDescriptor
@@ -169,6 +170,23 @@ class BoxService(
} }
newService.start() newService.start()
if (newService.needWIFIState()) {
val wifiPermission = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
android.Manifest.permission.ACCESS_FINE_LOCATION
} else {
android.Manifest.permission.ACCESS_BACKGROUND_LOCATION
}
if (ContextCompat.checkSelfPermission(
service, wifiPermission
) != PackageManager.PERMISSION_GRANTED
) {
newService.close()
stopAndAlert(Alert.RequestLocationPermission)
return
}
}
boxService = newService boxService = newService
commandServer?.setService(boxService) commandServer?.setService(boxService)
status.postValue(Status.Started) status.postValue(Status.Started)

View File

@@ -3,6 +3,7 @@ package io.nekohasekai.sfa.constant
enum class Alert { enum class Alert {
RequestVPNPermission, RequestVPNPermission,
RequestNotificationPermission, RequestNotificationPermission,
RequestLocationPermission,
EmptyConfiguration, EmptyConfiguration,
StartCommandServer, StartCommandServer,
CreateService, CreateService,

View File

@@ -4,12 +4,13 @@ import android.Manifest
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.net.Uri
import android.net.VpnService import android.net.VpnService
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Process
import androidx.activity.result.contract.ActivityResultContract import androidx.activity.result.contract.ActivityResultContract
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@@ -188,38 +189,12 @@ class MainActivity : AbstractActivity(), ServiceConnection.Callback {
} }
@SuppressLint("NewApi") @SuppressLint("NewApi")
fun startService(skipRequestLocation: Boolean = false) { fun startService() {
if (!ServiceNotification.checkPermission()) { if (!ServiceNotification.checkPermission()) {
notificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) notificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
return return
} }
// MIUI always return false for shouldShowRequestPermissionRationale
if (!skipRequestLocation && ContextCompat.checkSelfPermission(
this, Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
if (!ActivityCompat.shouldShowRequestPermissionRationale(
this, Manifest.permission.ACCESS_FINE_LOCATION
)
) {
MaterialAlertDialogBuilder(this)
.setTitle(R.string.location_permission_title)
.setMessage(R.string.location_permission_description)
.setPositiveButton(R.string.ok) { _, _ ->
locationPermissionLauncher.launch(
arrayOf(
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
)
)
}
.setCancelable(false)
.show()
return
}
}
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
if (Settings.rebuildServiceMode()) { if (Settings.rebuildServiceMode()) {
reconnect() reconnect()
@@ -246,11 +221,8 @@ class MainActivity : AbstractActivity(), ServiceConnection.Callback {
} }
} }
private val locationPermissionLauncher = registerForActivityResult( private val locationPermissionLauncher =
ActivityResultContracts.RequestMultiplePermissions() registerForActivityResult(ActivityResultContracts.RequestPermission()) {}
) {
startService(true)
}
private val prepareLauncher = registerForActivityResult(PrepareService()) { private val prepareLauncher = registerForActivityResult(PrepareService()) {
if (it) { if (it) {
@@ -290,6 +262,14 @@ class MainActivity : AbstractActivity(), ServiceConnection.Callback {
} }
override fun onServiceAlert(type: Alert, message: String?) { override fun onServiceAlert(type: Alert, message: String?) {
when (type) {
Alert.RequestLocationPermission -> {
return requestLocationPermission()
}
else -> {}
}
val builder = MaterialAlertDialogBuilder(this) val builder = MaterialAlertDialogBuilder(this)
builder.setPositiveButton(R.string.ok, null) builder.setPositiveButton(R.string.ok, null)
when (type) { when (type) {
@@ -320,10 +300,62 @@ class MainActivity : AbstractActivity(), ServiceConnection.Callback {
builder.setMessage(message) builder.setMessage(message)
} }
else -> {}
} }
builder.show() builder.show()
} }
private fun requestLocationPermission() {
MaterialAlertDialogBuilder(this)
.setTitle(R.string.location_permission_title)
.setMessage(R.string.location_permission_description)
.setPositiveButton(R.string.ok) { _, _ ->
requestLocationPermission0()
}
.setCancelable(false)
.show()
}
private fun requestLocationPermission0() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
locationPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
} else {
openPermissionSettings()
}
}
private fun openPermissionSettings() {
if (!getSystemProperty("ro.miui.ui.version.name").isNullOrBlank()) {
val intent = Intent("miui.intent.action.APP_PERM_EDITOR")
intent.putExtra("extra_package_uid", Process.myUid())
intent.putExtra("extra_pkgname", packageName)
try {
startActivity(intent)
return
} catch (ignored: Exception) {
}
}
try {
val intent = Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
intent.data = Uri.parse("package:$packageName")
startActivity(intent)
} catch (e: Exception) {
errorDialogBuilder(e).show()
}
}
@SuppressLint("PrivateApi")
fun getSystemProperty(key: String?): String? {
try {
return Class.forName("android.os.SystemProperties").getMethod("get", String::class.java)
.invoke(null, key) as String
} catch (ignored: Exception) {
}
return null
}
private var paused = false private var paused = false
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()

View File

@@ -146,6 +146,6 @@
<string name="other_methods">Other methods</string> <string name="other_methods">Other methods</string>
<string name="action_start">Start</string> <string name="action_start">Start</string>
<string name="location_permission_title">Location permission</string> <string name="location_permission_title">Location permission</string>
<string name="location_permission_description">sing-box uses the location permission to provide `wifi_ssid` and `wifi_bssid` routing rule entries, deny it if you don\'t need this feature.</string> <string name="location_permission_description">sing-box uses the **background location** permission to implement the `wifi_ssid` and `wifi_bssid` routing rule items that **you are using**.</string>
</resources> </resources>