Thursday, 18 September 2008

Getting Locations

I had toyed with Android when it first came out, but now a lot has changed again. Hopefully for the better, but it looks like my old code is just ripe for the scrap-heap. That is good and bad. Good because it allows me to start from scratch and bad because I have to start from scratch.

The first trouble I run into is that somehow the location provider is not accessible, the call to

(LocationManager)getSystemService(Context.LOCATION_SERVICE);


returns null. It turns out that the access to these requires some security settings in the androidManifest.xml:

<uses-permission name="android.permission.ACCESS_LOCATION"/>
<uses-permission name="android.permission.ACCESS_GPS"/>
<uses-permission name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission name="android.permission.ACCESS_MOCK_LOCATION"/>


Not quite 100% sure which one control which exactly, but the combination of them all seems to do the trick. Fine-tuning will come later.

With this set, at least I get a location manager now. And I get a list of all the available providers, which on the emulator is just one with the name GPS. But the call to getLastKnownLocation just returns null again and running it in a loop does not do any good either even when trying to get data into the emulator using the console. It somehow transpires that this call does not really do what one would expect. It seems to only give locations if there is a subscription to location updates is set up with a LocationListener. There is a thread on the android developer groups but that seems to go into the wrong direction, as it is not strictly required to have a separate thread for all this.

It is enough to have your activity implement the LocationListener and its four abstract methods. Now I have my very first logger that prints the current location onto the screen:


import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;


public class GPSLogger extends Activity implements LocationListener {
String TAG = "GPSLogger";

LocationManager lm;
TextView tv;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getLocation();
tv = new TextView(this);
tv.setText("Waiting");
setContentView(tv);
}


public void onLocationChanged(Location loc) {
Log.e(TAG, loc.toString());
tv.setText("Location " + loc.toString());
}
public void onProviderEnabled(String s){
}
public void onProviderDisabled(String s){
}
public void onStatusChanged(String s, int i, Bundle b){
}

public void getLocation() {
this.lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
this.lm.setTestProviderStatus(LocationManager.GPS_PROVIDER,LocationProvider.AVAILABLE, null, System.currentTimeMillis());
this.lm.setTestProviderEnabled(LocationManager.GPS_PROVIDER,true);
this.lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
}


Not fantastic, but the first steps are always the most difficult.

1 comment:

Jahmelon said...

I have found it more usefull to store lat long as an object or comma delimited string within one record of an SQLite database rather than one record for each coordinate. Eventually you are going to want to perform a query for all the records in the Coordinate table in order to get all your coordinates. This is WAY slower than looping through a split comma delimted string. It might not make a difference for a couple hundred points, but if you have 1000+, its quicker