@capacitor-community/background-geolocation
Advanced tools
@@ -25,6 +25,9 @@ package com.equimaps.capacitor_background_geolocation; | ||
| import com.getcapacitor.Logger; | ||
| import com.getcapacitor.NativePlugin; | ||
| import com.getcapacitor.PermissionState; | ||
| import com.getcapacitor.Plugin; | ||
| import com.getcapacitor.PluginCall; | ||
| import com.getcapacitor.PluginMethod; | ||
| import com.getcapacitor.annotation.CapacitorPlugin; | ||
| import com.getcapacitor.annotation.Permission; | ||
| import com.getcapacitor.annotation.PermissionCallback; | ||
| import com.google.android.gms.location.LocationServices; | ||
@@ -37,14 +40,15 @@ import com.google.android.gms.tasks.OnSuccessListener; | ||
| @NativePlugin( | ||
| permissions={ | ||
| // As of API level 31, the coarse permission MUST accompany | ||
| // the fine permission. | ||
| Manifest.permission.ACCESS_COARSE_LOCATION, | ||
| Manifest.permission.ACCESS_FINE_LOCATION | ||
| }, | ||
| // A random integer which is hopefully unique to this plugin. | ||
| permissionRequestCode = 28351 | ||
| @CapacitorPlugin( | ||
| name = "BackgroundGeolocation", | ||
| permissions = { | ||
| @Permission( | ||
| strings = { | ||
| Manifest.permission.ACCESS_COARSE_LOCATION, | ||
| Manifest.permission.ACCESS_FINE_LOCATION | ||
| }, | ||
| alias = "location" | ||
| ) | ||
| } | ||
| ) | ||
| public class BackgroundGeolocation extends Plugin { | ||
| private PluginCall callPendingPermissions = null; | ||
| private BackgroundGeolocationService.LocalBinder service = null; | ||
@@ -71,3 +75,3 @@ private Boolean stoppedWithoutPermissions = false; | ||
| @PluginMethod(returnType=PluginMethod.RETURN_CALLBACK) | ||
| @PluginMethod(returnType = PluginMethod.RETURN_CALLBACK) | ||
| public void addWatcher(final PluginCall call) { | ||
@@ -79,6 +83,6 @@ if (service == null) { | ||
| call.setKeepAlive(true); | ||
| if (!hasRequiredPermissions()) { | ||
| if (getPermissionState("location") != PermissionState.GRANTED) { | ||
| if (call.getBoolean("requestPermissions", true)) { | ||
| callPendingPermissions = call; | ||
| pluginRequestAllPermissions(); | ||
| requestPermissionForAlias("location", call, "locationPermissionsCallback"); | ||
| } else { | ||
@@ -166,16 +170,9 @@ call.reject("Permission denied.", "NOT_AUTHORIZED"); | ||
| @Override | ||
| protected void handleRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { | ||
| super.handleRequestPermissionsResult(requestCode, permissions, grantResults); | ||
| if (callPendingPermissions == null) { | ||
| @PermissionCallback | ||
| private void locationPermissionsCallback(PluginCall call) { | ||
| if (getPermissionState("location") != PermissionState.GRANTED) { | ||
| call.reject("User denied location permission", "NOT_AUTHORIZED"); | ||
| return; | ||
| } | ||
| PluginCall call = callPendingPermissions; | ||
| callPendingPermissions = null; | ||
| for (int result : grantResults) { | ||
| if (result == PackageManager.PERMISSION_DENIED) { | ||
| call.reject("User denied location permission", "NOT_AUTHORIZED"); | ||
| return; | ||
| } | ||
| } | ||
| if (call.getBoolean("stale", false)) { | ||
@@ -200,5 +197,5 @@ fetchLastLocation(call); | ||
| service.removeWatcher(callbackId); | ||
| PluginCall savedCall = bridge.getSavedCall(callbackId); | ||
| PluginCall savedCall = getBridge().getSavedCall(callbackId); | ||
| if (savedCall != null) { | ||
| savedCall.release(bridge); | ||
| savedCall.release(getBridge()); | ||
| } | ||
@@ -218,4 +215,3 @@ call.resolve(); | ||
| // Checks if device-wide location services are disabled | ||
| private static Boolean isLocationEnabled(Context context) | ||
| { | ||
| private static Boolean isLocationEnabled(Context context) { | ||
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { | ||
@@ -225,3 +221,3 @@ LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); | ||
| } else { | ||
| return ( | ||
| return ( | ||
| Settings.Secure.getInt( | ||
@@ -233,3 +229,2 @@ context.getContentResolver(), | ||
| ); | ||
| } | ||
@@ -266,3 +261,3 @@ } | ||
| String id = intent.getStringExtra("id"); | ||
| PluginCall call = bridge.getSavedCall(id); | ||
| PluginCall call = getBridge().getSavedCall(id); | ||
| if (call == null) { | ||
@@ -299,3 +294,2 @@ return; | ||
| Intent serviceIntent = new Intent(this.getContext(), BackgroundGeolocationService.class); | ||
| // Android O requires a Notification Channel. | ||
@@ -318,9 +312,6 @@ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | ||
| manager.createNotificationChannel(channel); | ||
| this.getContext().startForegroundService(serviceIntent); | ||
| } else { | ||
| this.getContext().startService(serviceIntent); | ||
| } | ||
| this.getContext().bindService( | ||
| serviceIntent, | ||
| new Intent(this.getContext(), BackgroundGeolocationService.class), | ||
| new ServiceConnection() { | ||
@@ -348,3 +339,3 @@ @Override | ||
| if (service != null) { | ||
| if (stoppedWithoutPermissions && hasRequiredPermissions()) { | ||
| if (stoppedWithoutPermissions && getPermissionState("location") == PermissionState.GRANTED) { | ||
| service.onPermissionsGranted(); | ||
@@ -358,3 +349,3 @@ } | ||
| protected void handleOnPause() { | ||
| stoppedWithoutPermissions = !hasRequiredPermissions(); | ||
| stoppedWithoutPermissions = getPermissionState("location") != PermissionState.GRANTED; | ||
| super.handleOnPause(); | ||
@@ -361,0 +352,0 @@ } |
@@ -46,7 +46,2 @@ package com.equimaps.capacitor_background_geolocation; | ||
| @Override | ||
| public int onStartCommand(Intent intent, int flags, int startId) { | ||
| return START_STICKY; | ||
| } | ||
| @Override | ||
| public IBinder onBind(Intent intent) { | ||
@@ -53,0 +48,0 @@ return binder; |
+80
-0
@@ -0,18 +1,81 @@ | ||
| /** | ||
| * The options for configuring a watcher that listens for location updates. | ||
| */ | ||
| export interface WatcherOptions { | ||
| /** | ||
| * If the "backgroundMessage" option is defined, the watcher will | ||
| * provide location updates whether the app is in the background or the | ||
| * foreground. If it is not defined, location updates are only | ||
| * guaranteed in the foreground. This is true on both platforms. | ||
| * | ||
| * On Android, a notification must be shown to continue receiving | ||
| * location updates in the background. This option specifies the text of | ||
| * that notification. | ||
| */ | ||
| backgroundMessage?: string; | ||
| /** | ||
| * The title of the notification mentioned above. | ||
| * @default "Using your location" | ||
| */ | ||
| backgroundTitle?: string; | ||
| /** | ||
| * Whether permissions should be requested from the user automatically, | ||
| * if they are not already granted. | ||
| * @default true | ||
| */ | ||
| requestPermissions?: boolean; | ||
| /** | ||
| * If "true", stale locations may be delivered while the device | ||
| * obtains a GPS fix. You are responsible for checking the "time" | ||
| * property. If "false", locations are guaranteed to be up to date. | ||
| * @default false | ||
| */ | ||
| stale?: boolean; | ||
| /** | ||
| * The distance in meters that the device must move before a new location update is triggered. | ||
| * This is used to filter out small movements and reduce the number of updates. | ||
| * @default 0 | ||
| */ | ||
| distanceFilter?: number; | ||
| } | ||
| /** | ||
| * Represents a geographical location with various attributes. | ||
| */ | ||
| export interface Location { | ||
| /** | ||
| * Longitude in degrees. | ||
| */ | ||
| latitude: number; | ||
| /** | ||
| * Latitude in degrees. | ||
| */ | ||
| longitude: number; | ||
| /** | ||
| * Radius of horizontal uncertainty in metres, with 68% confidence. | ||
| */ | ||
| accuracy: number; | ||
| /** | ||
| * Metres above sea level (or null). | ||
| */ | ||
| altitude: number | null; | ||
| /** | ||
| * Vertical uncertainty in metres, with 68% confidence (or null). | ||
| */ | ||
| altitudeAccuracy: number | null; | ||
| /** | ||
| * `true` if the location was simulated by software, rather than GPS. | ||
| */ | ||
| simulated: boolean; | ||
| /** | ||
| * Deviation from true north in degrees (or null). | ||
| */ | ||
| bearing: number | null; | ||
| /** | ||
| * Speed in metres per second (or null). | ||
| */ | ||
| speed: number | null; | ||
| /** | ||
| * Time the location was produced, in milliseconds since the unix epoch. | ||
| */ | ||
| time: number | null; | ||
@@ -26,2 +89,11 @@ } | ||
| export interface BackgroundGeolocationPlugin { | ||
| /** | ||
| * Adds a watcher for location updates. | ||
| * The watcher will be invoked with the latest location whenever it is available. | ||
| * If an error occurs, the callback will be invoked with the error. | ||
| * | ||
| * @param options the watcher options | ||
| * @param callback the callback to be invoked when a new location is available or an error occurs | ||
| * @returns a promise that resolves to a unique identifier for the watcher ID | ||
| */ | ||
| addWatcher( | ||
@@ -34,6 +106,14 @@ options: WatcherOptions, | ||
| ): Promise<string>; | ||
| /** | ||
| * Removes a watcher by its unique identifier. | ||
| * @param options the options for removing the watcher | ||
| * @returns a promise that resolves when the watcher is successfully removed | ||
| */ | ||
| removeWatcher(options: { | ||
| id: string | ||
| }): Promise<void>; | ||
| /** | ||
| * Opens the settings page of the app. | ||
| */ | ||
| openSettings(): Promise<void>; | ||
| } |
+1
-1
| { | ||
| "name": "@capacitor-community/background-geolocation", | ||
| "version": "1.2.23", | ||
| "version": "1.2.24", | ||
| "description": "Receive geolocation updates even while the app is in the background.", | ||
@@ -5,0 +5,0 @@ "repository": { |
+3
-0
@@ -217,2 +217,5 @@ # Background Geolocation | ||
| ### v1.2.24 | ||
| - Avoid crash introduced in v1.2.23. | ||
| ### v1.2.23 | ||
@@ -219,0 +222,0 @@ - Perhaps make location updates more persistent on Android, see #137. |
51692
4.7%587
12.67%264
1.15%