4

この機能を備えた TileProvider を実装したいと思います。

  • Mapを求めるTile
  • TileProvider は、Tileオフラインで使用できるかどうかを確認します
  • もしそうなら、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;
        }
    }
}

ただし、これはメモリにのみキャッシュするため、ユーザーがアプリを閉じるとキャッシュされず、Tilesダウンロードされる前にデフォルトの Google マップ マップが表示されます。

UrlTileProvidergetTileとして実装されてfinalいるため、上書きできません。メソッドTileProviderがなく、ソリューションを書き直すためのソース コードがありません。getTileURLUrlTileProvider

これにどのようにアプローチすればよいですか?私がやりたいことをする方法はありますか?なぜgetTile最終的なのですか?何か不足していますか?

4

1 に答える 1

1

最初のクラスをラップする2番目のクラスで解決しました。

私はラッパーが嫌いですが、これは私が考えることができる最良のアプローチであり、かなりうまく機能していると言わざるを得ません。

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 が非常に非効率的であることは承知しています。私のコードへのアップグレードは大歓迎です。

于 2013-05-22T11:19:02.140 に答える