diff --git a/extern/GmsApi b/extern/GmsApi
index c61a147d..3f1fa813 160000
--- a/extern/GmsApi
+++ b/extern/GmsApi
@@ -1 +1 @@
-Subproject commit c61a147de29456270bce1203c9f6700268b068c5
+Subproject commit 3f1fa81390d67053d3aa50b0bc3537953396bcf6
diff --git a/play-services-location/src/main/java/com/google/android/gms/location/GeofencingApi.java b/play-services-location/src/main/java/com/google/android/gms/location/GeofencingApi.java
index b2b581bf..0268aeb2 100644
--- a/play-services-location/src/main/java/com/google/android/gms/location/GeofencingApi.java
+++ b/play-services-location/src/main/java/com/google/android/gms/location/GeofencingApi.java
@@ -16,5 +16,33 @@
package com.google.android.gms.location;
+import android.app.PendingIntent;
+
+import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.common.api.PendingResult;
+import com.google.android.gms.common.api.Status;
+
+import java.util.List;
+
+/**
+ * The main entry point for interacting with the geofencing APIs.
+ *
+ * The methods must be used in conjunction with a GoogleApiClient. E.g.
+ *
+ * new GoogleApiClient.Builder(context)
+ * .addApi(LocationServices.API)
+ * .addConnectionCallbacks(this)
+ * .addOnConnectionFailedListener(this)
+ * .build()
+ *
+ */
public interface GeofencingApi {
+ PendingResult addGeofences(GoogleApiClient client, GeofencingRequest geofencingRequest, PendingIntent pendingIntent);
+
+ @Deprecated
+ PendingResult addGeofences(GoogleApiClient client, List geofences, PendingIntent pendingIntent);
+
+ PendingResult removeGeofences(GoogleApiClient client, List geofenceRequestIds);
+
+ PendingResult removeGeofences(GoogleApiClient client, PendingIntent pendingIntent);
}
diff --git a/play-services-location/src/main/java/org/microg/gms/location/FusedLocationProviderApiImpl.java b/play-services-location/src/main/java/org/microg/gms/location/FusedLocationProviderApiImpl.java
index 4da06a0a..84584ac0 100644
--- a/play-services-location/src/main/java/org/microg/gms/location/FusedLocationProviderApiImpl.java
+++ b/play-services-location/src/main/java/org/microg/gms/location/FusedLocationProviderApiImpl.java
@@ -137,5 +137,4 @@ public class FusedLocationProviderApiImpl implements FusedLocationProviderApi {
private interface Runnable {
void run(LocationClientImpl client) throws RemoteException;
}
-
}
diff --git a/play-services-location/src/main/java/org/microg/gms/location/GeofencingApiImpl.java b/play-services-location/src/main/java/org/microg/gms/location/GeofencingApiImpl.java
index 7b6512b0..e0b09c98 100644
--- a/play-services-location/src/main/java/org/microg/gms/location/GeofencingApiImpl.java
+++ b/play-services-location/src/main/java/org/microg/gms/location/GeofencingApiImpl.java
@@ -16,7 +16,101 @@
package org.microg.gms.location;
+import android.app.PendingIntent;
+import android.os.RemoteException;
+import android.support.annotation.NonNull;
+import android.util.Log;
+
+import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.common.api.PendingResult;
+import com.google.android.gms.common.api.Status;
+import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofencingApi;
+import com.google.android.gms.location.GeofencingRequest;
+import com.google.android.gms.location.LocationServices;
+import com.google.android.gms.location.internal.IGeofencerCallbacks;
+import com.google.android.gms.location.internal.ParcelableGeofence;
+
+import org.microg.gms.common.GmsConnector;
+
+import java.util.ArrayList;
+import java.util.List;
public class GeofencingApiImpl implements GeofencingApi {
+ @Override
+ public PendingResult addGeofences(GoogleApiClient client, final GeofencingRequest geofencingRequest, final PendingIntent pendingIntent) {
+ return callGeofencer(client, new Runnable() {
+ @Override
+ public void run(LocationClientImpl client, IGeofencerCallbacks callbacks) throws RemoteException {
+ client.addGeofences(geofencingRequest, pendingIntent, callbacks);
+ }
+ });
+ }
+
+ @Override
+ public PendingResult addGeofences(GoogleApiClient client, final List geofences, final PendingIntent pendingIntent) {
+ final List geofenceList = new ArrayList();
+ for (Geofence geofence : geofences) {
+ if (geofence instanceof ParcelableGeofence) geofenceList.add((ParcelableGeofence) geofence);
+ }
+ return callGeofencer(client, new Runnable() {
+ @Override
+ public void run(LocationClientImpl client, IGeofencerCallbacks callbacks) throws RemoteException {
+ client.addGeofences(geofenceList, pendingIntent, callbacks);
+ }
+ });
+ }
+
+ @Override
+ public PendingResult removeGeofences(GoogleApiClient client, final List geofenceRequestIds) {
+ return callGeofencer(client, new Runnable() {
+ @Override
+ public void run(LocationClientImpl client, IGeofencerCallbacks callbacks) throws RemoteException {
+ client.removeGeofences(geofenceRequestIds, callbacks);
+ }
+ });
+ }
+
+ @Override
+ public PendingResult removeGeofences(GoogleApiClient client, final PendingIntent pendingIntent) {
+ return callGeofencer(client, new Runnable() {
+ @Override
+ public void run(LocationClientImpl client, IGeofencerCallbacks callbacks) throws RemoteException {
+ client.removeGeofences(pendingIntent, callbacks);
+ }
+ });
+ }
+
+ @NonNull
+ private IGeofencerCallbacks.Stub createGeofencerCallbacks(final GmsConnector.Callback.ResultProvider resultProvider) {
+ return new IGeofencerCallbacks.Stub(){
+ @Override
+ public void onAddGeofenceResult(int statusCode, String[] requestIds) throws RemoteException {
+ resultProvider.onResultAvailable(new Status(statusCode));
+ }
+
+ @Override
+ public void onRemoveGeofencesByRequestIdsResult(int statusCode, String[] requestIds) throws RemoteException {
+ resultProvider.onResultAvailable(new Status(statusCode));
+ }
+
+ @Override
+ public void onRemoveGeofencesByPendingIntentResult(int statusCode, PendingIntent pendingIntent) throws RemoteException {
+ resultProvider.onResultAvailable(new Status(statusCode));
+ }
+ };
+ }
+
+ private PendingResult callGeofencer(GoogleApiClient client, final Runnable runnable) {
+ return GmsConnector.call(client, LocationServices.API, new GmsConnector.Callback() {
+ @Override
+ public void onClientAvailable(LocationClientImpl client, ResultProvider resultProvider) throws RemoteException {
+ runnable.run(client, createGeofencerCallbacks(resultProvider));
+ }
+ });
+ }
+
+ private interface Runnable {
+ void run(LocationClientImpl client, IGeofencerCallbacks callbacks) throws RemoteException;
+ }
}
diff --git a/play-services-location/src/main/java/org/microg/gms/location/LocationClientImpl.java b/play-services-location/src/main/java/org/microg/gms/location/LocationClientImpl.java
index e3593198..1d5f5b6c 100644
--- a/play-services-location/src/main/java/org/microg/gms/location/LocationClientImpl.java
+++ b/play-services-location/src/main/java/org/microg/gms/location/LocationClientImpl.java
@@ -25,14 +25,18 @@ import android.os.RemoteException;
import android.util.Log;
import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.location.GeofencingRequest;
import com.google.android.gms.location.ILocationListener;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
+import com.google.android.gms.location.internal.IGeofencerCallbacks;
+import com.google.android.gms.location.internal.ParcelableGeofence;
import org.microg.gms.common.api.GoogleApiClientImpl;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
public class LocationClientImpl extends GoogleLocationManagerClient {
@@ -42,7 +46,7 @@ public class LocationClientImpl extends GoogleLocationManagerClient {
public LocationClientImpl(Context context, GoogleApiClient.ConnectionCallbacks callbacks,
- GoogleApiClient.OnConnectionFailedListener connectionFailedListener) {
+ GoogleApiClient.OnConnectionFailedListener connectionFailedListener) {
super(context, callbacks, connectionFailedListener);
Log.d(TAG, "");
}
@@ -55,6 +59,38 @@ public class LocationClientImpl extends GoogleLocationManagerClient {
return null;
}
+ public void addGeofences(GeofencingRequest request, PendingIntent pendingIntent, IGeofencerCallbacks callbacks) throws RemoteException {
+ if (nativeLocation != null) {
+ nativeLocation.addGeofences(request, pendingIntent, callbacks);
+ } else {
+ getServiceInterface().addGeofences(request, pendingIntent, callbacks);
+ }
+ }
+
+ public void addGeofences(List request, PendingIntent pendingIntent, IGeofencerCallbacks callbacks) throws RemoteException {
+ if (nativeLocation != null) {
+ nativeLocation.addGeofences(request, pendingIntent, callbacks);
+ } else {
+ getServiceInterface().addGeofencesList(request, pendingIntent, callbacks, getContext().getPackageName());
+ }
+ }
+
+ public void removeGeofences(List geofenceRequestIds, IGeofencerCallbacks callbacks) throws RemoteException {
+ if (nativeLocation != null) {
+ nativeLocation.removeGeofences(geofenceRequestIds, callbacks);
+ } else {
+ getServiceInterface().removeGeofencesById(geofenceRequestIds.toArray(new String[geofenceRequestIds.size()]), callbacks, getContext().getPackageName());
+ }
+ }
+
+ public void removeGeofences(PendingIntent pendingIntent, IGeofencerCallbacks callbacks) throws RemoteException {
+ if (nativeLocation != null) {
+ nativeLocation.removeGeofences(pendingIntent, callbacks);
+ } else {
+ getServiceInterface().removeGeofencesByIntent(pendingIntent, callbacks, getContext().getPackageName());
+ }
+ }
+
public Location getLastLocation() throws RemoteException {
Log.d(TAG, "getLastLocation()");
if (nativeLocation != null) {
@@ -92,7 +128,7 @@ public class LocationClientImpl extends GoogleLocationManagerClient {
}
public void requestLocationUpdates(LocationRequest request, LocationListener listener,
- Looper looper) throws RemoteException {
+ Looper looper) throws RemoteException {
if (nativeLocation != null) {
nativeLocation.requestLocationUpdates(request, listener, looper);
}
diff --git a/play-services-location/src/main/java/org/microg/gms/location/NativeLocationClientImpl.java b/play-services-location/src/main/java/org/microg/gms/location/NativeLocationClientImpl.java
index 7555b806..158c8cc2 100644
--- a/play-services-location/src/main/java/org/microg/gms/location/NativeLocationClientImpl.java
+++ b/play-services-location/src/main/java/org/microg/gms/location/NativeLocationClientImpl.java
@@ -25,15 +25,29 @@ import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Looper;
+import android.os.RemoteException;
+import android.os.SystemClock;
import android.util.Log;
+import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.location.FusedLocationProviderApi;
+import com.google.android.gms.location.Geofence;
+import com.google.android.gms.location.GeofenceStatusCodes;
+import com.google.android.gms.location.GeofencingEvent;
+import com.google.android.gms.location.GeofencingRequest;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
+import com.google.android.gms.location.internal.IGeofencerCallbacks;
+import com.google.android.gms.location.internal.ParcelableGeofence;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import static android.location.LocationManager.KEY_LOCATION_CHANGED;
+import static android.location.LocationManager.KEY_PROXIMITY_ENTERING;
+
@SuppressWarnings("MissingPermission")
public class NativeLocationClientImpl {
private final static String TAG = "GmsToNativeLocClient";
@@ -71,6 +85,39 @@ public class NativeLocationClientImpl {
return criteria;
}
+ public void addGeofences(GeofencingRequest geofencingRequest, PendingIntent pendingIntent, IGeofencerCallbacks callbacks) throws RemoteException {
+ Log.d(TAG, "addGeofences(GeofencingRequest)");
+ callbacks.onAddGeofenceResult(GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE, new String[0]);
+ }
+
+ public void addGeofences(List geofences, PendingIntent pendingIntent, IGeofencerCallbacks callbacks) throws RemoteException {
+ Log.d(TAG, "addGeofences(List)");
+ Intent i = new Intent(context, NativePendingIntentForwarder.class);
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(EXTRA_PENDING_INTENT, pendingIntent);
+ i.putExtras(bundle);
+ nativePendingMap.put(pendingIntent, PendingIntent.getActivity(context, 0, i, 0));
+ List requestIds = new ArrayList();
+ for (ParcelableGeofence geofence : geofences) {
+ locationManager.addProximityAlert(geofence.latitude, geofence.longitude, geofence.radius,
+ geofence.expirationTime - SystemClock.elapsedRealtime(), nativePendingMap.get(pendingIntent));
+ requestIds.add(geofence.getRequestId());
+ }
+ callbacks.onAddGeofenceResult(CommonStatusCodes.SUCCESS, requestIds.toArray(new String[requestIds.size()]));
+ }
+
+ public void removeGeofences(List requestIds, IGeofencerCallbacks callbacks) throws RemoteException {
+ Log.d(TAG, "removeGeofences(List)");
+ callbacks.onRemoveGeofencesByRequestIdsResult(GeofenceStatusCodes.ERROR, requestIds.toArray(new String[requestIds.size()]));
+ }
+
+ public void removeGeofences(PendingIntent pendingIntent, IGeofencerCallbacks callbacks) throws RemoteException {
+ Log.d(TAG, "removeGeofences(PendingIntent)");
+ locationManager.removeProximityAlert(nativePendingMap.get(pendingIntent));
+ nativePendingMap.remove(pendingIntent);
+ callbacks.onRemoveGeofencesByPendingIntentResult(CommonStatusCodes.SUCCESS, pendingIntent);
+ }
+
public Location getLastLocation() {
Log.d(TAG, "getLastLocation()");
return locationManager.getLastKnownLocation(locationManager.getBestProvider(DEFAULT_CRITERIA, true));
@@ -131,11 +178,19 @@ public class NativeLocationClientImpl {
@Override
public void onReceive(Context context, Intent intent) {
- if (intent.hasExtra(LocationManager.KEY_LOCATION_CHANGED)) {
+ if (intent.hasExtra(KEY_PROXIMITY_ENTERING)) {
+ PendingIntent pendingIntent = intent.getExtras().getParcelable(EXTRA_PENDING_INTENT);
+ try {
+ intent.putExtra(GeofencingEvent.EXTRA_TRANSITION, intent.getBooleanExtra(KEY_PROXIMITY_ENTERING, false) ? Geofence.GEOFENCE_TRANSITION_ENTER : Geofence.GEOFENCE_TRANSITION_EXIT);
+ pendingIntent.send(context, 0, intent);
+ } catch (PendingIntent.CanceledException e) {
+ nativePendingMap.remove(pendingIntent);
+ }
+ } else if (intent.hasExtra(KEY_LOCATION_CHANGED)) {
PendingIntent pendingIntent = intent.getExtras().getParcelable(EXTRA_PENDING_INTENT);
try {
intent.putExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED,
- intent.getParcelableExtra(LocationManager.KEY_LOCATION_CHANGED));
+ intent.getParcelableExtra(KEY_LOCATION_CHANGED));
pendingIntent.send(context, 0, intent);
pendingCount.put(pendingIntent, pendingCount.get(pendingIntent) - 1);
if (pendingCount.get(pendingIntent) == 0) {