Integrating osmdroid part 2 – Using MBTiles as offline data source

Yesterday I wrote an article about how to integrate the osmdroid library into an Eclipse project. You may have noticed I didn’t mention anything about actually creating an Activity that actually does something with the freshly installed library.

Let’s change that :-). Below you’ll find a¬†heavily¬†commented example on how to instantiate a MapView using an offline MBTiles map source. Since creating an mbtiles file is also a project on its own, I’ll see if I can write something up about that process soon.

Questions? Let me know!

package com.example.yourproject;


import org.osmdroid.DefaultResourceProxyImpl;
import org.osmdroid.ResourceProxy;
import org.osmdroid.tileprovider.MapTileProviderArray;
import org.osmdroid.tileprovider.modules.IArchiveFile;
import org.osmdroid.tileprovider.modules.MBTilesFileArchive;
import org.osmdroid.tileprovider.modules.MapTileFileArchiveProvider;
import org.osmdroid.tileprovider.modules.MapTileModuleProviderBase;
import org.osmdroid.tileprovider.tilesource.XYTileSource;
import org.osmdroid.tileprovider.util.SimpleRegisterReceiver;
import org.osmdroid.views.MapController;
import org.osmdroid.views.MapView;

import android.os.Bundle;
import android.os.Environment;
import android.view.Menu;

public class RouteMapActivity extends Activity {

  private static final String TAG = "RouteMapActivity";

  public void onCreate(Bundle savedInstanceState) {

    * This whole thing revolves around instantiating a MapView class, way,
    * way below. And MapView requires a ResourceProxy. Who are we to deny
    * its needs? Let's create one!
    * It would have been nice if this was taken care of in the MapView
    * constructor. Interestingly MapView *has* a constructor that creates a
    * new DefaultResourceProxyImpl but unfortunately that one doesn't allow
    * us to specify the parameters we *do* need to set ...
    DefaultResourceProxyImpl resProxy;
    resProxy = new DefaultResourceProxyImpl(this.getApplicationContext());

    * A class that implements the ITileSource interface knows how to
    * convert an InputStream or a file path into a Drawable. It doesn't do
    * much more than that. The real 'sourcery' is performed by
    * MapTileFileArchiveProvider which will be introduced shortly.
    * What we need is really a BitmapTileSourceBase instance, but this
    * class is defined as abstract. XYTileSource is not and comes closest
    * to what we want.
    * Comment: I don't quite get why BitmapTileSource base is abstract; it
    * doesn't contain any abstract methods.
    XYTileSource tSource;
    tSource = new XYTileSource("mbtiles",
    8, 15, 256, ".png", "http://who.cares/");

    * Don't think the name SimpleRegisterReceiver is particularly well
    * chosen. SimpleReceiverRegistrar would have been better because the
    * only thing SimpleRegisterReceiver does, is wrap the methods
    * Context.registerReceiver(..) and Context.unregisterReceiver(..). Have
    * a look at the source if you don't believe me ;-).
    * So why does it exist then?? Don't know, but it's quite possible to
    * just ignore this step and state the Activity implements
    * IRegisterReceiver and replace the 'simpleReceiver' variable with
    * 'this' further down (no additional implementation required).
    SimpleRegisterReceiver sr = new SimpleRegisterReceiver(this);

    * The following looks complicated, but really only creates an
    * iArchiveFile[]. Apparently Marc Kurtz and Nicolas Gramlich, the
    * authors of MapTileFileArchiveProvider, figured it might be useful to
    * support multiple files/sources. I guess that might make sense if
    * you're providing separate files for, for example, cities.
    * They also provided quite a bit of logic in MapTileFileArchiveProvider
    * for handling SD Card inserts and ejects. Additionally, if files are
    * not explicitly specified they can be dynamically loaded from the
    * /mnt/sdcard/osmdroid directory, which is a nice feature.
    String packageDir = "/com.example.yourproject";
    String p = Environment.getExternalStorageDirectory() + packageDir;
    File f = new File(p, "TileDatabase.mbtiles");
    IArchiveFile[] files = { MBTilesFileArchive.getDatabaseFileArchive(f) };

    MapTileModuleProviderBase moduleProvider;
    moduleProvider = new MapTileFileArchiveProvider(sr, tSource, files);

    * So at this point we have a MapTileModuleProvider that provides
    * MapTileModules: a MapTileModule looks at one or more sources, which
    * are *not* ITileSources but IArchiveFiles and provides MapTiles. What,
    * then, does MapTileProviderArray do? Well, it just adds another layer
    * to the complexity cake: this makes it possible to set multiple
    * MapTileModuleProviders, such as an on- and offline source. I'm sure
    * it's useful for someone, but for simple applications it's probably
    * too much.
    MapTileModuleProviderBase[] pBaseArray;
    pBaseArray = new MapTileModuleProviderBase[] { moduleProvider };

    MapTileProviderArray provider;
    provider = new MapTileProviderArray(tSource, null, pBaseArray);

    * Are we there yet??? Create the MapView already!
    MapView mapView = new MapView(this, 256, resProxy, provider);

    // Zoom in and go to Amsterdam
    MapController controller = mapView.getController();
    controller.animateTo(new LatLonPoint(52.373444, 4.892229));

    // Set the MapView as the root View for this Activity; done!


  public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(, menu);
    return true;