kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
improve location permission check
rodzic
9b45ba84f7
commit
6184e9f30c
|
@ -189,7 +189,7 @@ class MainActivity : BaseActivity(), Logging,
|
||||||
|
|
||||||
/** Get the minimum permissions our app needs to run correctly
|
/** Get the minimum permissions our app needs to run correctly
|
||||||
*/
|
*/
|
||||||
private fun getMinimumPermissions(): List<String> {
|
private fun getMinimumPermissions(): Array<String> {
|
||||||
val perms = mutableListOf(
|
val perms = mutableListOf(
|
||||||
Manifest.permission.WAKE_LOCK
|
Manifest.permission.WAKE_LOCK
|
||||||
|
|
||||||
|
@ -218,18 +218,12 @@ class MainActivity : BaseActivity(), Logging,
|
||||||
/** Ask the user to grant Bluetooth scan/discovery permission */
|
/** Ask the user to grant Bluetooth scan/discovery permission */
|
||||||
fun requestScanPermission() = requestPermission(getScanPermissions(), true)
|
fun requestScanPermission() = requestPermission(getScanPermissions(), true)
|
||||||
|
|
||||||
/** Ask the user to grant foreground location permission */
|
|
||||||
fun requestLocationPermission() = requestPermission(getLocationPermissions())
|
|
||||||
|
|
||||||
/** Ask the user to grant background location permission */
|
|
||||||
fun requestBackgroundPermission() = requestPermission(getBackgroundPermissions())
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a localized string warning user about missing permissions. Or null if everything is find
|
* @return a localized string warning user about missing permissions. Or null if everything is find
|
||||||
*/
|
*/
|
||||||
@SuppressLint("InlinedApi")
|
@SuppressLint("InlinedApi")
|
||||||
fun getMissingMessage(
|
fun getMissingMessage(
|
||||||
missingPerms: List<String> = getMinimumPermissions()
|
missingPerms: Array<String> = getMinimumPermissions()
|
||||||
): String? {
|
): String? {
|
||||||
val renamedPermissions = mapOf(
|
val renamedPermissions = mapOf(
|
||||||
// Older versions of android don't know about these permissions - ignore failure to grant
|
// Older versions of android don't know about these permissions - ignore failure to grant
|
||||||
|
@ -262,7 +256,7 @@ class MainActivity : BaseActivity(), Logging,
|
||||||
* @return true if we already have the needed permissions
|
* @return true if we already have the needed permissions
|
||||||
*/
|
*/
|
||||||
private fun requestPermission(
|
private fun requestPermission(
|
||||||
missingPerms: List<String> = getMinimumPermissions(),
|
missingPerms: Array<String> = getMinimumPermissions(),
|
||||||
shouldShowDialog: Boolean = false
|
shouldShowDialog: Boolean = false
|
||||||
): Boolean =
|
): Boolean =
|
||||||
if (missingPerms.isNotEmpty()) {
|
if (missingPerms.isNotEmpty()) {
|
||||||
|
@ -275,7 +269,7 @@ class MainActivity : BaseActivity(), Logging,
|
||||||
// Ask for all the missing perms
|
// Ask for all the missing perms
|
||||||
ActivityCompat.requestPermissions(
|
ActivityCompat.requestPermissions(
|
||||||
this,
|
this,
|
||||||
missingPerms.toTypedArray(),
|
missingPerms,
|
||||||
DID_REQUEST_PERM
|
DID_REQUEST_PERM
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,17 +47,17 @@ fun Context.hasGps(): Boolean =
|
||||||
/**
|
/**
|
||||||
* return a list of the permissions we don't have
|
* return a list of the permissions we don't have
|
||||||
*/
|
*/
|
||||||
fun Context.getMissingPermissions(perms: List<String>) = perms.filter {
|
fun Context.getMissingPermissions(perms: List<String>): Array<String> = perms.filter {
|
||||||
ContextCompat.checkSelfPermission(
|
ContextCompat.checkSelfPermission(
|
||||||
this,
|
this,
|
||||||
it
|
it
|
||||||
) != PackageManager.PERMISSION_GRANTED
|
) != PackageManager.PERMISSION_GRANTED
|
||||||
}
|
}.toTypedArray()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bluetooth connect permissions (or empty if we already have what we need)
|
* Bluetooth connect permissions (or empty if we already have what we need)
|
||||||
*/
|
*/
|
||||||
fun Context.getConnectPermissions(): List<String> {
|
fun Context.getConnectPermissions(): Array<String> {
|
||||||
val perms = mutableListOf<String>()
|
val perms = mutableListOf<String>()
|
||||||
|
|
||||||
/* TODO - wait for targetSdkVersion 31
|
/* TODO - wait for targetSdkVersion 31
|
||||||
|
@ -76,7 +76,7 @@ fun Context.hasConnectPermission() = getConnectPermissions().isEmpty()
|
||||||
/**
|
/**
|
||||||
* Bluetooth scan/discovery permissions (or empty if we already have what we need)
|
* Bluetooth scan/discovery permissions (or empty if we already have what we need)
|
||||||
*/
|
*/
|
||||||
fun Context.getScanPermissions(): List<String> {
|
fun Context.getScanPermissions(): Array<String> {
|
||||||
val perms = mutableListOf<String>()
|
val perms = mutableListOf<String>()
|
||||||
|
|
||||||
/* TODO - wait for targetSdkVersion 31
|
/* TODO - wait for targetSdkVersion 31
|
||||||
|
@ -101,7 +101,7 @@ fun Context.hasScanPermission() = getScanPermissions().isEmpty()
|
||||||
/**
|
/**
|
||||||
* Camera permission (or empty if we already have what we need)
|
* Camera permission (or empty if we already have what we need)
|
||||||
*/
|
*/
|
||||||
fun Context.getCameraPermissions(): List<String> {
|
fun Context.getCameraPermissions(): Array<String> {
|
||||||
val perms = mutableListOf(Manifest.permission.CAMERA)
|
val perms = mutableListOf(Manifest.permission.CAMERA)
|
||||||
|
|
||||||
return getMissingPermissions(perms)
|
return getMissingPermissions(perms)
|
||||||
|
@ -113,7 +113,7 @@ fun Context.hasCameraPermission() = getCameraPermissions().isEmpty()
|
||||||
/**
|
/**
|
||||||
* Location permission (or empty if we already have what we need)
|
* Location permission (or empty if we already have what we need)
|
||||||
*/
|
*/
|
||||||
fun Context.getLocationPermissions(): List<String> {
|
fun Context.getLocationPermissions(): Array<String> {
|
||||||
val perms = mutableListOf(Manifest.permission.ACCESS_FINE_LOCATION)
|
val perms = mutableListOf(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||||
|
|
||||||
return getMissingPermissions(perms)
|
return getMissingPermissions(perms)
|
||||||
|
@ -125,8 +125,8 @@ fun Context.hasLocationPermission() = getLocationPermissions().isEmpty()
|
||||||
/**
|
/**
|
||||||
* A list of missing background location permissions (or empty if we already have what we need)
|
* A list of missing background location permissions (or empty if we already have what we need)
|
||||||
*/
|
*/
|
||||||
fun Context.getBackgroundPermissions(): List<String> {
|
fun Context.getBackgroundPermissions(): Array<String> {
|
||||||
val perms = mutableListOf<String>()
|
val perms = mutableListOf(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 29) // only added later
|
if (Build.VERSION.SDK_INT >= 29) // only added later
|
||||||
perms.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
|
perms.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.geeksville.mesh.ui
|
package com.geeksville.mesh.ui
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.ColorMatrix
|
import android.graphics.ColorMatrix
|
||||||
|
@ -25,6 +24,7 @@ import com.geeksville.mesh.AppOnlyProtos
|
||||||
import com.geeksville.mesh.ChannelProtos
|
import com.geeksville.mesh.ChannelProtos
|
||||||
import com.geeksville.mesh.ConfigProtos
|
import com.geeksville.mesh.ConfigProtos
|
||||||
import com.geeksville.mesh.R
|
import com.geeksville.mesh.R
|
||||||
|
import com.geeksville.mesh.android.getCameraPermissions
|
||||||
import com.geeksville.mesh.android.hasCameraPermission
|
import com.geeksville.mesh.android.hasCameraPermission
|
||||||
import com.geeksville.mesh.databinding.ChannelFragmentBinding
|
import com.geeksville.mesh.databinding.ChannelFragmentBinding
|
||||||
import com.geeksville.mesh.model.Channel
|
import com.geeksville.mesh.model.Channel
|
||||||
|
@ -219,12 +219,11 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
|
||||||
debug("Camera permission denied")
|
debug("Camera permission denied")
|
||||||
}
|
}
|
||||||
.setPositiveButton(getString(R.string.accept)) { _, _ ->
|
.setPositiveButton(getString(R.string.accept)) { _, _ ->
|
||||||
requestPermissionAndScanLauncher.launch(Manifest.permission.CAMERA)
|
requestPermissionAndScanLauncher.launch(requireContext().getCameraPermissions())
|
||||||
}
|
}
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun mlkitScan() {
|
private fun mlkitScan() {
|
||||||
debug("Starting ML Kit QR code scanner")
|
debug("Starting ML Kit QR code scanner")
|
||||||
val options = GmsBarcodeScannerOptions.Builder()
|
val options = GmsBarcodeScannerOptions.Builder()
|
||||||
|
@ -368,8 +367,8 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
|
||||||
}
|
}
|
||||||
|
|
||||||
private val requestPermissionAndScanLauncher =
|
private val requestPermissionAndScanLauncher =
|
||||||
registerForActivityResult(ActivityResultContracts.RequestPermission()) { allowed ->
|
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
|
||||||
if (allowed) zxingScan()
|
if (permissions.entries.all { it.value == true }) zxingScan()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register zxing launcher and result handler
|
// Register zxing launcher and result handler
|
||||||
|
|
|
@ -793,11 +793,9 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||||
binding.provideLocationCheckbox.setOnCheckedChangeListener { view, isChecked ->
|
binding.provideLocationCheckbox.setOnCheckedChangeListener { view, isChecked ->
|
||||||
if (view.isPressed && isChecked) { // We want to ignore changes caused by code (as opposed to the user)
|
if (view.isPressed && isChecked) { // We want to ignore changes caused by code (as opposed to the user)
|
||||||
// Don't check the box until the system setting changes
|
// Don't check the box until the system setting changes
|
||||||
view.isChecked = myActivity.hasLocationPermission() && myActivity.hasBackgroundPermission()
|
view.isChecked = myActivity.hasBackgroundPermission()
|
||||||
|
|
||||||
if (!myActivity.hasLocationPermission()) // Make sure we have location permission (prerequisite)
|
if (!myActivity.hasBackgroundPermission())
|
||||||
myActivity.requestLocationPermission()
|
|
||||||
else if (!myActivity.hasBackgroundPermission())
|
|
||||||
MaterialAlertDialogBuilder(requireContext())
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
.setTitle(R.string.background_required)
|
.setTitle(R.string.background_required)
|
||||||
.setMessage(R.string.why_background_required)
|
.setMessage(R.string.why_background_required)
|
||||||
|
@ -805,7 +803,12 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||||
debug("User denied background permission")
|
debug("User denied background permission")
|
||||||
}
|
}
|
||||||
.setPositiveButton(getString(R.string.accept)) { _, _ ->
|
.setPositiveButton(getString(R.string.accept)) { _, _ ->
|
||||||
myActivity.requestBackgroundPermission()
|
// Make sure we have location permission (prerequisite)
|
||||||
|
if (!myActivity.hasLocationPermission()) {
|
||||||
|
requestLocationAndBackgroundLauncher.launch(myActivity.getLocationPermissions())
|
||||||
|
} else {
|
||||||
|
requestBackgroundAndCheckLauncher.launch(myActivity.getBackgroundPermissions())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.show()
|
.show()
|
||||||
if (view.isChecked) {
|
if (view.isChecked) {
|
||||||
|
@ -940,6 +943,23 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val requestLocationAndBackgroundLauncher =
|
||||||
|
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
|
||||||
|
if (permissions.entries.all { it.value == true }) {
|
||||||
|
// Older versions of android only need Location permission
|
||||||
|
if (myActivity.hasBackgroundPermission()) {
|
||||||
|
binding.provideLocationCheckbox.isChecked = true
|
||||||
|
} else requestBackgroundAndCheckLauncher.launch(myActivity.getBackgroundPermissions())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val requestBackgroundAndCheckLauncher =
|
||||||
|
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
|
||||||
|
if (permissions.entries.all { it.value == true }) {
|
||||||
|
binding.provideLocationCheckbox.isChecked = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue