4

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.

  1. 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.

CoderBC
  • 1,262
  • 2
  • 13
  • 30

0 Answers0