Offline Maps

Offline Maps

Google Maps for Android has come a long way but we all make the kind assumption that our users have a fluid LTE connection. In reality there are 3 scenarios when trying to view google maps. Google maps has magically cached the area that you are interested in. The scary version, where you just see a vast sea of gray. Or we can take control and provide our users with an offline option that allows them to view their location even in the darkest subways.

95334d832869ce94a6a62ce94e856a68?s=128

Apoorv Kothari

May 16, 2015
Tweet

Transcript

  1. Offline Maps Apoorv Kothari

  2. Current Options • Google map caching • Scary Version

  3. Goal • Generating an offline Tile source • Integration with

    Map layer • Efficiently download tiles
  4. Understanding Tile • Tile size (256x256 px) • Tile coordinates

    [x,y,z] • Exponential growth of memory 4^zoom • Caching Manhattan(15 zoom): 240MB • Caching the world(15 zoom): ~40086GB
  5. Storing Files Tiles 0 1 2 0_1.png 1_0.png 1_1.png 1_2.png

    … 0_0.png 0_0.png 0_1.png 0_2.png 1_1.png
  6. Tile Source/Server • OpenStreetMaps is open data (ODbL) • http://wiki.openstreetmap.org/wiki/Tiles

    • MapQuest tile servers • http://developer.mapquest.com/web/products/open/map • http://otile1.mqcdn.com/tiles/1.0.0/map/[zoom]/[x]/[y].jpg
  7. Integrating with Map Layer

  8. Integrating with Map Layer • Google Map / TileOverlay /

    UrlTileProvider • getTileUrl() -> doesTileExists? -> saveToFile -> return file URL doesTileExists? saveTileToFile() getFileURL() getTileUrl() No Yes
  9. Integrating with Map Layer public class OfflineTileProvider extends UrlTileProvider
 {

    public static class TileCoordinate
 {
 public final int x;
 public final int y;
 public final int zoom; } 
 public URL getTileUrl(int x, int y, int zoom)
 {
 MapQuestTiles.TileCoordinate coordinate = new MapQuestTiles.TileCoordinate(x, y, zoom);
 String url = "http://otile1.mqcdn.com/tiles/1.0.0/map/" + zoom + "/" + x + "/" + y + ".jpg";
 try
 {
 return new URL(url);
 }
 catch(MalformedURLException e){}
 } 
 }
  10. Integrating with Map Layer public class OfflineTileProvider extends UrlTileProvider
 {


    ...
 
 public synchronized URL getTileUrl(int x, int y, int zoom)
 {
 MapQuestTiles.TileCoordinate coordinate = new MapQuestTiles.TileCoordinate(x, y, zoom);
 return getFileUrl(coordinate);
 }
 
 public static URL getFileUrl(MapQuestTiles.TileCoordinate coordinate)
 {
 if(coordinate.zoom >= 18)
 {
 return null;
 }
 
 URL url = null;
 if(MapQuestTiles.doesTileExist(coordinate))
 {
 try
 {
 File coordinateFile = MapQuestTiles.getCoordinateFile(coordinate);
 url = new URL("file:" + coordinateFile.getAbsolutePath());
 }
 catch(MalformedURLException e){}
 }
 
 return url;
 }
 }
  11. PreCaching Implementation

  12. None
  13. PreCaching Imp. http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Java public static TileCoordinate latLongToTileCoordinate(final double lat, final

    double lon, final int zoom)
 {
 int xtile = (int) Math.floor((lon + 180) / 360 * (1 << zoom));
 int ytile = (int) Math.floor((1 - Math.log(Math.tan(Math.toRadians(lat)) + 1 / Math
 .cos(Math.toRadians(lat))) / Math.PI) / 2 * (1 << zoom));
 if(xtile < 0)
 {
 xtile = 0;
 }
 if(xtile >= (1 << zoom))
 {
 xtile = ((1 << zoom) - 1);
 }
 if(ytile < 0)
 {
 ytile = 0;
 }
 if(ytile >= (1 << zoom))
 {
 ytile = ((1 << zoom) - 1);
 }
 
 return new TileCoordinate(xtile, ytile, zoom);
 }
  14. PreCaching Imp. (avoiding pitfalls) • Restrict area size (10000 tiles)

    • Check all tiles have been downloaded (service) • Synchronized access to tile files!! • Multi thread with limited thread pool size!!
  15. Advance Usage: MD5/Lower Tile Creation public class OfflineTileProvider extends UrlTileProvider


    { public static final String BAD_TILE_MD5 = "bb0f77951f30229b14a4d3ed0b836390"; 
 ...
 
 public static URL getFileUrl(MapQuestTiles.TileCoordinate coordinate)
 {
 
 ... url = MD5.compareMD5(BAD_TILE_MD5, coordinateFile) ? null : url;
 if(url == null)
 {
 try
 {
 File file = generateHigherZoomTile(coordinate);
 }
 catch(IOException e) {}
 } return url; }
  16. Future • Detect when Google tiles are available • Figure

    out how to share single source of tiles with all apps • Invalidate file cache • Delete unused file cache
  17. Practical Applications • Travel apps • Hiking • Sports tracking

    apps • Offline use of glass (sports) • Virtual walking tours • Gamify (hide and seek, first person shooter) • Navigating the seas
  18. apoorv@touchlab.co @t0idiu