Friday, May 30, 2014

Offline Mapping with Phonegap Build and mbTiles

Guest post by SilviaTerra intern Jim Miller
-------------------

Screenshot_2014-05-23-16-02-49.png

One of SilviaTerra's most popular products is Plot Hound, but navigating and mapping becomes tricky when you're deep in the woods without a data connection.


A little over a year ago, this post was created to shed some light on a possible solution where map tiles could be stored locally and then displayed in an HTML5 Mobile App, but it wasn't all that we were hoping for.


Ideally, the map tiles wouldn't be stored in a raw, uncompressed format on the local file system; instead, they could be efficiently stored in an mbTiles database. We wanted something similar to Scott Davis's solution to the problem: accessing an mbTiles database with tiles from MapBox with the Cordova SQLite Plugin and a custom Leaflet Tile Adapter. The dilemma was that there was no supported SQLite plugin for Phonegap Build, so to read an mbTiles database would mean sacrificing the hassle-free compiling and building that Phonegap Build does so nicely.


Finally, with Phonegap Build's feature to add your own plugin, we were able to submit a forked version of Brodysoft's Cordova SQLite plugin with a tweaked plugin.xml to get it to Build's standards. If you are interested in using an SQLite plugin for Android and iOS, feel free to grab his here. This allows us to access an mbTiles database stored on the phone rather than downloading individual tiles. All that was left to do was get the database to the phone and to display the tiles on a map (using a custom TileLayer).


This is the Phonegap app for Android that we made, integrating all of these processes together, and here is the source (most of the work is done in js/main.js).


A few notes on key steps to the final product: The SQLite plugin specifically looks for databases inside /data/data/{your package name}/databases, and because of this we used a few preferences in config.xml to make sure we were always saving to the internal file system of the Android device with the Phonegap FileTransfer API. And a special shout out to Scott Davis again: his custom TileLayer is the basis for js/TileLayer.MBTiles.js with a few modifications to account for a different SQLite plugin.

We're looking forward to integrating this proof-of-concept into Plot Hound in the coming month. Look for future updates on how we continue to develop HTML5 offline mapping technologies.

8 comments:

  1. Great, thanks for sharing this. How are the performances ? I had done a POC for android as well (https://github.com/tdurand/offline-phonegap-map) , but i've gave up because the performances .. I've tried your, seems to be better for performance, but have you tried with a larger MBTiles ?

    ReplyDelete
    Replies
    1. No, we haven't yet. We are prioritizing integration with Plot Hound right now, and we will likely only be dealing with smaller databases. If you'd like to give it a try, you can swap the download in main.js and try any mbtiles that you'd like.

      Thanks for the comment, sorry for the delay!

      Delete
    2. I'll try and i'll give some feedback here !

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. I see your example for android for downloading the database file which is great! I was wondering how does this work for ios? I am trying to include a database file in with my project and have sql lite see it and open the included one instead of creating its own. I am also using phonegap build to attempt that.

    ReplyDelete
    Replies
    1. I'm actually wondering the same this.

      The directory that the SQLite plugin uses for the databases is read-only according the cordova's documentations.

      cordova.file.applicationStorageDirectory - Root directory of the application's sandbox; on iOS this location is read-only

      Delete
    2. Ok this sound more like a bug in SQLitePlugin, but I figured out how to workaound. For the iOS you need to use cordova's documents folder for the database and you cannot use "databases" folder like on Android.

      downloadPath = cordova.file.documentsDirectory + "Database.db";

      Also I noticed that iOS needs .db extension when you open the database, even thought the documentation says that you don't have to provide it.

      if(device.platform == "iOS") {
      dbname = dbname + ".db";
      }

      var db = window.sqlitePlugin.openDatabase({
      name : dbname
      });

      Lots of trial and error.

      Delete
  4. I travel a lot and tried a lot of maps. The last one I used for my trip is HERE (traveled in Europe). I would love that people also used data rooms as broad as they use maps while they travel to always have access to their documents.

    ReplyDelete