Skip to content

Commit

Permalink
updated location probe to use fused provider
Browse files Browse the repository at this point in the history
  • Loading branch information
h0pbeat committed Jan 9, 2016
1 parent 9ebaac9 commit 3c5abc0
Showing 1 changed file with 129 additions and 135 deletions.
264 changes: 129 additions & 135 deletions funf_v4/src/main/java/edu/mit/media/funf/probe/builtin/LocationProbe.java
Original file line number Diff line number Diff line change
@@ -1,41 +1,21 @@
/**
*
* Funf: Open Sensing Framework
* Copyright (C) 2010-2011 Nadav Aharony, Wei Pan, Alex Pentland.
* Acknowledgments: Alan Gardner
* Contact: [email protected]
*
* This file is part of Funf.
*
* Funf is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Funf is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Funf. If not, see <http://www.gnu.org/licenses/>.
*
*/
package edu.mit.media.funf.probe.builtin;

import java.lang.reflect.Field;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.JsonObject;

import android.location.Location;
import android.os.Bundle;
import android.util.Log;

import edu.mit.media.funf.Schedule;
import edu.mit.media.funf.config.Configurable;
import edu.mit.media.funf.probe.Probe.Base;
Expand All @@ -46,146 +26,160 @@
import edu.mit.media.funf.probe.Probe.RequiredPermissions;
import edu.mit.media.funf.probe.builtin.ProbeKeys.LocationKeys;
import edu.mit.media.funf.time.DecimalTimeUnit;
import edu.mit.media.funf.util.LogUtil;

/**
* Sends all location points gathered by system.
* @author alangardner
*
* Updated location probe using fused location provider.
* Supports both active schedule and passive mode.
* @author [email protected]
*/
@DisplayName("Continuous Location Probe")
@DisplayName("Location Probe")
@RequiredPermissions({android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION})
@RequiredFeatures("android.hardware.location")
@Schedule.DefaultSchedule(interval=1800)
public class LocationProbe extends Base implements ContinuousProbe, PassiveProbe, LocationKeys {
public class LocationProbe extends Base implements ContinuousProbe, PassiveProbe, LocationKeys,
ConnectionCallbacks, OnConnectionFailedListener {

@Configurable
private boolean useGps = true;

@Configurable
private boolean useNetwork = true;

private Integer passiveInterval = 60;

@Configurable
private boolean useCache = true;
private Integer activeInterval = 5;

private Gson gson;
private LocationManager mLocationManager;
private LocationListener listener = new ProbeLocationListener();
private LocationListener passiveListener = new ProbeLocationListener();


private LocationRequest mLocationRequest;
private LocationRequest mLocationRequestPassive;
private GoogleApiClient mGoogleApiClient;
private ProbeLocationListener listener = new ProbeLocationListener();
private ProbeLocationListener passiveListener = new ProbeLocationListener();

private boolean toStartActiveMode = false;

@Override
protected void onEnable() {
super.onEnable();
gson = getGsonBuilder().addSerializationExclusionStrategy(new LocationExclusionStrategy()).create();
mLocationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
String passiveProvider = getPassiveProvider();
if (passiveProvider != null) {
mLocationManager.requestLocationUpdates(getPassiveProvider(), 0, 0, passiveListener);
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(getContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}

toStartActiveMode = false;

mLocationRequestPassive = new LocationRequest();
mLocationRequestPassive.setInterval(passiveInterval*1000);
mLocationRequestPassive.setFastestInterval(passiveInterval*1000);
mLocationRequestPassive.setPriority(LocationRequest.PRIORITY_NO_POWER);

mGoogleApiClient.connect();

}

@Override
protected void onStart() {
super.onStart();
if (useGps) {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
private class LocationExclusionStrategy implements ExclusionStrategy {

public boolean shouldSkipClass(Class<?> cls) {
return false;
}
if (useNetwork) {
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);

public boolean shouldSkipField(FieldAttributes f) {
String name = f.getName();
return (f.getDeclaringClass() == Location.class &&
(name.equals("mResults")
|| name.equals("mDistance")
|| name.equals("mInitialBearing")
|| name.equals("mLat1")
|| name.equals("mLat2")
|| name.equals("mLon1")
|| name.equals("mLon2")
|| name.equals("mLon2")
|| name.equals("mHasSpeed")
|| name.equals("mHasAccuracy")
|| name.equals("mHasAltitude")
|| name.equals("mHasBearing")
|| name.equals("mHasSpeed")
|| name.equals("mElapsedRealtimeNanos")
)
);
}
if (useCache) {
listener.onLocationChanged(mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER));
listener.onLocationChanged(mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER));

}

private class ProbeLocationListener implements LocationListener {

@Override
public void onLocationChanged(Location location) {
if (location != null) {
JsonObject data = gson.toJsonTree(location).getAsJsonObject();
data.addProperty(TIMESTAMP, DecimalTimeUnit.MILLISECONDS.toSeconds(data.get("mTime").getAsBigDecimal()));
sendData(gson.toJsonTree(location).getAsJsonObject());
}

}
if (!useGps && ! useNetwork) {
stop();
}

@Override
protected void onStart() {
super.onStart();

toStartActiveMode = true;

mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(activeInterval * 1000);
mLocationRequest.setFastestInterval(activeInterval * 1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest,
listener);
toStartActiveMode = false;
} else {
mGoogleApiClient.connect();
}



}

@Override
protected void onStop() {
super.onStop();
mLocationManager.removeUpdates(listener);
toStartActiveMode = false;
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, listener);
}

@Override
protected void onDisable() {
super.onDisable();
mLocationManager.removeUpdates(passiveListener);
}

private class ProbeLocationListener implements LocationListener{

@Override
public void onLocationChanged(Location location) {
if (location != null) {
String provider = location.getProvider();
if (provider == null
|| (useGps && LocationManager.GPS_PROVIDER.equals(provider))
|| (useNetwork && LocationManager.NETWORK_PROVIDER.equals(provider))) {
JsonObject data = gson.toJsonTree(location).getAsJsonObject();
data.addProperty(TIMESTAMP, DecimalTimeUnit.MILLISECONDS.toSeconds(data.get("mTime").getAsBigDecimal()));
sendData(gson.toJsonTree(location).getAsJsonObject());
}
}
if (!mGoogleApiClient.isConnected()) {
return;
}
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, passiveListener);
mGoogleApiClient.disconnect();
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
@Override
public void onConnected(Bundle bundle) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
mLocationRequestPassive, passiveListener);
if (toStartActiveMode) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest,
listener);
toStartActiveMode = false;
}
}

@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onConnectionSuspended(int i) {

@Override
public void onProviderDisabled(String provider) {
}

}

public class LocationExclusionStrategy implements ExclusionStrategy {

public boolean shouldSkipClass(Class<?> cls) {
return false;
}

public boolean shouldSkipField(FieldAttributes f) {
String name = f.getName();
return (f.getDeclaringClass() == Location.class &&
(name.equals("mResults")
|| name.equals("mDistance")
|| name.equals("mInitialBearing")
|| name.equals("mLat1")
|| name.equals("mLat2")
|| name.equals("mLon1")
|| name.equals("mLon2")
|| name.equals("mLon2")
|| name.equals("mHasSpeed")
|| name.equals("mHasAccuracy")
|| name.equals("mHasAltitude")
|| name.equals("mHasBearing")
|| name.equals("mHasSpeed")
|| name.equals("mElapsedRealtimeNanos")
)
);
}

}

/**
* Supporting API level 7 which does not have PASSIVE provider
* @return
*/
private String getPassiveProvider() {
try {
Field passiveProviderField = LocationManager.class.getDeclaredField("PASSIVE_PROVIDER");
return (String)passiveProviderField.get(null);
} catch (SecurityException e) {
} catch (NoSuchFieldException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
return null;

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {

}

}

0 comments on commit 3c5abc0

Please sign in to comment.