Skip to content

Instantly share code, notes, and snippets.

@exelban
Created March 27, 2020 13:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save exelban/67020d6f1de0dc9edb93056bec83e493 to your computer and use it in GitHub Desktop.
Save exelban/67020d6f1de0dc9edb93056bec83e493 to your computer and use it in GitHub Desktop.
Fused Location Provider for Capacitor
package com.getcapacitor.plugin;
import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Looper;
import com.getcapacitor.JSObject;
import com.getcapacitor.NativePlugin;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.PluginRequestCodes;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import java.util.HashMap;
import java.util.Map;
/**
* Geolocation plugin that uses the native location service instead of the browser API.
*
* https://developer.android.com/guide/topics/location/strategies.html
*/
@NativePlugin(
permissions={
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
},
permissionRequestCode = PluginRequestCodes.GEOLOCATION_REQUEST_PERMISSIONS
)
public class Geolocation extends Plugin {
Map<String, PluginCall> watchingCalls = new HashMap<>();
private FusedLocationProviderClient mFusedLocationClient;
private LocationRequest mLocationRequest;
protected Location mLastLocation;
LocationCallback locationCallback;
@PluginMethod()
public void getCurrentPosition(PluginCall call) {
if (!hasRequiredPermissions()) {
saveCall(call);
pluginRequestAllPermissions();
} else {
requestLocationUpdates(call);
clearLocationUpdates();
}
}
@PluginMethod(returnType=PluginMethod.RETURN_CALLBACK)
public void watchPosition(PluginCall call) {
call.save();
if (!hasRequiredPermissions()) {
saveCall(call);
pluginRequestAllPermissions();
} else {
startWatch(call);
}
}
@SuppressWarnings("MissingPermission")
private void startWatch(PluginCall call) {
requestLocationUpdates(call);
watchingCalls.put(call.getCallbackId(), call);
}
@SuppressWarnings("MissingPermission")
@PluginMethod()
public void clearWatch(PluginCall call) {
String callbackId = call.getString("id");
if (callbackId != null) {
PluginCall removed = watchingCalls.remove(callbackId);
if (removed != null) {
removed.release(bridge);
}
}
if (watchingCalls.size() == 0) {
clearLocationUpdates();
}
call.success();
}
private void requestLocationUpdates(final PluginCall call) {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getContext());
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(7500);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationCallback = new LocationCallback(){
@Override
public void onLocationResult(LocationResult locationResult) {
for (Location location : locationResult.getLocations()) {
if (location == null) {
call.success();
} else {
call.success(getJSObjectForLocation(location));
}
}
}
};
mFusedLocationClient.requestLocationUpdates(mLocationRequest, locationCallback, Looper.myLooper());
}
private void clearLocationUpdates() {
mFusedLocationClient.removeLocationUpdates(locationCallback);
}
@Override
protected void handleRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.handleRequestPermissionsResult(requestCode, permissions, grantResults);
PluginCall savedCall = getSavedCall();
if (savedCall == null) {
return;
}
for(int result : grantResults) {
if (result == PackageManager.PERMISSION_DENIED) {
savedCall.error("User denied location permission");
return;
}
}
if (savedCall.getMethodName().equals("getCurrentPosition")) {
requestLocationUpdates(savedCall);
clearLocationUpdates();
} else {
startWatch(savedCall);
}
}
private JSObject getJSObjectForLocation(Location location) {
JSObject ret = new JSObject();
JSObject coords = new JSObject();
ret.put("coords", coords);
coords.put("latitude", location.getLatitude());
coords.put("longitude", location.getLongitude());
coords.put("altitude", location.getAltitude());
coords.put("speed", location.getSpeed());
coords.put("heading", location.getBearing());
return ret;
}
}
@exelban
Copy link
Author

exelban commented Mar 27, 2020

To use fuse location plugin as geolocation service with a capacitor you need to do 2 steps:

  • replace an existing plugin (capacitor-android/src/main/java/com.getcapacitor/plugin/Geolocation) with code above
  • add implementation 'com.google.android.gms:play-services-location:16.0.0' to capacitor-android build.grande in section dependencies

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment