Teddy13
Teddy13

Reputation: 3854

Receive GPS Location updates in background

I am brand new to Android, migrating from iOS. I am developing a fitness app (4.3+) that calculates the users location and tracks it. Everything is working great, except when the app goes into the background, I stop receiving location updates.

I am currently using a BroadcastReceiver from my GPSManager class to the UserFitness class. In the GPSManager class, I get the LocationManager started and everything else including starting location updates. It then gets broadcasted to the UserFitness class every time a new location update is available and some calculation is done here, stored, and displayed to the user. I have researched that I need to implement a Service for the LocationManager to work in the background but I am not sure how to implement it for my current code. All my code is below.

Can anyone tell me how to get location updates in the background based on my code and whether this is possible for about 4 hours at a time without the system destroying the process? And if the system does destroy it, what can be done to get the process back to it's previous state ASAP?

Thank you!


CODE

GPSManager.java

public class GPSManager{

private static final String TAG = "GPSManager";
public static final String ACTION_LOCATION = "com.fitnesstracker.ACTION_LOCATION";

private static GPSManager sGPSManager;
private Context mAppContext;
private LocationManager mLocationManager;
private Location mLastLocation;

private GPSManager (Context appContext,GpsStatus.Listener listen)
{
    mAppContext = appContext;
    mLocationManager = (LocationManager) mAppContext.getSystemService(Context.LOCATION_SERVICE);
    mLocationManager.addGpsStatusListener(listen);
}

public static GPSManager get (Context c,GpsStatus.Listener listen)
{
    if (sGPSManager == null)
    {
        //USE THE APPLICATION CONTEXT TO AVOID LEAKING ACTIVITIES
        sGPSManager = new GPSManager(c,listen);
    }
    return sGPSManager;
}

private PendingIntent getLocationPendingIntent (boolean shouldCreate)
{
    Intent broadcast = new Intent(ACTION_LOCATION);
    int flags = shouldCreate ? 0 : PendingIntent.FLAG_NO_CREATE;

    return PendingIntent.getBroadcast(mAppContext, 0, broadcast, flags);
}

public void startLocationUpdates()
{
    String provider = LocationManager.GPS_PROVIDER;

    //GET LAST KNOWN LOCATION AND BROADCAST IF THERE IS ONE

    mLastLocation = mLocationManager.getLastKnownLocation(provider);
    if (mLastLocation != null)
    {
        mLastLocation.setTime(System.currentTimeMillis());
        broadcastLocation(mLastLocation);
    }

    //START UPDATES FROM LOCATION MANAGER
    PendingIntent pi = getLocationPendingIntent(true);
    mLocationManager.requestLocationUpdates(provider,0,0,pi);
}

private void broadcastLocation (Location location)
{
    Intent broadcast = new Intent(ACTION_LOCATION);
    broadcast.putExtra(LocationManager.KEY_LOCATION_CHANGED, location);
    mAppContext.sendBroadcast(broadcast);
}

public void stopLocationUpdates()
{
    PendingIntent pi = getLocationPendingIntent(false);

    if (pi != null)
    {
        mLocationManager.removeUpdates(pi);
        pi.cancel();
    }
}
}

UserFitness.java

public class UserFitness extends Activity  {

private GPSManager mGPSManager;
private Location mLastLocation;
private boolean isGPSReady;
private float mLastLocationMillis;

private GpsStatus.Listener mGPSListener = new GpsStatus.Listener()
{
    public void onGpsStatusChanged(int event) {
        switch (event) {
            case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
             if (mLastLocation != null)

             isGPSReady = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 13000;

             if (isGPSReady) { // A fix has been acquired.
                calculateUserDistance()
            } else { // The fix has been lost.
                Toast.makeText(getApplicationContext(), "GPS Signal Fix Lost", Toast.LENGTH_SHORT).show();
            }
            break;
            case GpsStatus.GPS_EVENT_FIRST_FIX:

            isGPSReady = true;
            break;
        }
    }
};

private BroadcastReceiver mLocationReceiver = new LocationReceiver()
{
    @Override
    protected void onLocationReceived (Context context, Location loc)
    {
        mLastLocationMillis = SystemClock.elapsedRealtime();
        mLastLocation = loc;
        Log.d("OnLocationReceived",mLastLocation.toString());
    }

    protected void onProviderEnabledChanged (boolean enabled)
    {

    }
};

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_fitness);
     mGPSManager = GPSManager.get(this,mGPSListener);
}

@Override
public void onStart()
{
    super.onStart();
    this.registerReceiver(mLocationReceiver, new IntentFilter(GPSManager.ACTION_LOCATION));
    mGPSManager.startLocationUpdates();
}

@Override
public void onStop()
{
    this.unregisterReceiver(mLocationReceiver);
    super.onStop();
}

/* private void calculateUserDistance() */

Upvotes: 0

Views: 406

Answers (1)

Pavel Dudka
Pavel Dudka

Reputation: 20944

Oh, no! This is an old deprecated way of dealing with location updates! First of all, you have to get familiar with this guideline. This guideline describes location tracking strategy using LocationClient.

Please note, there is even newer way of tracking current location - using GoogleApiClient in conjunction with LocationServices, but you can ignore it for now due to lack of proper documentation :(

Back to LocationClient - there are 2 ways of receiving location updates:

If you think of creating a fitness app - you will definitely want to check out ActivityRecognition API

Upvotes: 1

Related Questions