From 329216c760660a63198c26b0e87224476cfa2760 Mon Sep 17 00:00:00 2001 From: Steve Hannah Date: Sun, 24 Nov 2024 14:53:53 -0800 Subject: [PATCH] fix: Android geofence permissions 29+ (#3854) * fix: Android geofence permissions 29+ * hard-coded FLAG_MUTABLE because not available in older versions --- .../impl/android/AndroidImplementation.java | 27 ++++++++++++------- .../AndroidLocationPlayServiceManager.java | 6 ++--- .../BackgroundLocationBroadcastReceiver.java | 6 ++++- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java b/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java index 5508aa170f..13894624fd 100644 --- a/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java +++ b/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java @@ -6662,18 +6662,25 @@ public void printStackTraceToStream(Throwable t, Writer o) { * @return LocationControl Object */ public LocationManager getLocationManager() { - boolean permissionGranted = false; - if (Build.VERSION.SDK_INT >= 29 && "true".equals(Display.getInstance().getProperty("android.requiresBackgroundLocationPermissionForAPI29", "false"))) { - - if (checkForPermission("android.permission.ACCESS_BACKGROUND_LOCATION", "This is required to get the location")) { - permissionGranted = true; - } - - } - if (!permissionGranted && !checkForPermission( Manifest.permission.ACCESS_FINE_LOCATION, "This is required to get the location")) { + String permissionMessage = "This is required to get the location"; + if ( + !checkForPermission( Manifest.permission.ACCESS_FINE_LOCATION, permissionMessage) + ) { return null; } - + if ( + Build.VERSION.SDK_INT >= 29 + && "true".equals(Display.getInstance().getProperty("android.requiresBackgroundLocationPermissionForAPI29", "false")) + ) { + if ( + !checkForPermission( + "android.permission.ACCESS_BACKGROUND_LOCATION", + permissionMessage + ) + ) { + com.codename1.io.Log.e(new RuntimeException("Background location permission denied")); + } + } boolean includesPlayServices = Display.getInstance().getProperty("IncludeGPlayServices", "false").equals("true"); if (includesPlayServices && hasAndroidMarket()) { diff --git a/Ports/Android/src/com/codename1/location/AndroidLocationPlayServiceManager.java b/Ports/Android/src/com/codename1/location/AndroidLocationPlayServiceManager.java index 2decb33195..bc135b06de 100644 --- a/Ports/Android/src/com/codename1/location/AndroidLocationPlayServiceManager.java +++ b/Ports/Android/src/com/codename1/location/AndroidLocationPlayServiceManager.java @@ -66,7 +66,7 @@ public class AndroidLocationPlayServiceManager extends com.codename1.location.Lo LifecycleListener { - + private static final int FLAG_MUTABLE = 33554432; static class ParcelableUtil { public static byte[] marshall(Parcelable parceable) { Parcel parcel = Parcel.obtain(); @@ -477,12 +477,12 @@ private PendingIntent createGeofencePendingIntent( } Intent intent = new Intent(context, BackgroundLocationBroadcastReceiver.class); intent.setAction(BackgroundLocationBroadcastReceiver.ACTION_PROCESS_GEOFENCE_TRANSITIONS); - intent.setData(Uri.parse("http://codenameone.com/a?" + geofenceListenerClass.getName())); + intent.putExtra("geofenceListenerClass", geofenceListenerClass.getName()); geofencePendingIntent = PendingIntent.getBroadcast( AndroidNativeUtil.getContext().getApplicationContext(), 0, intent, - PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE + PendingIntent.FLAG_UPDATE_CURRENT | FLAG_MUTABLE ); return geofencePendingIntent; } else { diff --git a/Ports/Android/src/com/codename1/location/BackgroundLocationBroadcastReceiver.java b/Ports/Android/src/com/codename1/location/BackgroundLocationBroadcastReceiver.java index def4cc57b3..01856fa1f1 100644 --- a/Ports/Android/src/com/codename1/location/BackgroundLocationBroadcastReceiver.java +++ b/Ports/Android/src/com/codename1/location/BackgroundLocationBroadcastReceiver.java @@ -105,7 +105,11 @@ public void onReceive(Context context, Intent intent) { String dataString = intent.getDataString(); if (dataString == null) { - return; + if (intent.getExtras() != null && intent.getExtras().get("geofenceListenerClass") != null) { + dataString = "-?" + intent.getExtras().get("geofenceListenerClass"); + } else { + return; + } } String[] params = dataString.split("[?]"); if (params.length < 2) {