Improve location permission request and description

This commit is contained in:
iKirby 2024-02-19 22:58:51 +08:00 committed by 世界
parent a35318ded2
commit a4dbcd344a
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
3 changed files with 93 additions and 10 deletions

View file

@ -5,7 +5,6 @@ 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
@ -27,6 +26,7 @@ import io.nekohasekai.sfa.constant.Alert
import io.nekohasekai.sfa.constant.Status import io.nekohasekai.sfa.constant.Status
import io.nekohasekai.sfa.database.ProfileManager import io.nekohasekai.sfa.database.ProfileManager
import io.nekohasekai.sfa.database.Settings import io.nekohasekai.sfa.database.Settings
import io.nekohasekai.sfa.ktx.hasPermission
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -174,10 +174,7 @@ class BoxService(
} else { } else {
android.Manifest.permission.ACCESS_BACKGROUND_LOCATION android.Manifest.permission.ACCESS_BACKGROUND_LOCATION
} }
if (ContextCompat.checkSelfPermission( if (!service.hasPermission(wifiPermission)) {
service, wifiPermission
) != PackageManager.PERMISSION_GRANTED
) {
newService.close() newService.close()
stopAndAlert(Alert.RequestLocationPermission) stopAndAlert(Alert.RequestLocationPermission)
return return

View file

@ -0,0 +1,9 @@
package io.nekohasekai.sfa.ktx
import android.content.Context
import android.content.pm.PackageManager
import androidx.core.content.ContextCompat
fun Context.hasPermission(permission: String): Boolean {
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
}

View file

@ -9,8 +9,10 @@ import android.net.VpnService
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Process import android.os.Process
import android.text.Html
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.annotation.RequiresApi
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
@ -34,6 +36,7 @@ import io.nekohasekai.sfa.database.Settings
import io.nekohasekai.sfa.database.TypedProfile import io.nekohasekai.sfa.database.TypedProfile
import io.nekohasekai.sfa.databinding.ActivityMainBinding import io.nekohasekai.sfa.databinding.ActivityMainBinding
import io.nekohasekai.sfa.ktx.errorDialogBuilder import io.nekohasekai.sfa.ktx.errorDialogBuilder
import io.nekohasekai.sfa.ktx.hasPermission
import io.nekohasekai.sfa.ui.profile.NewProfileActivity import io.nekohasekai.sfa.ui.profile.NewProfileActivity
import io.nekohasekai.sfa.ui.shared.AbstractActivity import io.nekohasekai.sfa.ui.shared.AbstractActivity
import io.nekohasekai.sfa.vendor.Vendor import io.nekohasekai.sfa.vendor.Vendor
@ -220,7 +223,26 @@ class MainActivity : AbstractActivity(), ServiceConnection.Callback {
} }
private val locationPermissionLauncher = private val locationPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) {} registerForActivityResult(ActivityResultContracts.RequestPermission()) {
if (it) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
requestBackgroundLocationPermission()
} else {
startService()
}
} else {
showPermissionDeniedDescription()
}
}
private val backgroundLocationPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
if (it) {
startService()
} else {
showPermissionDeniedDescription()
}
}
private val prepareLauncher = registerForActivityResult(PrepareService()) { private val prepareLauncher = registerForActivityResult(PrepareService()) {
if (it) { if (it) {
@ -305,24 +327,58 @@ class MainActivity : AbstractActivity(), ServiceConnection.Callback {
} }
private fun requestLocationPermission() { private fun requestLocationPermission() {
if (!hasPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
requestFineLocationPermission()
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
requestBackgroundLocationPermission()
}
}
private fun requestFineLocationPermission() {
val message = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(
getString(R.string.location_permission_description),
Html.FROM_HTML_MODE_LEGACY
)
} else {
@Suppress("DEPRECATION")
Html.fromHtml(getString(R.string.location_permission_description))
}
MaterialAlertDialogBuilder(this) MaterialAlertDialogBuilder(this)
.setTitle(R.string.location_permission_title) .setTitle(R.string.location_permission_title)
.setMessage(R.string.location_permission_description) .setMessage(message)
.setPositiveButton(R.string.ok) { _, _ -> .setPositiveButton(R.string.ok) { _, _ ->
requestLocationPermission0() requestFineLocationPermission0()
} }
.setCancelable(false) .setCancelable(false)
.show() .show()
} }
private fun requestLocationPermission0() { private fun requestFineLocationPermission0() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
locationPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION) locationPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
} else { } else {
openPermissionSettings() openPermissionSettings()
} }
} }
@RequiresApi(Build.VERSION_CODES.Q)
private fun requestBackgroundLocationPermission() {
MaterialAlertDialogBuilder(this)
.setTitle(R.string.location_permission_title)
.setMessage(
Html.fromHtml(
getString(R.string.location_permission_background_description),
Html.FROM_HTML_MODE_LEGACY
)
)
.setPositiveButton(R.string.ok) { _, _ ->
backgroundLocationPermissionLauncher.launch(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
}
.setCancelable(false)
.show()
}
private fun openPermissionSettings() { private fun openPermissionSettings() {
if (!getSystemProperty("ro.miui.ui.version.name").isNullOrBlank()) { if (!getSystemProperty("ro.miui.ui.version.name").isNullOrBlank()) {
val intent = Intent("miui.intent.action.APP_PERM_EDITOR") val intent = Intent("miui.intent.action.APP_PERM_EDITOR")
@ -344,6 +400,27 @@ class MainActivity : AbstractActivity(), ServiceConnection.Callback {
} }
} }
private fun showPermissionDeniedDescription() {
val message = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(
getString(R.string.location_permission_denied_description),
Html.FROM_HTML_MODE_LEGACY
)
} else {
@Suppress("DEPRECATION")
Html.fromHtml(getString(R.string.location_permission_denied_description))
}
MaterialAlertDialogBuilder(this)
.setTitle(R.string.location_permission_title)
.setMessage(message)
.setPositiveButton(R.string.ok, null)
.setNeutralButton(R.string.open_settings) { _, _ ->
openPermissionSettings()
}
.setCancelable(false)
.show()
}
@SuppressLint("PrivateApi") @SuppressLint("PrivateApi")
fun getSystemProperty(key: String?): String? { fun getSystemProperty(key: String?): String? {
try { try {