2013-05-22 27 views
3

我想要實現這個功能的TileProvider:谷歌地圖Android的阿比2 - 混合TileProvider/URLTileProvider爲MapBox實施

如果說 Tile可脫機
  • Map要求一個Tile
  • TileProvider檢查
  • 如果是這樣,TileProvider返回說Tile
  • 無論可用性,TileProvider在線檢查一個新的瓷磚並將其下載到Cache在外部存儲器中。
  • TileProvider給出新地圖的地圖,地圖更新它。

這是我目前UrlTileProvider實現:

public class MapBoxOnlineTileProvider extends UrlTileProvider { 

    private static final String[] FORMATS; 

    static { 
     final String[] servers = new String[] { "a", "b", "c", "d" }; 
     final String[] formats = new String[servers.length]; 
     for (int i = 0; i < servers.length; i++) { 
      formats[i] = String.format(
        "%%s://%s.tiles.mapbox.com/v3/%%s/%%d/%%d/%%d.png", 
        servers[i]); 
     } 
     FORMATS = formats; 
    } 

    // ------------------------------------------------------------------------ 
    // Instance Variables 
    // ------------------------------------------------------------------------ 

    private String mMapIdentifier; 

    // ------------------------------------------------------------------------ 
    // Constructors 
    // ------------------------------------------------------------------------ 



    public MapBoxOnlineTileProvider(final String mapIdentifier) { 
     super(256, 256); 
     this.mMapIdentifier = mapIdentifier; 
    } 

    // ------------------------------------------------------------------------ 
    // Public Methods 
    // ------------------------------------------------------------------------ 

    public String getMapIdentifier() { 
     return this.mMapIdentifier; 
    } 

    public void setMapIdentifier(final String anIdentifier) { 
     this.mMapIdentifier = anIdentifier; 
    } 

    @Override 
    public URL getTileUrl(final int x, final int y, final int z) { 
     final String f = FORMATS[new Random().nextInt(FORMATS.length)]; 
     final String p = "http"; 
     try { 
      return new URL(String.format(f, p, this.mMapIdentifier, z, x, y)); 
     } catch (final MalformedURLException e) { 
      e.printStackTrace(); 
      return null; 
     } 
    } 
} 

然而,這隻會緩存在內存中,所以如果用戶關閉我的應用程序不會將它們緩存,默認的谷歌地圖的地圖將在下載之前出現。

UrlTileProvider implements getTile as final,所以我不能覆蓋它。 TileProvider沒有getTileURL方法,並且UrlTileProvider源代碼不可用於我重寫我的解決方案。

我該如何解決這個問題?有什麼辦法可以做我想做的事嗎?爲什麼getTile最終?我錯過了什麼嗎?

回答

0

解決它與包裝在第一類的第二類。

儘管我不喜歡包裝紙,但這是我能想到的最好的方法,我必須說它很好地工作。

public class MapBoxMixedTileProvider implements TileProvider { 

    private final MapBoxOnlineTileProvider provider; 
    private final Context context; 

    public MapBoxMixedTileProvider(final Context context, final String mapId) { 
     provider = new MapBoxOnlineTileProvider(mapId); 
     this.context = context; 
    } 

    @Override 
    public Tile getTile(final int arg0, final int arg1, final int arg2) { 
     final URL url = provider.getTileUrl(arg0, arg1, arg2); 
     // Remove the "http://a." from the url, then replace all the '/' and '.' 
     // with 
     // '_', then replace the final "_png" with ".png", so openFileInput 
     // doesn't cry a lot. 
     final String finalUrl = (url.toString().substring(9)).replace('/', '_') 
       .replace('.', '_').replace("_png", ".png"); 
     System.out.println(finalUrl); 
     boolean contained = false; 
     for (final String file : context.fileList()) { 
      if (file.contains(finalUrl)) { 
       contained = true; 
       break; 
      } 
     } 
     try { 
      if (contained) { 
       final FileInputStream fis = context.openFileInput(finalUrl); 
       return new Tile(256, 256, byteArrayFromInputStream(fis)); 
      } else { 
       final FileOutputStream fos = context.openFileOutput(finalUrl, 
         Context.MODE_PRIVATE); 
       final Tile t = provider.getTile(arg0, arg1, arg2); 
       fos.write(t.data); 
       fos.flush(); 
       fos.close(); 
       return t; 
      } 
     } catch (final IOException ex) { 
      ex.printStackTrace(); 
      return null; 
     } 
    } 

    private byte[] byteArrayFromInputStream(final FileInputStream is) 
      throws IOException { 
     final BufferedInputStream bis = new BufferedInputStream(is); 
     final ArrayList<Integer> bytes = new ArrayList<Integer>(); 
     int current = 0; 
     while ((current = bis.read()) != -1) { 
      bytes.add(Integer.valueOf(current)); 
     } 
     final byte[] bs = new byte[bytes.size()]; 
     for (int i = 0; i < bytes.size(); i++) { 
      bs[i] = bytes.get(i).byteValue(); 
     } 
     bis.close(); 
     is.close(); 
     return bs; 
    } 

} 

這樣,爲了得到TileProvider工作,我只需要做到這一點:

final MapBoxMixedTileProvider provider = new MapBoxMixedTileProvider(
         this, MAPBOX_MAP_IDENTIFIER); 
//zIndex is set to -4 so Polyines and Polygons get shown OVER and not under the Overlay 
final TileOverlayOptions overlay = new TileOverlayOptions().tileProvider(provider).zIndex(-4); 
tileOverlay = mMap.addTileOverlay(overlay); 

我知道,我的byteArrayFromInputStream是非常低效的。歡迎任何升級到我的代碼。

+0

什麼是MapBoxOnlineTileProvider? – pablobaldez

0

由於信譽度低,我無法發表評論。評論到這一點:

我知道我的byteArrayFromInputStream是極其低效率。歡迎任何升級到我的代碼。

看一看this,它顯示了從文件中讀取數據更有效的方法 - 利用緩衝和省略的ArrayList