Refactor permission requests.

Fixes #1224.
This commit is contained in:
Dennis Guse
2022-05-12 22:18:59 +02:00
parent 24eb768707
commit e409b315b4
4 changed files with 70 additions and 37 deletions
@@ -1,6 +1,5 @@
package de.dennisguse.opentracks;
import android.Manifest;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
@@ -15,8 +14,6 @@ import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
@@ -379,17 +376,7 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
return;
}
ActivityResultLauncher<String[]> locationPermissionRequest = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), result -> {
Boolean fineLocationGranted = result.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false);
Boolean coarseLocationGranted = result.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false);
if (fineLocationGranted == null || !fineLocationGranted
|| coarseLocationGranted == null || !coarseLocationGranted) {
Toast.makeText(this, R.string.permission_gps_failed, Toast.LENGTH_SHORT).show();
}
}
);
String[] permissions = new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION};
locationPermissionRequest.launch(permissions);
PermissionUtils.requestGPSPermission(this, null, () -> Toast.makeText(this, R.string.permission_gps_failed, Toast.LENGTH_SHORT).show());
}
private void onGpsStatusChanged(GpsStatusValue gpsStatusValue) {
@@ -35,6 +35,7 @@ import de.dennisguse.opentracks.sensors.sensorData.SensorDataCycling;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataRunning;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.util.PermissionUtils;
/**
* Bluetooth LE sensor manager: manages connections to Bluetooth LE sensors.
@@ -161,6 +162,9 @@ public class BluetoothRemoteSensorManager implements BluetoothConnectionManager.
} else {
connectionManager.disconnect();
}
if (!PermissionUtils.hasBluetoothPermissions(context)) {
Log.w(TAG, "BLUETOOTH_SCAN and/or BLUETOOTH_CONNECT not granted; not connecting.");
}
Log.i(TAG, "Connecting to bluetooth address: " + address);
try {
@@ -1,6 +1,5 @@
package de.dennisguse.opentracks.settings.bluetooth;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
@@ -9,8 +8,6 @@ import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.ParcelUuid;
import android.text.TextUtils;
@@ -18,10 +15,7 @@ import android.util.AttributeSet;
import android.util.Log;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.preference.DialogPreference;
import androidx.preference.PreferenceDialogFragmentCompat;
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat;
@@ -35,6 +29,7 @@ import java.util.stream.Collectors;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.sensors.BluetoothUtils;
import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.util.PermissionUtils;
/**
* Preference to select a discoverable Bluetooth LE device.
@@ -150,26 +145,17 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference {
bluetoothIcon = AnimatedVectorDrawableCompat.create(getContext(), R.drawable.ic_bluetooth_searching_animated_24dp);
bluetoothIcon.start();
if (
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && (
ContextCompat.checkSelfPermission(getContext(), Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(getContext(), Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED
)
) {
ActivityResultLauncher<String[]> requestPermissionLauncher =
registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), granted -> {
if (!granted.containsValue(false)) {
startBluetoothScan();
} else if (shouldShowRequestPermissionRationale(Manifest.permission.BLUETOOTH_SCAN) || shouldShowRequestPermissionRationale(Manifest.permission.BLUETOOTH_CONNECT)) {
if (!PermissionUtils.hasBluetoothPermissions(getContext())) {
PermissionUtils.requestBluetoothPermission(this,
this::startBluetoothScan,
() -> {
if (PermissionUtils.shouldShowRequestPermissionRationaleBluetooth(this)) {
Toast.makeText(getContext(), R.string.permission_bluetooth_failed_rejected, Toast.LENGTH_LONG).show();
dismiss();
} else {
Toast.makeText(getContext(), R.string.permission_bluetooth_failed, Toast.LENGTH_SHORT).show();
dismiss();
}
dismiss();
});
requestPermissionLauncher.launch(new String[]{Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN});
} else {
startBluetoothScan();
}
@@ -3,16 +3,72 @@ package de.dennisguse.opentracks.util;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import androidx.activity.result.ActivityResultCaller;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import java.util.Arrays;
public class PermissionUtils {
private static final String[] GPS = new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
private static final String[] BLUETOOTH;
static {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
BLUETOOTH = new String[]{};
} else {
BLUETOOTH = new String[]{Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT};
}
}
private PermissionUtils() {
}
public static boolean hasGPSPermission(Context context) {
return ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
return hasPermissions(context, GPS);
}
public static void requestGPSPermission(ActivityResultCaller context, @Nullable Runnable onGranted, @Nullable Runnable onRejected) {
requestPermission(context, GPS, onGranted, onRejected);
}
public static boolean shouldShowRequestPermissionRationaleBluetooth(Fragment context) {
return Arrays.stream(BLUETOOTH).anyMatch(context::shouldShowRequestPermissionRationale);
}
public static boolean hasBluetoothPermissions(Context context) {
return hasPermissions(context, BLUETOOTH);
}
public static void requestBluetoothPermission(ActivityResultCaller context, @Nullable Runnable onGranted, @Nullable Runnable onRejected) {
requestPermission(context, BLUETOOTH, onGranted, onRejected);
}
private static void requestPermission(ActivityResultCaller context, final String[] permissions, @Nullable Runnable onGranted, @Nullable Runnable onRejected) {
ActivityResultLauncher<String[]> locationPermissionRequest = context.registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), result -> {
boolean isGranted = Arrays.stream(permissions)
.allMatch(p -> result.getOrDefault(p, false));
if (isGranted && onGranted != null) {
onGranted.run();
}
if (!isGranted && onRejected != null) {
onRejected.run();
}
}
);
locationPermissionRequest.launch(permissions);
}
private static boolean hasPermissions(Context context, String[] permissions) {
return Arrays.stream(permissions)
.map(p -> ContextCompat.checkSelfPermission(context, p))
.allMatch(r -> r == PackageManager.PERMISSION_GRANTED);
}
}