forked from upstream-mirrors/OpenTracks
3910837d1a
Added ACCESS_BACKGROUND_LOCATION permission to access GPS while phone is in standby. This is necessary for situations where the PublicAPI is triggered to start a record from an external device like a smartwatch.
102 lines
3.9 KiB
Java
102 lines
3.9 KiB
Java
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.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
|
|
public class PermissionRequester {
|
|
|
|
private final List<String> permissions;
|
|
|
|
public PermissionRequester(List<String> permissions) {
|
|
this.permissions = permissions;
|
|
}
|
|
|
|
public boolean hasPermission(Context context) {
|
|
return permissions.stream()
|
|
.map(p -> ContextCompat.checkSelfPermission(context, p))
|
|
.allMatch(r -> r == PackageManager.PERMISSION_GRANTED);
|
|
}
|
|
|
|
public void requestPermissionsIfNeeded(Context context, ActivityResultCaller caller, @Nullable Runnable onGranted, @Nullable RejectedCallback onRejected) {
|
|
if (!hasPermission(context)) {
|
|
requestPermission(caller, onGranted, onRejected);
|
|
}
|
|
}
|
|
|
|
public boolean shouldShowRequestPermissionRationale(Fragment context) {
|
|
return permissions.stream()
|
|
.anyMatch(context::shouldShowRequestPermissionRationale);
|
|
}
|
|
|
|
private void requestPermission(ActivityResultCaller context, @Nullable Runnable onGranted, @Nullable RejectedCallback onRejected) {
|
|
ActivityResultLauncher<String[]> locationPermissionRequest = context.registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), result -> {
|
|
boolean isGranted = permissions.stream()
|
|
.allMatch(p -> result.getOrDefault(p, false));
|
|
if (isGranted && onGranted != null) {
|
|
onGranted.run();
|
|
}
|
|
if (!isGranted && onRejected != null) {
|
|
onRejected.rejected(this);
|
|
}
|
|
}
|
|
);
|
|
|
|
locationPermissionRequest.launch(permissions.toArray(permissions.toArray(new String[0])));
|
|
}
|
|
|
|
private static final List<String> GPS_PERMISSION = List.of(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION);
|
|
|
|
private static final List<String> BLUETOOTH_PERMISSIONS;
|
|
|
|
static {
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
BLUETOOTH_PERMISSIONS = List.of(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT);
|
|
} else {
|
|
BLUETOOTH_PERMISSIONS = Collections.emptyList();
|
|
}
|
|
}
|
|
|
|
private static final List<String> NOTIFICATION_PERMISSIONS;
|
|
|
|
static {
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
NOTIFICATION_PERMISSIONS = List.of(Manifest.permission.POST_NOTIFICATIONS);
|
|
} else {
|
|
NOTIFICATION_PERMISSIONS = Collections.emptyList();
|
|
}
|
|
}
|
|
|
|
private static final List<String> ALL_PERMISSIONS;
|
|
|
|
static {
|
|
ArrayList<String> all = new ArrayList<>(GPS_PERMISSION);
|
|
all.addAll(BLUETOOTH_PERMISSIONS);
|
|
all.addAll(NOTIFICATION_PERMISSIONS);
|
|
|
|
ALL_PERMISSIONS = Collections.unmodifiableList(all);
|
|
}
|
|
|
|
public final static PermissionRequester GPS = new PermissionRequester(GPS_PERMISSION);
|
|
public final static PermissionRequester BLUETOOTH = new PermissionRequester(BLUETOOTH_PERMISSIONS);
|
|
public final static PermissionRequester NOTIFICATION = new PermissionRequester(NOTIFICATION_PERMISSIONS);
|
|
|
|
public final static PermissionRequester ALL = new PermissionRequester(ALL_PERMISSIONS);
|
|
|
|
public interface RejectedCallback {
|
|
void rejected(PermissionRequester permissionRequester);
|
|
}
|
|
}
|