Level
I am a beginner
Task
To run an android service that sends location updates (latitude, longitude) to a database periodically while a driver is driving (to track location) every 5mins. I want to update the database with location even if the app is not active, hence I decided to use the firebase job dispatcher.
Note
I have already seen several threads on how to do this using ALARM_MANAGER or broadcast receivers etc. I would like to know how to do this with a job dispatcher. My current code works but I am pretty sure its not the right way to go about it.
Questions
1. Where do I make a call to build the Googleapi and call the Connect() method? Right now, my scheduler calls a class 'onStart', which in turns performs the connection.
- Instead of using the jobScheduler is there any way in which I can use the 'Location Receiver' to do this as I read it takes a time interval, and returns the updated location by overwriting
onLocationChanged()
.
Currently Working Code
The firebase service:-
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import com.firebase.jobdispatcher.JobParameters;
import com.firebase.jobdispatcher.JobService;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;
public class GPSTracking extends JobService {
private AsyncTask mBackgroundTask;
public static final String LOG_TAG = "location-scheduler";
@Override
public boolean onStartJob(final JobParameters jobParameters) {
Log.i(LOG_TAG,"Scheduling");
mBackgroundTask = new AsyncTask() {
@Override
protected Object doInBackground(Object[] params) {
Context context = GPSTracking2.this;
LocationTracker.execute(context);
return null;
}
@Override
protected void onPostExecute(Object o) {
jobFinished(jobParameters, false);
}
};
mBackgroundTask.execute();
return true;
}
@Override
public boolean onStopJob(JobParameters jobParameters) {
if (mBackgroundTask != null) {
mBackgroundTask.cancel(true);
}
return true;
}
}
The actual tracking:-
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.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;
public class LocationTracker implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;
private Context context;
private static final String LOG_TAG="LOCATION TRACKER";
public LocationTracker(Context context){
this.context = context;
buildGoogleApiClient();
}
@Override
protected void finalize() throws Throwable {
super.finalize();
//Disconnect
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
public static void execute(Context context){
LocationTracker2 track = new LocationTracker2(context);
//connect
track.startConnection();
}
public void startConnection(){
mGoogleApiClient.connect();
}
private static void trackLocation(Location location) {
// To replace with updating database
if (location!=null) {
Log.i("TRACKING LAT", String.valueOf(location.getLatitude()));
Log.i("TRACKING LON", String.valueOf(location.getLongitude()));
}
else
{
Log.i("TRACKING LAT", "Null location received");
}
}
@Override
public void onConnected(@Nullable Bundle bundle) {
// Create new location request
// The permission should be granted previously
if (ActivityCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
trackLocation(mLastLocation);
}
@Override
public void onConnectionSuspended(int i) {
Log.i(LOG_TAG,"Connection suspended");
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Log.i(LOG_TAG,"Connection failed");
}
}
Inside Main, start the scheduling:
Driver driver = new GooglePlayDriver(context);
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(driver);
Job locationTrackerJob = dispatcher.newJobBuilder()
.setService(GPSTracking.class)
.setTag(JOB_TAG)
.setLifetime(Lifetime.FOREVER)
.setRecurring(true)
.setTrigger(Trigger.executionWindow(
REMINDER_INTERVAL_SECONDS,
REMINDER_INTERVAL_SECONDS + SYNC_FLEXTIME_SECONDS
))
.setReplaceCurrent(true)
.build();
dispatcher.schedule(locationTrackerJob);
NOTE
- You might have to add code to check for permissions depending on the api
- I am leaving out registering the service in Android manifest and dependency in build gradle.