Created
October 23, 2015 13:37
-
-
Save cyrixmorten/2c3bad07f0848ef5dd50 to your computer and use it in GitHub Desktop.
ReactiveLocation in Service
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
public class FusedLocationTrackerService extends InjectingService { | |
private static final String TAG = FusedLocationTrackerService.class.getSimpleName(); | |
public FusedLocationTrackerService() { | |
} | |
public static void start(Context context) { | |
Log.e(TAG, "startGPSTrackerService"); | |
context.startService(new Intent(context, FusedLocationTrackerService.class)); | |
} | |
public static void stop(Context context) { | |
context.stopService(new Intent(context, FusedLocationTrackerService.class)); | |
} | |
private static final int DISTANCE_METERS_FOR_GEOFENCEREBUILD = 1500; | |
private static final int DISTANCE_METERS_FOR_UIUPDATE = 20; | |
private Subscription locationSubscription; | |
private Location mLastGeofenceRebuildLocation; | |
private Location mLastUIUpdateLocation; | |
private LocationTracker locationTracker; | |
@Inject | |
GeofencingModule geofencingModule; | |
@Inject | |
GuardCache guardCache; | |
@Override | |
public void onCreate() { | |
Log.d(TAG, "GPSTrackerService onCreate"); | |
super.onCreate(); | |
} | |
@Override | |
public int onStartCommand(Intent intent, int flags, final int startId) { | |
Log.i(TAG, "Starting GPSTrackerService!"); | |
if (hasGooglePlayServices()) { | |
locationTracker = new LocationTracker(); | |
requestLocationUpdates(); | |
} | |
return Service.START_STICKY; | |
} | |
@Override | |
public IBinder onBind(Intent intent) { | |
return null; | |
} | |
@Override | |
public void onDestroy() { | |
Log.i(TAG, "Stopping GPSTrackerService"); | |
if (hasGooglePlayServices()) { | |
unsubscribeLocationUpdates(); | |
} | |
super.onDestroy(); | |
} | |
public void unsubscribeLocationUpdates() { | |
if (locationSubscription != null && !locationSubscription.isUnsubscribed()) { | |
Log.i(TAG, "Unsubscribe location updates"); | |
try { | |
locationSubscription.unsubscribe(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
locationSubscription = null; | |
} | |
} | |
private boolean hasGooglePlayServices() { | |
int result = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext()); | |
if (result != ConnectionResult.SUCCESS) { | |
return false; | |
} | |
return true; | |
} | |
private void requestLocationUpdates() { | |
Log.i(TAG, "requestLocationUpdates"); | |
unsubscribeLocationUpdates(); // in case we are already listening | |
LocationRequest request = LocationRequest.create() //standard GMS LocationRequest | |
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) | |
.setInterval(10000) | |
.setFastestInterval(5000); | |
ReactiveLocationProvider locationProvider = new ReactiveLocationProvider(getApplicationContext()); | |
locationSubscription = locationProvider.getUpdatedLocation(request) | |
.observeOn(Schedulers.from(Executors.newSingleThreadExecutor())) | |
.doOnError(new Action1<Throwable>() { | |
@Override | |
public void call(Throwable throwable) { | |
String message = "Error on location init: " + throwable.getMessage(); | |
Log.e(TAG, message, throwable); | |
Crashlytics.logException(throwable); | |
} | |
}) | |
.onErrorReturn(new Func1<Throwable, Location>() { | |
@Override | |
public Location call(Throwable throwable) { | |
Location location = new android.location.Location(""); | |
return location; | |
} | |
}) | |
.filter(new Func1<Location, Boolean>() { | |
@Override | |
public Boolean call(Location location) { | |
if (location.getAccuracy() > 30) { | |
return false; | |
} | |
return true; | |
} | |
}) | |
.subscribe(new Action1<Location>() { | |
@Override | |
public void call(Location location) { | |
if (guardCache.isLoggedIn()) { | |
LocationModule.Recent.setLastKnownLocation(location); | |
if (!rebuildGeofencesIfDistanceThresholdReached(location)) { | |
updateUIIfDistanceThresholdReached(location); | |
inspectDistanceToGeofencedTasks(location); | |
} | |
Guard guard = guardCache.getLoggedIn(); | |
locationTracker.appendLocation(getApplicationContext(), guard, location); | |
} else { | |
stopSelf(); | |
} | |
} | |
}); | |
} | |
private boolean rebuildGeofencesIfDistanceThresholdReached(Location location) { | |
float distance = Util.distanceMeters(mLastGeofenceRebuildLocation, location); | |
if (mLastGeofenceRebuildLocation == null || distance >= DISTANCE_METERS_FOR_GEOFENCEREBUILD) { | |
mLastGeofenceRebuildLocation = location; | |
RegisterGeofencesIntentService.start(getApplicationContext()); | |
return true; | |
} | |
return false; | |
} | |
private void updateUIIfDistanceThresholdReached(Location location) { | |
float distance = Util.distanceMeters(mLastUIUpdateLocation, location); | |
if (mLastUIUpdateLocation == null || distance >= DISTANCE_METERS_FOR_UIUPDATE) { | |
mLastUIUpdateLocation = location; | |
EventBusController.postUIUpdate(location); | |
} | |
} | |
private void inspectDistanceToGeofencedTasks(Location location) { | |
Set<GSTask> geofencedTasks = GeofencingModule.Recent.getAllGeofencedTasks(); | |
List<String> tasksWithinGeofence = Lists.newArrayList(); | |
List<String> tasksMovedWithinGeofence = Lists.newArrayList(); | |
List<String> tasksMovedOutsideGeofence = Lists.newArrayList(); | |
for (GSTask task: geofencedTasks) { | |
ParseGeoPoint clientPosition = task.getClientPosition(); | |
float distance = ParseModule.distanceBetweenMeters(location, clientPosition); | |
int radius = task.getGeofenceStrategy().getGeofenceRadius(); | |
if (distance <= radius) { | |
tasksWithinGeofence.add(task.getParseObject().getObjectId()); | |
} | |
if (GeofencingModule.Recent.getWithinGeofence().contains(task)) { | |
if (distance > radius) { | |
tasksMovedOutsideGeofence.add(task.getParseObject().getObjectId()); | |
} | |
} else { | |
if (distance < radius) { | |
tasksMovedWithinGeofence.add(task.getParseObject().getObjectId()); | |
} | |
} | |
} | |
geofencingModule.onWithinGeofences(tasksWithinGeofence.toArray(new String[tasksWithinGeofence.size()])); | |
geofencingModule.onEnteredGeofences(tasksMovedWithinGeofence.toArray(new String[tasksMovedWithinGeofence.size()]), true); | |
geofencingModule.onExitedGeofences(tasksMovedOutsideGeofence.toArray(new String[tasksMovedOutsideGeofence.size()]), true); | |
} | |
} |
@farmazon3000 InjectingService
is simple android Service
@cyrixmorten used dependency injection dagger framework.
If I have time I will publish in github new project with examples of service for continuous location monitoring..
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@cyrixmorten Can you please give more light on what this Service is intended to do, I'm doing similar stuff, I may share my experience with you.
What is
InjectingService
? And what isRegisterGeofencesIntentService
?