diff --git a/README.md b/README.md index c9d4b30f..8eb45977 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ To use this plugin, add `geolocator` as a [dependency in your pubspec.yaml file] ```yaml dependencies: - geolocator: ^6.1.7 + geolocator: ^6.1.9 ```
diff --git a/geolocator/CHANGELOG.md b/geolocator/CHANGELOG.md index 9591a01b..4228e5d4 100644 --- a/geolocator/CHANGELOG.md +++ b/geolocator/CHANGELOG.md @@ -1,3 +1,11 @@ +## 6.2.0 + +- Added a functionality to receive NMEA messages. + +## 6.1.9 + +- Return `LocationPermission.always` when requesting permission on Android 5.1 and below (see issue [#610](https://github.com/Baseflow/flutter-geolocator/issues/610)). + ## 6.1.8+1 - Fixed Dart formatting issue. diff --git a/geolocator/README.md b/geolocator/README.md index fac54ce9..6c817166 100644 --- a/geolocator/README.md +++ b/geolocator/README.md @@ -19,12 +19,7 @@ A Flutter geolocation plugin which provides easy access to platform specific loc ## Usage -To use this plugin, add `geolocator` as a [dependency in your pubspec.yaml file](https://flutter.io/platform-plugins/). For example: - -```yaml -dependencies: - geolocator: ^6.1.8 -``` +To add the geolocator to your Flutter application read the [install](https://pub.dev/packages/geolocator/install) instructions. Below are some Android and iOS specifics that are required for the geolocator to work correctly.
Android diff --git a/geolocator/android/build.gradle b/geolocator/android/build.gradle index 5365b734..b7b2d7fb 100644 --- a/geolocator/android/build.gradle +++ b/geolocator/android/build.gradle @@ -22,7 +22,7 @@ rootProject.allprojects { apply plugin: 'com.android.library' android { - compileSdkVersion 29 + compileSdkVersion 30 defaultConfig { minSdkVersion 16 diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java b/geolocator/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java index 17efe836..e245bf86 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java @@ -1,15 +1,17 @@ package com.baseflow.geolocator; -import android.util.Log; - +import android.app.Activity; +import android.content.Context; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.baseflow.geolocator.location.GeolocationManager; +import com.baseflow.geolocator.nmea.NmeaMessageManager; import com.baseflow.geolocator.permission.PermissionManager; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; +import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.PluginRegistry.Registrar; /** GeolocatorPlugin */ @@ -18,18 +20,25 @@ public class GeolocatorPlugin implements FlutterPlugin, ActivityAware { private static final String TAG = "GeocodingPlugin"; private final PermissionManager permissionManager; private final GeolocationManager geolocationManager; + private final NmeaMessageManager nmeaMessageManager; @Nullable private MethodCallHandlerImpl methodCallHandler; - @Nullable private StreamHandlerImpl streamHandler; + @Nullable + private PositionStreamHandlerImpl positionStreamHandler; - @Nullable private Registrar pluginRegistrar; + @Nullable + private NmeaStreamHandlerImpl nmeaStreamHandler; - @Nullable private ActivityPluginBinding pluginBinding; + @Nullable + private Registrar pluginRegistrar; - public GeolocatorPlugin() { + @Nullable + private ActivityPluginBinding pluginBinding; + public GeolocatorPlugin() { this.permissionManager = new PermissionManager(); + this.nmeaMessageManager = new NmeaMessageManager(permissionManager); this.geolocationManager = new GeolocationManager(permissionManager); } @@ -45,27 +54,13 @@ public GeolocatorPlugin() { public static void registerWith(Registrar registrar) { GeolocatorPlugin geolocatorPlugin = new GeolocatorPlugin(); geolocatorPlugin.pluginRegistrar = registrar; - geolocatorPlugin.registerListeners(); - - MethodCallHandlerImpl methodCallHandler = - new MethodCallHandlerImpl( - geolocatorPlugin.permissionManager, geolocatorPlugin.geolocationManager); - methodCallHandler.startListening(registrar.context(), registrar.messenger()); - methodCallHandler.setActivity(registrar.activity()); - - StreamHandlerImpl streamHandler = new StreamHandlerImpl(geolocatorPlugin.geolocationManager); - streamHandler.startListening(registrar.context(), registrar.messenger()); - streamHandler.setActivity(registrar.activity()); + geolocatorPlugin.configureListeners(registrar.context(), registrar.messenger()); + geolocatorPlugin.setActivity(registrar.activity()); } @Override public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { - methodCallHandler = new MethodCallHandlerImpl(this.permissionManager, this.geolocationManager); - methodCallHandler.startListening( - flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); - streamHandler = new StreamHandlerImpl(this.geolocationManager); - streamHandler.startListening( - flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); + configureListeners(flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); } @Override @@ -75,23 +70,21 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { methodCallHandler = null; } - if (streamHandler != null) { - streamHandler.stopListening(); - streamHandler = null; + if (positionStreamHandler != null) { + positionStreamHandler.stopListening(); + positionStreamHandler = null; + } + + if (nmeaStreamHandler != null) { + nmeaStreamHandler.stopListening(); + nmeaStreamHandler = null; } } @Override public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { - if (methodCallHandler != null) { - methodCallHandler.setActivity(binding.getActivity()); - } - if (streamHandler != null) { - streamHandler.setActivity(binding.getActivity()); - } - this.pluginBinding = binding; - registerListeners(); + setActivity(binding.getActivity()); } @Override @@ -106,14 +99,38 @@ public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBindin @Override public void onDetachedFromActivity() { + setActivity(null); + } + + + void configureListeners(Context applicationContext, BinaryMessenger messenger) { + methodCallHandler = + new MethodCallHandlerImpl(permissionManager, geolocationManager); + methodCallHandler.startListening(applicationContext, messenger); + + positionStreamHandler = new PositionStreamHandlerImpl(geolocationManager); + positionStreamHandler.startListening(applicationContext, messenger); + + nmeaStreamHandler = new NmeaStreamHandlerImpl(nmeaMessageManager); + nmeaStreamHandler.startListening(applicationContext, messenger); + } + + void setActivity(@Nullable Activity activity) { if (methodCallHandler != null) { - methodCallHandler.setActivity(null); + methodCallHandler.setActivity(activity); } - if (streamHandler != null) { - streamHandler.setActivity(null); + if (positionStreamHandler != null) { + positionStreamHandler.setActivity(activity); + } + if (nmeaStreamHandler != null) { + nmeaStreamHandler.setActivity(activity); } - deregisterListeners(); + if (activity != null) { + registerListeners(); + } else { + deregisterListeners(); + } } private void registerListeners() { diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java b/geolocator/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java new file mode 100644 index 00000000..9d0f5dc9 --- /dev/null +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java @@ -0,0 +1,106 @@ +package com.baseflow.geolocator; + +import android.app.Activity; +import android.content.Context; +import android.util.Log; +import androidx.annotation.Nullable; +import com.baseflow.geolocator.errors.ErrorCodes; +import com.baseflow.geolocator.location.GeolocationManager; +import com.baseflow.geolocator.nmea.NmeaMessageManager; +import com.baseflow.geolocator.nmea.NmeaMessageaClient; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.EventChannel; +import java.util.HashMap; +import java.util.Map; + +class NmeaStreamHandlerImpl implements EventChannel.StreamHandler { + + private static final String TAG = "NmeaStreamHandlerImpl"; + + private final NmeaMessageManager nmeaMessageManager; + + @Nullable + private EventChannel channel; + @Nullable + private Context context; + @Nullable + private Activity activity; + @Nullable + private NmeaMessageaClient nmeaMessageaClient; + + public NmeaStreamHandlerImpl(NmeaMessageManager nmeaMessageManager) { + this.nmeaMessageManager = nmeaMessageManager; + } + + private static Map toMap(String message, Long timestamp) { + if (message == null || timestamp == null) { + return null; + } + + Map nmeaMap = new HashMap<>(); + + nmeaMap.put("timestamp", timestamp); + nmeaMap.put("message", message); + + return nmeaMap; + } + + void setActivity(@Nullable Activity activity) { + this.activity = activity; + } + + /** + * Registers this instance as event stream handler on the given {@code messenger}. + * + *

Stops any previously started and unstopped calls. + * + *

This should be cleaned with {@link #stopListening} once the messenger is disposed of. + */ + void startListening(Context context, BinaryMessenger messenger) { + if (channel != null) { + Log.w(TAG, "Setting a event call handler before the last was disposed."); + stopListening(); + } + + channel = new EventChannel(messenger, "flutter.baseflow.com/nmea_updates"); + channel.setStreamHandler(this); + this.context = context; + } + + /** + * Clears this instance from listening to method calls. + * + *

Does nothing if {@link #startListening} hasn't been called, or if we're already stopped. + */ + void stopListening() { + if (channel == null) { + Log.d(TAG, "Tried to stop listening when no MethodChannel had been initialized."); + return; + } + + channel.setStreamHandler(null); + channel = null; + } + + @Override + public void onListen(Object arguments, EventChannel.EventSink events) { + + this.nmeaMessageaClient = nmeaMessageManager.createNmeaClient(context); + + nmeaMessageManager.startNmeaUpdates( + context, + activity, + this.nmeaMessageaClient, + (String message, long timestamp) -> events.success(toMap(message, timestamp)), + (ErrorCodes errorCodes) -> + events.error(errorCodes.toString(), errorCodes.toDescription(), null)); + } + + @Override + public void onCancel(Object arguments) { + if (this.nmeaMessageaClient != null) { + nmeaMessageManager.stopNmeaUpdates(this.nmeaMessageaClient); + } + } + +} diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java b/geolocator/android/src/main/java/com/baseflow/geolocator/PositionStreamHandlerImpl.java similarity index 93% rename from geolocator/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java rename to geolocator/android/src/main/java/com/baseflow/geolocator/PositionStreamHandlerImpl.java index eaf83cdd..f3f5a54d 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/PositionStreamHandlerImpl.java @@ -15,8 +15,9 @@ import java.util.Map; -class StreamHandlerImpl implements EventChannel.StreamHandler { - private static final String TAG = "StreamHandlerImpl"; +class PositionStreamHandlerImpl implements EventChannel.StreamHandler { + + private static final String TAG = "PositionStreamHandler"; private final GeolocationManager geolocationManager; @@ -25,7 +26,7 @@ class StreamHandlerImpl implements EventChannel.StreamHandler { @Nullable private Activity activity; @Nullable private LocationClient locationClient; - public StreamHandlerImpl(GeolocationManager geolocationManager) { + public PositionStreamHandlerImpl(GeolocationManager geolocationManager) { this.geolocationManager = geolocationManager; } diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/GeolocationManager.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/GeolocationManager.java index d7fb9347..4ef8f170 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/GeolocationManager.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/GeolocationManager.java @@ -5,23 +5,22 @@ import android.content.Intent; import androidx.annotation.NonNull; import androidx.annotation.Nullable; - import com.baseflow.geolocator.errors.ErrorCallback; import com.baseflow.geolocator.errors.ErrorCodes; -import com.baseflow.geolocator.errors.PermissionUndefinedException; -import com.baseflow.geolocator.permission.LocationPermission; import com.baseflow.geolocator.permission.PermissionManager; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GoogleApiAvailability; -; import io.flutter.plugin.common.PluginRegistry.ActivityResultListener; import java.util.ArrayList; import java.util.List; public class GeolocationManager implements ActivityResultListener { - @NonNull private final PermissionManager permissionManager; + + @NonNull + private final PermissionManager permissionManager; private final List locationClients; + public GeolocationManager(@NonNull PermissionManager permissionManager) { this.permissionManager = permissionManager; this.locationClients = new ArrayList<>(); @@ -34,7 +33,7 @@ public void getLastKnownPosition( PositionChangedCallback positionChangedCallback, ErrorCallback errorCallback) { - handlePermissions( + permissionManager.handlePermissions( context, activity, () -> { @@ -63,7 +62,7 @@ public void startPositionUpdates( this.locationClients.add(locationClient); - handlePermissions( + permissionManager.handlePermissions( context, activity, () -> locationClient.startPositionUpdates(activity, positionChangedCallback, errorCallback), @@ -94,46 +93,6 @@ private boolean isGooglePlayServicesAvailable(Context context) { return resultCode == ConnectionResult.SUCCESS; } - private void handlePermissions( - Context context, - @Nullable Activity activity, - Runnable hasPermissionCallback, - ErrorCallback errorCallback) { - try { - LocationPermission permissionStatus = - permissionManager.checkPermissionStatus(context, activity); - - if (permissionStatus == LocationPermission.deniedForever) { - errorCallback.onError(ErrorCodes.permissionDenied); - return; - } - - if (permissionStatus == LocationPermission.whileInUse - || permissionStatus == LocationPermission.always) { - hasPermissionCallback.run(); - return; - } - - if (permissionStatus == LocationPermission.denied && activity != null) { - permissionManager.requestPermission( - activity, - (permission) -> { - if (permission == LocationPermission.whileInUse - || permission == LocationPermission.always) { - hasPermissionCallback.run(); - } else { - errorCallback.onError(ErrorCodes.permissionDenied); - } - }, - errorCallback); - } else { - errorCallback.onError(ErrorCodes.permissionDenied); - } - } catch (PermissionUndefinedException ex) { - errorCallback.onError(ErrorCodes.permissionDefinitionsNotFound); - } - } - @Override public boolean onActivityResult(int requestCode, int resultCode, Intent data) { for (LocationClient client : this.locationClients) { diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationManagerClient.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationManagerClient.java index 6a7f9268..23d4cf84 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationManagerClient.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationManagerClient.java @@ -20,7 +20,8 @@ import java.util.List; -class LocationManagerClient implements LocationClient, LocationListener { + +class LocationManagerClient implements LocationClient, LocationListener{ private static final long TWO_MINUTES = 120000; private final LocationManager locationManager; diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java b/geolocator/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java new file mode 100644 index 00000000..c0c8175d --- /dev/null +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java @@ -0,0 +1,85 @@ +package com.baseflow.geolocator.nmea; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.location.OnNmeaMessageListener; +import android.os.Looper; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.baseflow.geolocator.errors.ErrorCallback; +import com.baseflow.geolocator.errors.ErrorCodes; + + +@SuppressLint("NewApi") +public class GnssNmeaMessageClient implements OnNmeaMessageListener, LocationListener, + NmeaMessageaClient { + + private final LocationManager locationManager; + @Nullable + private NmeaChangedCallback nmeaChangedCallback; + + @Nullable + private ErrorCallback errorCallback; + + private boolean isListening = false; + + + public GnssNmeaMessageClient( + @NonNull Context context) { + this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + } + + @SuppressLint("MissingPermission") + public void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, + ErrorCallback errorCallback) { + + this.locationManager.addNmeaListener(this, null); + this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0, this, + Looper.getMainLooper()); + this.nmeaChangedCallback = nmeaChangedCallback; + this.errorCallback = errorCallback; + this.isListening = true; + } + + @SuppressLint("MissingPermission") + @Override + public void stopNmeaUpdates() { + this.isListening = false; + this.locationManager.removeUpdates(this); + } + + + @Override + public void onNmeaMessage(String message, long timestamp) { + if (this.nmeaChangedCallback != null) { + this.nmeaChangedCallback.onNmeaMessage(message, timestamp); + } + } + + + @Override + public void onLocationChanged(@NonNull Location location) { + } + + + @Override + public void onProviderEnabled(String s) { + } + + @SuppressLint("MissingPermission") + @Override + public void onProviderDisabled(String provider) { + if (provider.equals(LocationManager.GPS_PROVIDER)) { + if (isListening) { + this.locationManager.removeUpdates(this); + } + + if (this.errorCallback != null) { + errorCallback.onError(ErrorCodes.locationServicesDisabled); + } + } + } +} diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/nmea/GpsNmeaMessageClient.java b/geolocator/android/src/main/java/com/baseflow/geolocator/nmea/GpsNmeaMessageClient.java new file mode 100644 index 00000000..82864bf0 --- /dev/null +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/nmea/GpsNmeaMessageClient.java @@ -0,0 +1,79 @@ +package com.baseflow.geolocator.nmea; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.location.GpsStatus; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.baseflow.geolocator.errors.ErrorCallback; +import com.baseflow.geolocator.errors.ErrorCodes; + + +public class GpsNmeaMessageClient implements LocationListener, GpsStatus.NmeaListener, + NmeaMessageaClient { + + LocationManager locationManager; + @Nullable + private NmeaChangedCallback nmeaChangedCallback; + + @Nullable + private ErrorCallback errorCallback; + + private boolean isListening = false; + + + public GpsNmeaMessageClient( + @NonNull Context context) { + this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + } + + @SuppressLint("MissingPermission") + public void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, + ErrorCallback errorCallback) { + + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0, this); + locationManager.addNmeaListener(this); + this.nmeaChangedCallback = nmeaChangedCallback; + this.errorCallback = errorCallback; + this.isListening = true; + } + + @SuppressLint("MissingPermission") + @Override + public void stopNmeaUpdates() { + this.isListening = false; + this.locationManager.removeUpdates(this); + } + + @Override + public void onLocationChanged(@NonNull Location location) { + } + + @Override + public void onProviderEnabled(String s) { + } + + @SuppressLint("MissingPermission") + @Override + public void onProviderDisabled(String s) { + if (s.equals(LocationManager.GPS_PROVIDER)) { + if (isListening) { + this.locationManager.removeUpdates(this); + } + + if (this.errorCallback != null) { + errorCallback.onError(ErrorCodes.locationServicesDisabled); + } + } + } + + @Override + public void onNmeaReceived(long l, String s) { + if (this.nmeaChangedCallback != null) { + this.nmeaChangedCallback.onNmeaMessage(s, l); + } + } +} diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/nmea/NmeaChangedCallback.java b/geolocator/android/src/main/java/com/baseflow/geolocator/nmea/NmeaChangedCallback.java new file mode 100644 index 00000000..a65bcc86 --- /dev/null +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/nmea/NmeaChangedCallback.java @@ -0,0 +1,8 @@ +package com.baseflow.geolocator.nmea; + + +@FunctionalInterface +public interface NmeaChangedCallback { + + void onNmeaMessage(String message, long timeStamp); +} diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java b/geolocator/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java new file mode 100644 index 00000000..69c22cb7 --- /dev/null +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java @@ -0,0 +1,42 @@ +package com.baseflow.geolocator.nmea; + + +import android.app.Activity; +import android.content.Context; +import android.os.Build.VERSION_CODES; +import androidx.annotation.NonNull; +import com.baseflow.geolocator.errors.ErrorCallback; +import com.baseflow.geolocator.permission.PermissionManager; + +public class NmeaMessageManager { + + @NonNull + private final PermissionManager permissionManager; + + + public NmeaMessageManager(@NonNull PermissionManager permissionManager) { + this.permissionManager = permissionManager; + } + + + public void startNmeaUpdates(Context context, Activity activity, NmeaMessageaClient client, + NmeaChangedCallback nmeaChangedCallback, ErrorCallback errorCallback) { + + permissionManager.handlePermissions( + context, + activity, + () -> client.startNmeaUpdates(nmeaChangedCallback, errorCallback), + errorCallback); + } + + public void stopNmeaUpdates(NmeaMessageaClient client) { + client.stopNmeaUpdates(); + } + + public NmeaMessageaClient createNmeaClient(Context context) { + return android.os.Build.VERSION.SDK_INT >= VERSION_CODES.N + ? new GnssNmeaMessageClient(context) + : new GpsNmeaMessageClient(context); + } + +} diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java b/geolocator/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java new file mode 100644 index 00000000..21b48ae6 --- /dev/null +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java @@ -0,0 +1,11 @@ +package com.baseflow.geolocator.nmea; + +import com.baseflow.geolocator.errors.ErrorCallback; + +public interface NmeaMessageaClient { + + void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, + ErrorCallback errorCallback); + + void stopNmeaUpdates(); +} diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/permission/PermissionManager.java b/geolocator/android/src/main/java/com/baseflow/geolocator/permission/PermissionManager.java index d41aa55f..a8a01dc4 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/permission/PermissionManager.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/permission/PermissionManager.java @@ -27,6 +27,47 @@ public class PermissionManager implements PluginRegistry.RequestPermissionsResul @Nullable private ErrorCallback errorCallback; @Nullable private PermissionResultCallback resultCallback; + + public void handlePermissions( + Context context, + @Nullable Activity activity, + Runnable hasPermissionCallback, + ErrorCallback errorCallback) { + try { + LocationPermission permissionStatus = + checkPermissionStatus(context, activity); + + if (permissionStatus == LocationPermission.deniedForever) { + errorCallback.onError(ErrorCodes.permissionDenied); + return; + } + + if (permissionStatus == LocationPermission.whileInUse + || permissionStatus == LocationPermission.always) { + hasPermissionCallback.run(); + return; + } + + if (permissionStatus == LocationPermission.denied && activity != null) { + requestPermission( + activity, + (permission) -> { + if (permission == LocationPermission.whileInUse + || permission == LocationPermission.always) { + hasPermissionCallback.run(); + } else { + errorCallback.onError(ErrorCodes.permissionDenied); + } + }, + errorCallback); + } else { + errorCallback.onError(ErrorCodes.permissionDenied); + } + } catch (PermissionUndefinedException ex) { + errorCallback.onError(ErrorCodes.permissionDefinitionsNotFound); + } + } + public LocationPermission checkPermissionStatus(Context context, Activity activity) throws PermissionUndefinedException { String permission = determineFineOrCoarse(context); @@ -72,6 +113,7 @@ public void requestPermission( // Before Android M, requesting permissions was not needed. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + resultCallback.onResult(LocationPermission.always); return; } diff --git a/geolocator/example/android/app/src/main/res/values/styles.xml b/geolocator/example/android/app/src/main/res/values/styles.xml index 1f83a33f..322503e4 100644 --- a/geolocator/example/android/app/src/main/res/values/styles.xml +++ b/geolocator/example/android/app/src/main/res/values/styles.xml @@ -10,7 +10,7 @@ This theme determines the color of the Android Window while your Flutter UI initializes, as well as behind your Flutter UI while its running. - + This Theme is only used starting with V2 of Flutter's Android embedding. -->