Android permissions

Every Android application makes use of the facilities of the user’s phone (or pad or device). These facilities include memory, storage, the internet, GPS location services, phone book, and so on. Most of these facilities are straight-forward enough. But many have an impact (negative or positive) on the user or the device. For example, access to the user’s private contacts database should be restricted. And accessing some services, such as the internet, incurs a cost on some users, depending on their connection and arrangements with their phone provider.

The Android security system provides maximum flexibility with maximum security. Aside from the initial, default set of permissions (the “sandbox”) that an app operates in, it must get explicit permissions to do everything else.

The central security mechanism – as you are no doubt aware as a user of Android apps – is that in order to access almost any service via code, an application must explicitly request permission to do so. There are a lot of potential permissions to request – the full list is here. Some are downright dangerous – witness the permission to disable the device (BRICK) or allow an app to delete packages (DELETE_PACKAGES). These permissions should only be granted to very highly trusted and tested applications.

So, if you, as an application developer, want to broadcast an SMS receipt notification for example, then you have to make that explicit to the user downloading your app.

In the application’s XML manifest, a <uses-permission> entry must be made. Dublin Buzz needs permission to use GPS and network location providers and also to access the internet. These three lines make that request:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>

As you can see, all permissions (pre-defined ones anyway) are preceded by “android.permission”. In our case, we need access to GPS (ACCESS_FINE_LOCATION) and network location (ACCESS_COARSE_LOCATION), plus the internet (INTERNET). When a user goes to download the file from Google Market, they are notified of the requirements of the application.

(I mentioned “pre-defined” permissions above. This is because developers can also add their own, custom permissions, perhaps to allow trusted applications to access their own data. This is beyond the scope of this posting.)

The system works reasonably well, as long as the Android API enforces use of the permissions. As long as users are aware of the implications of granting certain permissions, and as long as an application takes care to use the minimum required permissions, then every party is happy.

This is another reason why downloading apps with suspicious requests should not be done! if you’re downloading a simple calendar app, then if it makes a request for your location over GPS, you ought to be slightly suspicious!

Posted in Android, Android development, Mobile Apps | Leave a comment

Android preferences

Dublin Buzz uses the preferences storage mechanism for storing users’ favourites. This is an ideal mechanism – very easy to use, persistent between application launches, and doesn’t require any special permissions or access to SD cards or external memory. In fact, for doing simple key/value storage, it is the obvious choice.

Favourites are stored when the user hits the “Make fav” button in the SightViewer activity. The click handler for the button is here:

 /**
  * Uses preferences mechanism for saving favourites. Saves the sight's name and setting 
  * @param setting
  */
 private void setFavourite (int setting)
 {
  SharedPreferences favs = this.getSharedPreferences("MyPrefs", MODE_WORLD_WRITEABLE);
  SharedPreferences.Editor editor = favs.edit();
  editor.putInt(theSight.getName(), setting); 
  editor.commit();
 }

A SharedPreferences is an interface for accessing preference data. The reference to it is through the activity’s getSharedPreferences() method call. The method is passed a preference file name, in this case “MyPrefs”. Ideally, to make it unique, this should be more specific, something like “com.dublin.buzz.MyPrefs” or equivalent, to make it unique on the Android device. We also pass it a mode, in this case something to indicate that we are writing preferences.
All preferences pass via an editor, which ensures that they are in the right format before being committed to the preferences storage. Changes are batched until you call commit() or apply().
We pass in the name of the sight as the key and the setting value (either 1 or 0). A setting value of 0 takes the sight out of the favourites list, while a setting of 1 indicates that it is a favourite. The setting is obviously an integer, so we use the setInt() method to write it to the editor. And then we must commit() those changes, which writes them to the preferences file.

So, we have written out a value for the sight, as to whether it is a favourite or not. Then how do we read back that value? This code, in the SightViewer onStart() method reads the preferences, looking for the key of the sight name:

  // Test to see if this is a favourite or not?
  SharedPreferences favs = this.getSharedPreferences("MyPrefs", MODE_WORLD_READABLE);
  int result = favs.getInt(theSight.getName(), 0);
  isAFavourite = result==1;

It is the opposite process to writing preferences. This time, we get the preferences in the same way, but we are in reading mode. And the getInt() method call on the preferences uses the sight’s name as a key and a default value of zero. In other words, if the key does not exist, the method returns this default value – 0. This corresponds to a setting of off, meaning the sight is not a favourite. Which makes sense, because we only add it to the favourites by writing a setting of 1. If the sight has been added and then taken out again, it has a setting explicitly in the preferences of zero anyway. Otherwise, it has no setting. This “lazy” way to use preferences is more efficient, but cannot be generalised to all situations.

I also read the preferences to get the entire list of available favourites, in the DublinBuzz.java file:

 /**
  * Gets the current list of user favourites
  * @return
  */
 private List<Sight> getFavourites()
 {
   List<Sight> favourites = new ArrayList<Sight>();
   SharedPreferences favs = this.getSharedPreferences("MyPrefs", MODE_WORLD_READABLE);
   for (Sight s: app.sights)
   {
   	int result = favs.getInt(s.getName(), 0);
   	if (result==1)
   		favourites.add(s);
   }
   return favourites;
 }
Posted in Android, Android development, Mobile Apps | Leave a comment

Map overlays

I have explained in an earlier post how to display Google Maps. In Dublin Buzz, every map opens centred on the sight and also contains a red dot and text label for the sight. This was more complicated to achieve that it looks! In fact, Android Google Maps use a concept called “Overlays” to provide this kind of functionality. My overlay also allows users to click on it and to see some details about the sight, such as its phone number. Let’s see how the code does that.

It is all contained in the MapLabel.java file, downloadable here: MapLabel.
All map overlays are subclasses of the Overlay object (it gets slightly more complex when you want multiple overlays, but for now, it is sufficient to understand the simpler case of just using one overlay on a map). We must override the draw() method of the Overlay to provide the custom drawing functionality. The Overlay superclass handles the rest.

package com.tony.buzz;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.*;
import com.google.android.maps.*;

/**
 * Displays a simple label with the name of the sight in red and a red dot over the map
 * @author Tony Scannell
 */
public class MapLabel extends Overlay {

	private GeoPoint sight = null;
	private String name = null;
	private Context mapviewer = null;
	private String details = null;

	/**
	 * Constructs a map overlay at the point specified and with the text displayed
	 * @param thePlace The geographic point to display the label at
	 * @param desc The label to append
	 */
	public MapLabel(GeoPoint thePlace, String desc, String details, Context activity)
	{
		sight = thePlace;
		name = desc;
		this.details = details;
		mapviewer = activity;
	}

	/**
	 * Overrides the draw method to provide the custom drawing of the label and red dot indicating where a sight is
	 */
	@Override
	public void draw (Canvas canvas, MapView map, boolean shadow)
	{
		// Start by converting the geopoint to a pixel location on the map (held in mypt)
		Projection projection = map.getProjection();
		Point mypt = new Point();
		projection.toPixels(sight, mypt);

		// Use this paint to draw the dot and write the text label
		Paint pt = new Paint();
		pt.setTextSize(25);
		pt.setARGB(250, 255, 0, 0);
		pt.setAntiAlias(true);
		pt.setFakeBoldText(true);

		int rad = 5;
		// Draws a red dot
		RectF oval = new RectF(mypt.x-rad, mypt.y-rad, mypt.x+rad, mypt.y+rad);
		canvas.drawOval(oval, pt);
		// Writes out the text label for the sight
		canvas.drawText(name, mypt.x+rad, mypt.y, pt);
	}

	/**
	 * Some tap on the surface displays the details for the sight (e.g. address and phone)
	 */
	@Override
	public boolean onTap (GeoPoint point, MapView map)
	{
	    AlertDialog.Builder builder = new AlertDialog.Builder(mapviewer);
	    builder.setTitle(name);
	    builder.setMessage(details);
     	    builder.setCancelable(true);
	    builder.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
	    public void onClick(DialogInterface dialog, int id) {
	    	dialog.cancel();
	        }
	    });
     	AlertDialog alert = builder.create();
	    alert.show();
	    return true;
	}
}

The essence of what needs to be done is to convert a geographical location (a GeoPoint in Android) to a specific pixel on the map displayed. These three lines of code get a projection object from the map view object, and then uses the toPixels method to convert a GeoPoint location to pixels on the map.

Projection projection = map.getProjection();
Point mypt = new Point();
projection.toPixels(sight, mypt);

The rest of the code uses a Paint object to specify colour and text size. The draw() method (of which this code is a part) is an override of the existing Overlay object’s draw() method and it receives a Canvas argument, to be used in drawing text and shapes on. Basically, I use the point object calculated earlier and draw an oval (actually, a circle, but using the drawOval method) onto the canvas, followed by the text. And that’s it.

To handle users taps on the map, we simple override the onTap() method. The onTap() method opens a dialog with an OK button and the sight’s details displayed.

Here’s a map displayed with the text and red dot.

Posted in Android, Android development, Mobile Apps | Leave a comment

Getting user’s current location using GPS (or network…)

One of the major features of Dublin Buzz – and what makes it a mobile application – is its knowledge about the user’s whereabouts. This is obtained by using the built-in GPS location chip on the Android device, if it has one. Alternatively, if the user has GPS switched off for any reason, or they prefer not to use it to conserve battery, the less accurate network location provider can be used. This posting will show you the steps to obtain location data.

loc = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

This first line of code obtains the LocationManager object. This will be the service API that provides us with all of the location finding services we will be needing. The loc object is defined as:

	public LocationManager loc = null;

All the code for loading a specific provider (either GPS or network) is done in DublinBuzz.java. That code is in a Word document available here: DublinBuzz.

The relevant code for getting a provider of location data is here:

/**
* Sets up the providing of location information for the user
*/
private void setupLocationProvider() {
    provider = app.loc.getBestProvider(getLocationProviderCriteria(), true);
    if (provider==null)
    {
    	Button b = (Button)findViewById(R.id.DistanceButton);
    	b.setTextColor(Color.DKGRAY);
    	b.setEnabled(false);
    }
    else
    {
    	currentLocation = app.loc.getLastKnownLocation(provider);
    	if (currentLocation != null)
    	{
    	    for (Sight s : app.sights)
   		s.refreshDistanceFromCurrentLocation(currentLocation);
    	}
    }
  // We have a location provider, so now create and add a listener for updating
  // periodically. We can then refresh distance too.
  updater = new LocationListener() {
  public void onLocationChanged (Location location){
  	currentLocation = location ; 
  	for (Sight s : app.sights)
  		s.refreshDistanceFromCurrentLocation(location);
  		if (app.preferredButton==R.id.DistanceButton)
  			ShowDistance(null);
  		else
  			displaySights(null);
  }
  public void onProviderDisabled(String provider)
  { 	}
  public void onProviderEnabled(String provider)
  {	}
  public void onStatusChanged(String provider, int status, Bundle extras){}
  };
  if (provider !=null)
  {
  	app.loc.requestLocationUpdates(provider, timeBetweenUpdates, distanceBeforeUpdates, updater);
  }
}

The very first line (provider = app.loc.getBestProvider(getLocationProviderCriteria(), true);) asks the LocationManager to find out what the best provider would be, given the set of criteria returned from the getLocationProviderCriteria() method call. I’ll explain a little about those criteria later on in the post, but for now, rest assured that those criteria specify things like cost, accuracy, and capability of the provider. If no provider is available, then the application cannot display distance data! So it reverts to turning off the “By Distance” button. Obviously, this is not ideal behaviour. But the philosophy of Android is to allow the end-user (who is boss) to decide whether to use GPS or not. After all of the controversy over iPhones and Androids storing location data, this is a power that users should have.

I then try and get the last available/known location data for the user. Then I update the distance data for every individual sight in turn:

currentLocation = app.loc.getLastKnownLocation(provider);
if (currentLocation != null)
{
    for (Sight s : app.sights)
	s.refreshDistanceFromCurrentLocation(currentLocation);
}

The following code creates a listener for location updates. Obviously, location changes as the user moves about. One of its key aspects is its very dynamism. This means that callbacks have to be defined to handle the changing location data. This is fully customisable by the programmer. In our case, we define an onLocationChanged method that does two main things: it updates the distance data for all sights; and it redisplays the list of sights if the user is currently looking at them ordered by distance:

// We have a location provider, so now create and add a listener for updating
// periodically. We can then refresh distance too.
updater = new LocationListener() {
public void onLocationChanged (Location location){
	currentLocation = location ; 
	for (Sight s : app.sights)
	    s.refreshDistanceFromCurrentLocation(location);
    	    if (app.preferredButton==R.id.DistanceButton)
    	        ShowDistance(null);
    	    else
    		displaySights(null);
    	    }

Finally, the location manager must be told where and how often to send location updates to:

   app.loc.requestLocationUpdates(provider, timeBetweenUpdates, 
   	distanceBeforeUpdates, updater);

The requestLocationUpdates method does what it says. It takes four arguments: the type or provider we want to ask for updates from (obtained earlier), the time in milliseconds between each update, the distance between updates, in meters, and the listener which will process those updates. The time and distance arguments need to be set just low enough to provide frequent and accurate updates, but not too low, as that would be a battery wasting hog. In my Dublin Buzz application, I have set these arguments to 10,000 ms and 10 meters respectively:

private static final long timeBetweenUpdates = 10000; // milliseconds between updates
private static final float distanceBeforeUpdates = 10; // meters moved before needing updates

The application can now display accurate, dynamic distance information for the user. I’ll explain more about that in a further post, but for now, enjoy the view!. As you can see below, you can tell that I actually live in Dublin. I live in Kilmainham, actually, so the data seems to be accurate enough.

Posted in Android, Android development, Mobile Apps | Leave a comment

Sorting sights – by distance, or alphabetically

All sights in Dublin Buzz can be sorted by the user, in one of three ways – alphabetically, by distance, or by “popularity”. (I define popularity somewhat subjectively!). In any case, it requires a little Java trick combined with a well-known design pattern to make this work. Here is the code for sorting by distance, for example:

    /**
     * User clicked distance button
     * Sorts by distance, nearest to furthest. 
     * @param v
     */
	public void ShowDistance (View v)
    {
    	viewable = getDisplaySights(app.sights);
    	changeButtonColours(R.id.DistanceButton);
        displaySights (new Comparator<Sight>(){
            public int compare(Sight p1, Sight p2) {
                if (p1.getLatestDistance() > p2.getLatestDistance())
                	return 1;
                if (p1.getLatestDistance() < p2.getLatestDistance())
                	return -1;
                return 0;		                
            }
        });
    }

This code makes use of anonymous classes to pass a new Comparator object (which has no name, hence is anonymous) to the displaySights() method. displaySights() uses this comparator to do the sorting of the list of sights. In this example, the comparator sorts sights by comparing their distances to the user. The getLatestDistance() method retrieves the last known distance (in meters) for the sight to the user. This is updated by a different part of the code as GPS coordinates change. All comparators work by returning 1 when the first argument is greater than the second argument, -1 when it is smaller, and 0 when they are equal. The sort algorithm borrows this comparator to apply sorting logic. This is an example of the Strategy design pattern at work. In the Strategy pattern, the official definiton (by Gang of Four) is “Define a family of algorithms, encapsulate each one, and make them interchangeable. Lets the algorithm vary independently from clients that use it.” Here, the algorithm that varies is the algorithm for comparing two sights. The client in this case is my code for sorting them (displaySights()) and the user of the algorithms is the Collections.sort() method.

    public void displaySights (Comparator<Sight> compare)
    {
        // The order this list by ordering preferences, passed via the comparator, if specified
        if (compare != null)
        	Collections.sort(viewable, compare);

You simply pass in a different comparator if you want to sort on some other criteria. In fact, the criteria to sort on can be based on any custom ordering you can think of. It is an incredibly powerful and flexible way to change (dynamically) the sorting behaviour you want.

Here’s the code for sorting alphabetically. Notice how it is very similar to the method for sorting by distance, but it just forces the use of a string comparison on the name.

    public void ShowAToZ (View v)
    {
    	viewable = getDisplaySights(app.sights);
    	changeButtonColours(R.id.AToZButton);
        displaySights(new Comparator<Sight>(){
            public int compare(Sight p1, Sight p2) {
                return (p1.getName().compareTo(p2.getName()));
            }
        });
    }
Posted in Android, Android development, Mobile Apps | Leave a comment

Displaying maps centred on GPS coordinates

Using Dublin Buzz makes it incredibly easy to view sights and read all about them. If you have been convinced by the sight’s description that you would like to visit, then it is a simple matter to then find out where the sight is, by clicking a button a viewing the Google Maps application, with the sight pin-pointed on the map.

Dublin Buzz stores the GPS coordinates for each and every sight. This makes it possible for the application to calculate where you are in relation to the sight (calculated using your own current GPS coordinates.). I’ll discuss that in another posting, but for now, let’s look at how to display a map centred on the sight.

Maps are displayed using an activity called MapViewer (available in Word document format here:  MapViewer). This is launched from the SightViewer code using an Intent (see the posting describing Intents and how to use them below).

    	Intent launch = new Intent(this, MapViewer.class);
    	launch.putExtra("Sight", theSight);
    	startActivity(launch);

Step 1 is finding out the sight’s location. For Google Maps to work, they expect GeoPoints, not latitude and longitude. A GeoPoint is constructed using latitude and longitude however, quite simply:

  String name = sight.getName();
  double latitude = sight.getLatitude();
  double longitude = sight.getLongitude();

  Double lat = latitude * 1E6;
  Double lng = longitude * 1E6;
  GeoPoint centre = new GeoPoint(lat.intValue(), lng.intValue());

In the code above, I extract latitude and longitude from the Sight bundled into the extra data when the Intent was launched. I multiply both of them by 1 million. These extended values can then be passed to the GeoPoint constructor.

Now, we’re ready to display the map. Let’s look at the code to do this:

mapView = (MapView)findViewById(R.id.MapViewer);
mapView.setStreetView(true);
mapView.setBuiltInZoomControls(true);
mapController = mapView.getController();
mapController.setCenter(centre);
mapController.setZoom(18);
mapController.animateTo(centre);
mapView.setTag(name);

We create a MapViewer object in the first line, which is a XML-defined page for displaying maps. This requires one little bit of magic, that I will just mention, but without getting into too much detail about. In order to use Google Maps, you need to download a unique Google Maps API key. This has to be inserted into the XML for the map viewing page. Here’s the code (with the key altered…!):

<com.google.android.maps.MapView
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:enabled="true"
  android:id="@+id/MapViewer"
  android:clickable="true"
  android:apiKey="9JL86OJj87MGiX_S_lYC_Pd50M2HJ4op5wkosF9g"
/>

I won’t go into the details of how to obtain a key as it is outside the purpose of this posting (and this blog). Google have a website devoted to it: http://code.google.com/android/add-ons/google-apis/mapkey.html

Once you’ve obtained a link to the MapView object, you then can set street view and zoom controls, along with other stuff that configures the map display for the user.
I then get a MapController object that allows me to display the map in a specific way. I want it zoomed to a particular size (18 in this case) and to use the GeoPoint of the Sight calculated earlier to be the centre of the map. Finally, I set the map’s title to be the name of the sight. I found out that 18 was the size I wanted by trial-and-error! It is a magic number that, really, should have been defined as a constant!

All of this code looks fairly complicated and, to me at first, arbitrary. But it makes sense when you think of the flexibility it gives you to display maps in whatever way you see fit.

Posted in Android, Android development, Mobile Apps | Leave a comment

Toasts – or how to pop up a message for the user

Users of the Dublin Buzz application can add sights to their list of favourites. This makes them easily accessible at a later time. If you fancy popping down to a sight after reading about it, you can simple hit the “Make Fav” button on the sight’s page. When you’ve tired of it, you simply take it off your favourites list.

Both these actions – adding a favourite or taking it away – use a facility in Android called “Toasts”. They’re a fancy name for something incredibly simple – displaying a little pop-up bit of text on-screen for a short amount of time, before it automatically fades away. (See screen grab below). It is the perfect mechanism for alerting your users to something they’ve done, but without slowing them down by insisting the press “OK” on a dialog box. It is probably the least intrusive way to give them information and is perfect for making the application more user-friendly.

Here’s the code for producing toasts in Dublin Buzz:

 Toast toast = Toast.makeText(this, R.string.subFav, Toast.LENGTH_SHORT);
 toast.show();

Did I say it was incredibly simple?

A Toast object is constructed using the Toast classes’ makeText() method. This takes the current context (the activity, or “this”), a string to display, and the length of time to display it for. The alternative to Toast.LENGTH_SHORT is Toast.LENGTH_LONG (which is customisable). Then, once declared, you call toast.show() and it is displayed, asynchronously, so it doesn’t block.

And voila! You have a message displayed.

Posted in Android, Android development, Mobile Apps | Leave a comment