From a4dbcd344abc7e3f73f1fbc2b9c7c0dd3def4340 Mon Sep 17 00:00:00 2001 From: iKirby <6316115+iKirby@users.noreply.github.com> Date: Mon, 19 Feb 2024 22:58:51 +0800 Subject: [PATCH] Improve location permission request and description --- .../java/io/nekohasekai/sfa/bg/BoxService.kt | 7 +- .../java/io/nekohasekai/sfa/ktx/Context.kt | 9 ++ .../io/nekohasekai/sfa/ui/MainActivity.kt | 87 +++++++++++++++++-- 3 files changed, 93 insertions(+), 10 deletions(-) create mode 100644 app/src/main/java/io/nekohasekai/sfa/ktx/Context.kt diff --git a/app/src/main/java/io/nekohasekai/sfa/bg/BoxService.kt b/app/src/main/java/io/nekohasekai/sfa/bg/BoxService.kt index 03cbbc1..5176a51 100644 --- a/app/src/main/java/io/nekohasekai/sfa/bg/BoxService.kt +++ b/app/src/main/java/io/nekohasekai/sfa/bg/BoxService.kt @@ -5,7 +5,6 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter -import android.content.pm.PackageManager import android.os.Build import android.os.IBinder import android.os.ParcelFileDescriptor @@ -27,6 +26,7 @@ import io.nekohasekai.sfa.constant.Alert import io.nekohasekai.sfa.constant.Status import io.nekohasekai.sfa.database.ProfileManager import io.nekohasekai.sfa.database.Settings +import io.nekohasekai.sfa.ktx.hasPermission import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay @@ -174,10 +174,7 @@ class BoxService( } else { android.Manifest.permission.ACCESS_BACKGROUND_LOCATION } - if (ContextCompat.checkSelfPermission( - service, wifiPermission - ) != PackageManager.PERMISSION_GRANTED - ) { + if (!service.hasPermission(wifiPermission)) { newService.close() stopAndAlert(Alert.RequestLocationPermission) return diff --git a/app/src/main/java/io/nekohasekai/sfa/ktx/Context.kt b/app/src/main/java/io/nekohasekai/sfa/ktx/Context.kt new file mode 100644 index 0000000..ac31b70 --- /dev/null +++ b/app/src/main/java/io/nekohasekai/sfa/ktx/Context.kt @@ -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 +} diff --git a/app/src/main/java/io/nekohasekai/sfa/ui/MainActivity.kt b/app/src/main/java/io/nekohasekai/sfa/ui/MainActivity.kt index dee84c1..9ea0680 100644 --- a/app/src/main/java/io/nekohasekai/sfa/ui/MainActivity.kt +++ b/app/src/main/java/io/nekohasekai/sfa/ui/MainActivity.kt @@ -9,8 +9,10 @@ import android.net.VpnService import android.os.Build import android.os.Bundle import android.os.Process +import android.text.Html import androidx.activity.result.contract.ActivityResultContract import androidx.activity.result.contract.ActivityResultContracts +import androidx.annotation.RequiresApi import androidx.core.content.ContextCompat import androidx.lifecycle.MutableLiveData import androidx.lifecycle.lifecycleScope @@ -34,6 +36,7 @@ import io.nekohasekai.sfa.database.Settings import io.nekohasekai.sfa.database.TypedProfile import io.nekohasekai.sfa.databinding.ActivityMainBinding import io.nekohasekai.sfa.ktx.errorDialogBuilder +import io.nekohasekai.sfa.ktx.hasPermission import io.nekohasekai.sfa.ui.profile.NewProfileActivity import io.nekohasekai.sfa.ui.shared.AbstractActivity import io.nekohasekai.sfa.vendor.Vendor @@ -220,7 +223,26 @@ class MainActivity : AbstractActivity(), ServiceConnection.Callback { } 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()) { if (it) { @@ -305,24 +327,58 @@ class MainActivity : AbstractActivity(), ServiceConnection.Callback { } 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) .setTitle(R.string.location_permission_title) - .setMessage(R.string.location_permission_description) + .setMessage(message) .setPositiveButton(R.string.ok) { _, _ -> - requestLocationPermission0() + requestFineLocationPermission0() } .setCancelable(false) .show() } - private fun requestLocationPermission0() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { + private fun requestFineLocationPermission0() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { locationPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION) } else { 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() { if (!getSystemProperty("ro.miui.ui.version.name").isNullOrBlank()) { 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") fun getSystemProperty(key: String?): String? { try {