Reputation: 3854
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
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