-
-
Save MehdiFal/6ae11fd67473d488e659ea347e522945 to your computer and use it in GitHub Desktop.
This file contains 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
import android.Manifest; | |
import android.annotation.SuppressLint; | |
import android.app.Activity; | |
import android.content.Context; | |
import android.content.pm.PackageManager; | |
import android.location.Location; | |
import android.os.Bundle; | |
import android.support.annotation.NonNull; | |
import android.support.v4.app.ActivityCompat; | |
import com.corelib.utils.Logger; | |
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 java.util.Calendar; | |
import java.util.Date; | |
public class GeoLocService implements ConnectionCallbacks, | |
OnConnectionFailedListener, | |
LocationListener { | |
// The desired interval for location updates. Inexact. Updates may be more or less frequent. | |
private final static long UPDATE_INTERVAL_IN_MILLISECONDS = 1000; | |
//The fastest rate for active location updates. Exact Updates will never be more frequent than this value. | |
private final static long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2; | |
private GoogleApiClient googleApiClient; | |
private LocationRequest locationRequest; | |
private LocationResponse locationResponse; | |
private Location currentLocation; | |
public GeoLocService (Context context, LocationResponse locationResponse) { | |
this.locationResponse = locationResponse; | |
googleApiClient = new GoogleApiClient.Builder (context) | |
.addConnectionCallbacks (this) | |
.addOnConnectionFailedListener (this) | |
.addApi (LocationServices.API) | |
.build (); | |
createLocationRequest (); | |
} | |
public void onStart () { | |
if (googleApiClient != null) { | |
googleApiClient.connect (); | |
} | |
} | |
// Within onPause(), we pause location updates, but leave the | |
// connection to GoogleApiClient intact. Here, we resume receiving | |
// location updates if the user has requested them. | |
public void onResume () { | |
if (googleApiClient != null && googleApiClient.isConnected ()) { | |
startLocationUpdates (); | |
} | |
} | |
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object. | |
public void onPause () { | |
if (googleApiClient != null && googleApiClient.isConnected ()) { | |
stopLocationUpdates (); | |
} | |
} | |
public void disconnect () { | |
if (googleApiClient != null) { | |
if (googleApiClient.isConnected ()) { | |
stopLocationUpdates (); | |
} | |
googleApiClient.disconnect (); | |
} | |
} | |
protected void createLocationRequest() { | |
locationRequest = new LocationRequest(); | |
// Sets the desired interval for active location updates. This interval is | |
// inexact. You may not receive updates at all if no location sources are available, or | |
// you may receive them slower than requested. You may also receive updates faster than | |
// requested if other applications are requesting location at a faster interval. | |
locationRequest.setInterval (UPDATE_INTERVAL_IN_MILLISECONDS); | |
// Sets the fastest rate for active location updates. This interval is exact, and your | |
// application will never receive updates faster than this value. | |
locationRequest.setFastestInterval (FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS); | |
locationRequest.setPriority (LocationRequest.PRIORITY_HIGH_ACCURACY); | |
} | |
// Requests location updates from the FusedLocationApi. | |
@SuppressLint("MissingPermission") | |
public void startLocationUpdates () { | |
Logger.info (GeoLocService.class.getSimpleName () + "-- startLocationUpdates", "Got into the startLocationUpdates"); | |
LocationServices.FusedLocationApi.requestLocationUpdates (googleApiClient, locationRequest, this); | |
} | |
// Removes location updates from the FusedLocationApi. | |
// It is a good practice to remove location requests when the activity is in a paused or | |
// stopped state. Doing so helps battery performance and is especially | |
// recommended in applications that request frequent location updates. | |
public void stopLocationUpdates() { | |
Logger.info (GeoLocService.class.getSimpleName () + "-- stopLocationUpdates", "Got into the stopLocationUpdates"); | |
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this); | |
} | |
// Runs when a GoogleApiClient object successfully connects. | |
@SuppressLint ("MissingPermission") | |
@Override | |
public void onConnected(Bundle connectionHint) { | |
Logger.info (GeoLocService.class.getSimpleName () + "-- Success", "Connected to GoogleApiClient"); | |
// If the initial location was never previously requested, we use | |
// FusedLocationApi.getLastLocation() to get it. If it was previously requested, we store | |
// its value in the Bundle and check for it in onCreate(). We | |
// do not request it again unless the user specifically requests location updates by pressing | |
// the Start Updates button. | |
// Because we cache the value of the initial location in the Bundle, it means that if the | |
// user launches the activity, | |
// moves to a new location, and then changes the device orientation, the original location | |
// is displayed as the activity is re-created. | |
if (currentLocation == null) { | |
currentLocation = LocationServices.FusedLocationApi.getLastLocation (googleApiClient); | |
sendUpdates (); | |
} | |
// If the user presses the Start Updates button before GoogleApiClient connects, we set | |
// mRequestingLocationUpdates to true (see startUpdatesButtonHandler()). Here, we check | |
// the value of mRequestingLocationUpdates and if it is true, we start location updates. | |
startLocationUpdates (); | |
} | |
private void sendUpdates () { | |
Logger.info (GeoLocService.class.getSimpleName () + "-- sendUpdates", "Got into the sendUpdates"); | |
if (locationResponse != null && currentLocation != null) { | |
Logger.info (GeoLocService.class.getSimpleName () + "-- SendUpdates", | |
"Retrieved Loc : " + currentLocation.getLatitude () + " : " + currentLocation.getLongitude () | |
); | |
locationResponse.onLocation (currentLocation); | |
} | |
} | |
// Callback that fires when the location changes. | |
@Override | |
public void onLocationChanged (Location location) { | |
double speed = calculateDistance (location, currentLocation); | |
currentLocation = location; | |
currentLocation.setSpeed ((float) speed); | |
lastUpdateTime = Calendar.getInstance ().getTime (); | |
Logger.info (GeoLocService.class.getSimpleName () + "-- OnLocChanged", "Got into the OnlocationChanged"); | |
sendUpdates (); | |
} | |
@Override | |
public void onConnectionSuspended (int cause) { | |
// The connection to Google Play services was lost for some reason. We call connect() to | |
// attempt to re-establish the connection. | |
Logger.error (GeoLocService.class.getSimpleName () + "-- Error", "Connection suspended"); | |
googleApiClient.connect (); | |
} | |
@Override | |
public void onConnectionFailed (@NonNull ConnectionResult result) { | |
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in onConnectionFailed. | |
Logger.error (GeoLocService.class.getSimpleName () + "-- Error", "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode()); | |
if (locationResponse != null) { | |
locationResponse.onFailure (result.getErrorCode ()); | |
} | |
} | |
// TODO : IMPORTANT !!!! make it blocking UI Rendering....... | |
public static boolean checkLocationPerms (Activity context) { | |
if (ActivityCompat.checkSelfPermission (context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED | |
&& ActivityCompat.checkSelfPermission (context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { | |
ActivityCompat.requestPermissions ( | |
context, | |
new String [] { | |
Manifest.permission.ACCESS_FINE_LOCATION, | |
Manifest.permission.ACCESS_COARSE_LOCATION, | |
Manifest.permission.ACCESS_NETWORK_STATE | |
}, | |
1000 | |
); | |
return false; | |
} | |
return true; | |
} | |
public GoogleApiClient getGoogleApiClient () { | |
return googleApiClient; | |
} | |
public interface LocationResponse { | |
void onLocation (Location location); | |
void onFailure (int errorCode); | |
} | |
} |
This file contains 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
import android.location.Location; | |
import android.os.Bundle; | |
import android.support.annotation.NonNull; | |
import android.view.View; | |
import android.widget.TextView; | |
import com.corelib.services.GeoLocService; | |
import com.corelib.utils.Json; | |
import com.corelib.utils.Lang; | |
import com.corelib.utils.Logger; | |
import com.corelib.workers.LocalWorker; | |
import com.corelib.workers.callbacks.impls.SimpleLocalWorkerCallback; | |
import com.fasterxml.jackson.databind.JsonNode; | |
import com.fasterxml.jackson.databind.node.ObjectNode; | |
import java.io.IOException; | |
public abstract class LocationActivity extends BaseActivity { | |
protected final static String Latitude = "latitude"; | |
protected final static String Longitude = "longitude"; | |
protected final static String LastLocation = "lastLocation"; | |
private GeoLocService locationService; | |
protected Location lastPosition; | |
@Override | |
protected void onCreate (Bundle savedInstanceState) { | |
super.onCreate (savedInstanceState); | |
if (enableLocTrack ()) { | |
if (GeoLocService.checkLocationPerms (this)) { | |
initLocService (); | |
} | |
initLastKnownLocation (); | |
} | |
} | |
@Override | |
protected void onStart () { | |
super.onStart (); | |
if (enableLocTrack ()) { | |
if (locationService != null) { | |
locationService.onStart (); | |
} | |
} | |
} | |
@Override | |
public void onRequestPermissionsResult (int requestCode, @NonNull String [] permissions, @NonNull int[] grantResults) { | |
super.onRequestPermissionsResult (requestCode, permissions, grantResults); | |
if (requestCode == PermReqCode) { | |
if (enableLocTrack ()) { | |
if (GeoLocService.checkLocationPerms (this)) { | |
initLocService (); | |
locationService.onStart (); | |
} | |
} | |
} | |
} | |
@Override | |
protected void onResume () { | |
super.onResume (); | |
if (enableLocTrack ()) { | |
if (locationService != null) { | |
locationService.onResume (); | |
} | |
initLastKnownLocation (); | |
} | |
} | |
@Override | |
protected void onPause () { | |
super.onPause (); | |
if (enableLocTrack ()) { | |
if (locationService != null) { | |
locationService.onPause (); | |
} | |
persistLastKnownLocation (); | |
} | |
} | |
@Override | |
protected void onStop () { | |
if (enableLocTrack ()) { | |
if (locationService != null) { | |
locationService.disconnect (); | |
} | |
} | |
super.onStop (); | |
} | |
private void initLastKnownLocation () { | |
localWorker.get ( | |
LastLocation, | |
LocalWorker.RootAppPrefs, | |
LocalWorker.Repo.Preferences, | |
LocalWorker.Type.Json, | |
new SimpleLocalWorkerCallback () { | |
@Override | |
public void onUISuccess (Object response) { | |
createLocation ((JsonNode)response); | |
onLocationSuccess (lastPosition, false); | |
} | |
} | |
); | |
} | |
protected void fetchLastKnownLocation () { | |
try { | |
JsonNode localLoc = (JsonNode)localWorker.get (LastLocation, LocalWorker.RootAppPrefs, LocalWorker.Repo.Preferences); | |
createLocation (localLoc); | |
} catch (IOException e) { | |
Logger.error (LocationActivity.class.getSimpleName () + " --> getLastKnownLocation", e); | |
} | |
} | |
private void createLocation (JsonNode response) { | |
lastPosition = new Location (Lang.EMPTY); | |
if (response == null) { | |
lastPosition.setLatitude (0); | |
lastPosition.setLongitude (0); | |
return; | |
} | |
lastPosition.setLatitude (response.get ("latitude").asDouble (0)); | |
lastPosition.setLongitude (response.get ("longitude").asDouble (0)); | |
} | |
private void persistLastKnownLocation () { | |
if (lastPosition == null) { | |
lastPosition = new Location (Lang.EMPTY); | |
lastPosition.setLatitude (0); | |
lastPosition.setLongitude (0); | |
} | |
ObjectNode node = Json.createObject (); | |
node.put (Latitude, lastPosition.getLatitude ()); | |
node.put (Longitude, lastPosition.getLongitude ()); | |
// store in SharedPrefs | |
localWorker.post ( | |
LastLocation, | |
LocalWorker.RootAppPrefs, | |
LocalWorker.Repo.Preferences, | |
LocalWorker.Type.Json, | |
node, | |
new SimpleLocalWorkerCallback () | |
); | |
} | |
private void initLocService () { | |
GeoLocService.LocationResponse response = new GeoLocService.LocationResponse () { | |
@Override | |
public void onLocation (final Location location) { | |
lastPosition = location; | |
onLocationSuccess (location, true); | |
} | |
@Override | |
public void onFailure (int errorCode) { | |
onLocationFailure (errorCode); | |
} | |
}; | |
locationService = new GeoLocService (getApplicationContext (), response); | |
} | |
protected void stopFetchingLocations () { | |
if (locationService != null) { | |
locationService.stopLocationUpdates (); | |
locationService.disconnect (); | |
} | |
} | |
protected GeoLocService getLocationService () { | |
return locationService; | |
} | |
public Location getLastPosition () { | |
return lastPosition; | |
} | |
protected abstract void onLocationSuccess (Location location, boolean gps); | |
protected abstract void onLocationFailure (int errorCode); | |
protected abstract boolean enableLocTrack (); | |
protected abstract boolean requestLocPerm (); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment