Add Geofencing API client code

This commit is contained in:
Marvin W 2017-02-11 02:14:16 +01:00
parent 3eac7fc77f
commit aec1ad93b8
No known key found for this signature in database
GPG Key ID: 072E9235DB996F2A
6 changed files with 218 additions and 6 deletions

2
extern/GmsApi vendored

@ -1 +1 @@
Subproject commit c61a147de29456270bce1203c9f6700268b068c5
Subproject commit 3f1fa81390d67053d3aa50b0bc3537953396bcf6

View File

@ -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.
* <p>
* The methods must be used in conjunction with a GoogleApiClient. E.g.
* <pre>
* new GoogleApiClient.Builder(context)
* .addApi(LocationServices.API)
* .addConnectionCallbacks(this)
* .addOnConnectionFailedListener(this)
* .build()
* </pre>
*/
public interface GeofencingApi {
PendingResult<Status> addGeofences(GoogleApiClient client, GeofencingRequest geofencingRequest, PendingIntent pendingIntent);
@Deprecated
PendingResult<Status> addGeofences(GoogleApiClient client, List<Geofence> geofences, PendingIntent pendingIntent);
PendingResult<Status> removeGeofences(GoogleApiClient client, List<String> geofenceRequestIds);
PendingResult<Status> removeGeofences(GoogleApiClient client, PendingIntent pendingIntent);
}

View File

@ -137,5 +137,4 @@ public class FusedLocationProviderApiImpl implements FusedLocationProviderApi {
private interface Runnable {
void run(LocationClientImpl client) throws RemoteException;
}
}

View File

@ -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<Status> 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<Status> addGeofences(GoogleApiClient client, final List<Geofence> geofences, final PendingIntent pendingIntent) {
final List<ParcelableGeofence> geofenceList = new ArrayList<ParcelableGeofence>();
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<Status> removeGeofences(GoogleApiClient client, final List<String> geofenceRequestIds) {
return callGeofencer(client, new Runnable() {
@Override
public void run(LocationClientImpl client, IGeofencerCallbacks callbacks) throws RemoteException {
client.removeGeofences(geofenceRequestIds, callbacks);
}
});
}
@Override
public PendingResult<Status> 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<Status> 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<Status> callGeofencer(GoogleApiClient client, final Runnable runnable) {
return GmsConnector.call(client, LocationServices.API, new GmsConnector.Callback<LocationClientImpl, Status>() {
@Override
public void onClientAvailable(LocationClientImpl client, ResultProvider<Status> resultProvider) throws RemoteException {
runnable.run(client, createGeofencerCallbacks(resultProvider));
}
});
}
private interface Runnable {
void run(LocationClientImpl client, IGeofencerCallbacks callbacks) throws RemoteException;
}
}

View File

@ -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, "<init>");
}
@ -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<ParcelableGeofence> 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<String> 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);
}

View File

@ -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<ParcelableGeofence> geofences, PendingIntent pendingIntent, IGeofencerCallbacks callbacks) throws RemoteException {
Log.d(TAG, "addGeofences(List<ParcelableGeofence>)");
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<String> requestIds = new ArrayList<String>();
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<String> requestIds, IGeofencerCallbacks callbacks) throws RemoteException {
Log.d(TAG, "removeGeofences(List<RequestId>)");
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) {