Last active
April 24, 2019 14:58
-
-
Save ishmaelmakitla/40efa5a37849299dde64d6a397cbbb84 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package <your package>; | |
import java.util.ArrayList; | |
import org.json.JSONException; | |
import org.json.JSONObject; | |
import za.co.smartcitizens.trafficlights.spotter.models.LastKnownUserPosition; | |
import za.co.smartcitizens.trafficlights.spotter.models.TrafficLightIntersectionGeofence; | |
import android.content.Context; | |
import android.content.SharedPreferences; | |
import android.content.SharedPreferences.Editor; | |
import android.location.Location; | |
import android.os.Bundle; | |
import android.preference.PreferenceManager; | |
import android.util.Log; | |
import android.widget.Toast; | |
import com.google.android.gms.common.ConnectionResult; | |
import com.google.android.gms.common.api.GoogleApiClient; | |
import com.google.android.gms.location.LocationListener; | |
import com.google.android.gms.location.LocationRequest; | |
import com.google.android.gms.location.LocationServices; | |
/** | |
* This utility class is used to provide functionality to detect distance movement for the user so as to automatically refresh the geofences | |
* closest to the user. This provides a fairly good example of how to use LocationListener in a utility class (not an Activity). | |
* @author Ishmael Makitla | |
http://ishLema.co.za | |
* | |
*/ | |
public class TrafficLightSpotterUserLocationUtils implements LocationListener{ | |
private static final String TAG = TrafficLightSpotterUserLocationUtils.class.getSimpleName(); | |
private static final String SHARED_PREFERENCES_LAST_LOCATION_KEY = "lastLocation"; | |
private static final int SIGNIFICANT_DISPLACEMENT_THRESHOLD = 5; //5 km distance | |
private Context context; | |
private GoogleApiClient googleApiClient; | |
private Gson gson; | |
private SharedPreferences prefs; | |
private GeofenceRefreshRequestListener geofenceRefreshRequestListener; | |
private static TrafficLightSpotterUserLocationUtils INSTANCE; | |
public static TrafficLightSpotterUserLocationUtils getInstance(){ | |
if(INSTANCE == null){ INSTANCE = new TrafficLightSpotterUserLocationUtils(); } | |
return INSTANCE; | |
} | |
public void init(Context ctx, GoogleApiClient connectedGoogleAPIClient, GeofenceRefreshRequestListener refreshRequestListener){ | |
this.context = ctx; | |
this.googleApiClient = connectedGoogleAPIClient; | |
this.geofenceRefreshRequestListener = refreshRequestListener; | |
prefs = PreferenceManager.getDefaultSharedPreferences(context); | |
requestLocationUpdates(); | |
} | |
/** | |
* Helper method to connect the Google API Client | |
*/ | |
private void requestLocationUpdates() { | |
Log.i(TAG,"requestLocationUpdates"); | |
try{ | |
LocationRequest locationRequest = LocationRequest.create(); | |
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); | |
locationRequest.setInterval(180000); // update every (3) minutes | |
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this); | |
} | |
catch(Exception e){ | |
Log.e(TAG, "Error at requestLocationUpdates. ", e); | |
} | |
} | |
@Override | |
public void onLocationChanged(Location location) { | |
if(location == null){ return; } | |
Log.i(TAG, "onLocationChanged. Lat "+location.getLatitude()+" , Lon: "+location.getLongitude()); | |
//retrieve last-known location (if it does not exist, then this is the first time we get location updates | |
processLocationChange(location); | |
} | |
/** | |
* This method measures the distance between the last known location of the user and the current on. | |
* It does this to calculate how far the user has moved so that it can update the geofences it setups. | |
* | |
* @param currentLocation - the most recent user location | |
*/ | |
private void processLocationChange(Location currentLocation){ | |
if(currentLocation == null){return;} | |
LastKnownUserPosition userPreviousPosition = getLastKnownUserLocation(); | |
if(userPreviousPosition == null){ | |
//Cannot compare, set this as current location | |
setNewUserPosition(currentLocation); | |
return; | |
} | |
float[] results = new float[3]; | |
Location.distanceBetween(currentLocation.getLatitude(), currentLocation.getLongitude(), userPreviousPosition.getLatitude(), userPreviousPosition.getLongitude(), results); | |
float distance = (results.length > 0 ? results[0]: 0); | |
if( (distance/1000) >= SIGNIFICANT_DISPLACEMENT_THRESHOLD){ | |
//the user has moved quite a distance | |
Log.i(TAG, "User has moved "+(distance/1000)+"km. It Is Necessary To Refreshe Geofences."); | |
//set as new location | |
setNewUserPosition(currentLocation); | |
//notify the listener | |
if(geofenceRefreshRequestListener != null){ geofenceRefreshRequestListener.onGeofenceRefreshRequired(currentLocation); } | |
} | |
else{ | |
Log.i(TAG, "Distance "+(distance/1000)+"km Too Small To Refreshe Geofence. Ignore"); | |
} | |
} | |
/** | |
* | |
* @return | |
*/ | |
private LastKnownUserPosition getLastKnownUserLocation(){ | |
LastKnownUserPosition lastKnownLocation = null; | |
try{ | |
String lastPositionString = prefs.getString(SHARED_PREFERENCES_LAST_LOCATION_KEY, null); | |
if(lastPositionString !=null && !lastPositionString.trim().isEmpty()){ | |
lastKnownLocation = LastKnownUserPosition.asLastKnownUserPosition(lastPositionString); | |
} | |
} | |
catch(Exception e){ | |
Log.e(TAG, "Error at getLastKnownUserLocation. ", e); | |
} | |
return lastKnownLocation; | |
} | |
/** | |
* Record the current location. This is only done when the displacement is above threshold | |
* @param newLocation | |
*/ | |
private void setNewUserPosition(final Location newLocation){ | |
LastKnownUserPosition currentPosition = new LastKnownUserPosition(newLocation.getLatitude(), newLocation.getLongitude()); | |
try{ | |
Editor editor = prefs.edit(); | |
editor.putString(SHARED_PREFERENCES_LAST_LOCATION_KEY, currentPosition.toString()); | |
editor.apply(); | |
} | |
catch(Exception e){ | |
Log.e(TAG, "Error at setNewUserPosition. ", e); | |
} | |
try { | |
//do something...in my case I was updating the list of users who should receive alerts; | |
} | |
catch (JSONException jse) { | |
Log.e(TAG, "Error While Updating Alert Subscription. ", jse); | |
} | |
catch(Exception e){ | |
Log.e(TAG, "Error While Updating Alert Subscription. ", e); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment