Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Offline Maps

Offline Maps

More about the project: https://www.youtube.com/watch?app=desktop&v=kXJ7BiDmNss

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.

Apoorv Kothari

May 16, 2015
Tweet

More Decks by Apoorv Kothari

Other Decks in Technology

Transcript

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

    Map layer • Efficiently download tiles
  2. 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
  3. 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
  4. 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
  5. Integrating with Map Layer • Google Map / TileOverlay /

    UrlTileProvider • getTileUrl() -> doesTileExists? -> saveToFile -> return file URL doesTileExists? saveTileToFile() getFileURL() getTileUrl() No Yes
  6. 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){}
 } 
 }
  7. 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;
 }
 }
  8. 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);
 }
  9. 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!!
  10. 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; }
  11. 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
  12. 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