Wednesday 24 September 2008

A simple Android Tracklogging Service

So far, I had wired my tracklogging to the main Activity just to get going, but in real life this is supposed to happen behind the scenes, so a Service is the right thing to implement. This turned out to be easier that I thought.

First of all the class needs to be derived from Service, which is a bit like an Acitivty but without any (ever) visible action. As a service can potentially communicate with other applications it has the onBind() method, but we return always null here: there is nothing this service has to communicate about.

A second thing is that my tracklogging service needs to get the location updates, so I made it implement the LocationListener interface. I do not care that much about providers at the moment (with the Mock providers gone in 1.0 there is not so very much one can do anyway), I only implement onLocationChanged().

In this I simply stuff the data into my ContentProvider (which has been in some aspects covered earlier, but awaits a bigger write-up here soon) and I am done.
Fortunately, this operation should be very short, so there is no need to start another thread for this service.

This is how the service looks like:


import android.app.Service;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

public class LocationLoggerService extends Service implements LocationListener {

private final static String TAG = "LocationLoggerService";
LocationManager lm;
GPXWriter writer;

public LocationLoggerService() {
}

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public void onCreate() {
subscribeToLocationUpdates();
}

public void onLocationChanged(Location loc) {
Log.d(TAG, loc.toString());
ContentValues values = new ContentValues();
values.put(GPSData.GPSPoint.LONGITUDE, loc.getLongitude());
values.put(GPSData.GPSPoint.LATITUDE, loc.getLatitude());
values.put(GPSData.GPSPoint.TIME, loc.getTime());
getContentResolver().insert(GPSDataContentProvider.CONTENT_URI, values);
}
public void onProviderEnabled(String s){
}
public void onProviderDisabled(String s){
}
public void onStatusChanged(String s, int i, Bundle b){
}

public void subscribeToLocationUpdates() {
this.lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
this.lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
}


Now I only need to start the service. In the next post I will cover how to start the service at boot time, but here, I still link it to my main Activity, where in its onCreate() method I add a call to start the service, like so:

componentName comp = new ComponentName(getPackageName(), LocationLoggerService.class.getName());
ComponentName service = startService(new Intent().setComponent(comp));


The last step is to add the service to the AndroidManifest.xml:

<service android:name="LocationLoggerService"
android:enabled="true"
android:exported="false"
android:label="LocationLoggerService"
/>

4 comments:

Mr Simons said...

Thanks man! just the thing i was looking for.

Douglas C. R. Paes said...

you have solved my problem

tks

Anonymous said...

Thanx!! this was really helpful. Coul d you also show how to stop this service.

not-alone said...

that's great man! thanks thanks tnanks!