I need to write an app, which every 5 minutes determines the current location of the mobile phone (using all free, available location providers) and sends it to a server.
If some location provider doesn't work at the start of the application, but becomes available later, the application should process its location data as well.
In order to do this, I implemented following class. In one of my activities, I create an instance of it and call its startTrackingUpdates
method. locationChangeHandler
does the processing of location data.
public class LocationTracker implements ILocationTracker, LocationListener {
public static final long MIN_TIME_BETWEEN_UPDATES = 1000 * 60 * 5; // 5 minutes
public static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
private ILocationManager locationManager;
private ILocationChangeHandler locationChangeHandler;
public LocationTracker(final ILocationManager aLocationManager,
final ILocationChangeHandler aLocationChangeHandler) {
this.locationManager = aLocationManager;
this.locationChangeHandler = aLocationChangeHandler;
}
public void startTrackingUpdates() {
final List<String> providers = locationManager.getAllProviders();
for (final String curProviderName : providers)
{
final ILocationProvider provider = locationManager.getLocationProvider(curProviderName);
if (!provider.hasMonetaryCost())
{
subscribeToLocationChanges(provider);
}
}
}
private void subscribeToLocationChanges(final ILocationProvider aProvider) {
locationManager.requestLocationUpdates(aProvider.getName(), MIN_TIME_BETWEEN_UPDATES,
(float)MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
}
public void onLocationChanged(final Location aLocation) {
locationChangeHandler.processLocationChange(new LocationWrapper(aLocation));
}
public void onProviderDisabled(final String aProvider) {
}
public void onProviderEnabled(final String aProvider) {
}
public void onStatusChanged(final String aProvider, final int aStatus,
final Bundle aExtras) {
}
}
I built the application and installed it on my mobile phone. Then, in the morning I took my phone, went to work, then went back home. At home I checked the results of a day-long work of the application and found only one record in the database.
Provided that the rest of the system (transmission of location data to the server, saving in the database) works correctly, I must have some problem in the location tracking code (onLocationChanged
wasn't invoked even though I changed my location several times).
What's wrong with my code (how should I change it, in order for the onLocationChanged
to be called whenever the location of the phone changes by more than MIN_DISTANCE_CHANGE_FOR_UPDATES
meters according to one of the locatin providers) ?
Update 1 (18.08.2013 13:59 MSK):
I changed my code according to msh recommendations. I start the timer using following code:
public void startSavingGeoData() {
final IAlarmManager alarmManager = activity.getAlarmManager();
final IPendingIntent pendingIntent = activity.createPendingResult(
ALARM_ID, intentFactory.createEmptyIntent(), 0);
alarmManager.setRepeating(INTERVAL, pendingIntent);
}
In the activity
I put following timer event handler:
@Override
protected void onActivityResult(final int aRequestCode, final int aResultCode,
final Intent aData) {
geoDataSender.processOnActivityResult(aRequestCode, aResultCode,
new IntentWrapper(aData));
}
When the phone is turned on, everything works as expected - onActivityResult
is executed once in INTERVAL
milliseconds.
But when I press the power button (screen becomes disabled), onActivityResult
is not invoked at all. When I press the power button again, onActivityResult
is executed as many times, as INTERVAL
has passed since the time when I turned the phone off. If I turned the phone off for 1 * INTERVAL
milliseconds, it will fire once. If I turned the phone off for 2 * INTERVAL
milliseconds, it will fire twice etc.
Note: By "turning off" I mean a short press of the power button (the phone still "lives" and reacts to incoming SMS, for example).
How should I modify the code of startSavingGeoData
in order for the method onActivityResult
to be executed every INTERVAL
milliseconds, even when the phone sleeps?
Update 2 (18.08.2013 19:29 MSK): Neither alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 0, INTERVAL, pendingIntent)
, nor alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, INTERVAL, INTERVAL, pendingIntent)
solved the problem.
Your code is probably correct, but location providers are not running when your phone is sleeping. You may need to acquire a wakelock (if you don't care about power draw), or use AlarmManager and schedule your application to wake up and check location periodically (you still need to have active wakelock while you are waiting for an update, either acquired by AlamManager, or your own).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With