I write solutions to the problems I can't find much about elsewhere on the Web, also some code/script snippets that are absolutely awesome and make my life easier. Will be glad if someone finds these posts interesting and helpful!

Thursday, May 5, 2011

Offline Google Maps for Android

This took me a while to figure out as I couldn't find any tutorial, but it's fairly easy after all.
The map container of my choice is OSMDroid, which is a great (and open source!) replacement for Google Maps container.
Resolve the MapView and set tile provider as follows

It basically defines a new OnlineTileSourceBase with:
  • name "Google Maps" (this is an important bit, as it will be used to lookup the directory with offline tiles)
  • resource id "unknown" (I also downloaded OSMDroid source code, added a value "google" to the ResourceProxy.string enum and used that instead)
  • minimum zoom level 1
  • maximum zoom level 20
  • tile size 256 pixels
  • tile file extension ".png"
  • tile base url
  • finally inside the overriden method getTileURLString it describes how to build a URL to get a tile for specific location and zoom level
OK, now the controller supports Google Maps and if setUseDataConnection was set to true it would already show everything and would work fine with Google Maps. But the mission is to make it work offline.
The best tool to export the tiles for an area is Mobile Atlas Creator (version up to 1.8, they removed Google Maps from 1.9). Export an area with map source set to Google Maps in desired zoom levels in Osmdroid ZIP format (it's going to take a while). Put the output ZIP file into the /sdcard/osmdroid/Google Maps directory (if it doesn't exist, create it; the name has to be the same as the first parameter in the OnlineTileSourceBase constructor). Again, as I downloaded the source code for OSMDroid, I changed some values in the org.osmdroid.tileprovider.constants.OpenStreetMapTileProviderConstants class (such as OSMDROID_PATH to put the tiles in my directory instead of /sdcard/osmdroid).
Start up the application, now it should show offline tiles. Notice that now, if the SD card is unmounted, the controller will appear empty.
But the story doesn't end here. As the Google Maps terms of use (10.1.3.b) state:
No Pre-Fetching, Caching, or Storage of Content. You must not pre-fetch, cache, or store any Content, except that you may store: (i) limited amounts of Content for the purpose of improving the performance of your Maps API Implementation if you do so temporarily, securely, and in a manner that does not permit use of the Content outside of the Service; and (ii) any content identifier or key that the Maps APIs Documentation specifically permits you to store. For example, you must not use the Content to create an independent database of “places.”
So it sounds like an application is quite limited to use offline Google Maps tiles. 
Nonetheless, it seems they don't disallow to temporarily cache the tiles and work in online mode (of course then one also needs to store the tiles securely). To achieve this, unzip the ZIP file with extracted map area into the location /sdcard/osmdroid/Google Maps/tiles (or whatever is the location specified in OpenStreetMapTileProviderConstants.OSMDROID_PATH), then set mapView.setUseDataConnection(true). The default cache expiry period is not very long, so I also altered it in the source code by setting the values of OpenStreetMapTileProviderConstants.TILE_EXPIRY_TIME_MILLISECONDS and OpenStreetMapTileProviderConstants.DEFAULT_MAXIMUM_CACHED_FILE_AGE to (1000 * 60 * 60 * 24 * 365 * 10) (that's 10 years) . This will make OSMDroid to use pre-fetched tiles for areas where available, but for the rest of the world it will download new tiles.
That's it. Hope it helps.
UPDATE As stated in the comments, you need the Mobile Atlas Creator version 1.8 (I see they removed all versions prior to 1.9 from sourceforge). The other tool capable of fetching tiles is "OsmAnd Map Creator" (I see they deprecated it too, still it's available for download), but I'm not sure what the output directories look like, so one would have to adjust it manually to the structure OSMDroid controller expects.

7 comments:

  1. Hi, nowadays Mobile Atlas Creator has some severe difficulties with the map providers, and among others Google maps cannot be created for offline use.
    Can you recommend perhaps another possibilty to obtain google maps for offline usage?

    The idea of yours is great, and I have changed my program as well, but at the end I had to face this problem.

    ReplyDelete
  2. Great! Many thank to you! What about Google Maps Hybrid URL?

    ReplyDelete
  3. @milkos Ouch! I didn't see that coming.. I've updated the post including your tip. Thanks for the heads up mate!

    @Thamachat the hybrid url part is 'lyrs=h@145' that goes into the address as a parameter. A valid example is http://mt3.google.com/vt/lyrs=h@145&hl=en&x=257&y=171&z=9

    ReplyDelete
  4. http://stackoverflow.com/questions/9747765/how-can-download-map-in-osmdroid/9749861#9749861

    ReplyDelete
  5. please help how to change constants,should I download specific file

    ReplyDelete
  6. Aww man thank you VERY MUCH!!!!!! You have saved my life thank you....

    ReplyDelete
  7. How the Mobile Atlas Creator will be used to show the offline map ? please help me...

    ReplyDelete