Programming for Mobiles

Practical 1: GeoMessaging

Resources

Location updates

In order to request location updates your program needs to interact with the LocationManager. In the onCreate method you should collect an instance of it and create a LocationListener to handle the location events.

@Override
public void onCreate(Bundle savedInstanceState) {
    ...
    mLocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    mLocListener = new LocationListener() {
      @Override
      public void onLocationChanged(Location location) {
       // do something with the new location  
      }

      @Override
      public void onProviderDisabled(String provider) {}

      @Override 
      public void onProviderEnabled(String provider) {}

      @Override
      public void onStatusChanged(String provider, int status, Bundle extras) {}
    };
}

You then need to register the LocationListener in the onResume method

@Override
protected void onResume() {
   ...
   mLocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocListener);
}

And you need to unregister in onPause method

@Override
protected void onPause() {
   ...
   mLocManager.removeUpdates(mLocListener);
}

Don't forget to request the relevant permissions too.

In order to test your application indoors you might want to inject fake location events into it. This can be done using a Mock location provider. One example is OldTracks which is available on the market place. More information is here [web].

Note: if you prefer to use Network Location instead of GPS then that is perfectly acceptable for the purposes of this practical

Showing an image from a URL

When displaying a message from the server you will need to download an image and display it on the screen.

String pictureUri = ....;
ImageView imageView = ...;
URL pictureURL = new URL(pictureUri);			
imageView.setImageDrawable(Drawable.createFromStream(pictureURL.openStream(), null));

Handlers

If you attempt a long running task (such as uploading a message) in the UI thread then your application will block and could get killed by the OS. It is better practice to do the upload in the background using another Thread. However, if you do this you need some way of communicating back to the UI thread when the work is done - you should never attempt to manipulate the UI from any other thread. Handlers are how you do this

// create a ProgressDialog
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setTitle(R.string.postingMessage);
progressDialog.setMessage(getString(R.string.sendingMessage));
progressDialog.show();
  
final int HANDLER_FAILED = 0;
final int HANDLER_MESSAGE_SENT = 2;
final Handler handler = new Handler() {
  @Override
  public void handleMessage(Message msg) {
    progressDialog.dismiss();
    switch (msg.what) {
      case HANDLER_MESSAGE_SENT:
        // tell the user that the message was posted (try Toast)
        break;
      case HANDLER_FAILED:
        // tell the user we failed
     break;
    }
    super.handleMessage(msg);
  }
};

new Thread(new Runnable() {
  @Override
  public void run() {
   boolean result = longRunningTask();
   if (result)
    handler.sendEmptyMessage(HANDLER_MESSAGE_SENT);
   else
    handler.sendEmptyMessage(HANDLER_FAILED);
  }
}).start();