0

So I've finally gotten osmdroid working with a local directory but I'd like to load tiles from Mapnik when they are missing locally. I'm not sure what I'm missing.

My implementation is as follows:

private MapView mapView = null;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.osm_map);

    mapView = (MapView) findViewById(R.id.mapview);
    mapView.setBuiltInZoomControls(true);
    mapView.setMultiTouchControls(true);

    MapController mapController = mapView.getController();
    mapController.setZoom(5);
    GeoPoint point2 = new GeoPoint(55708545, 10006348);
    mapController.setCenter(point2);

    //TODO Save to SD
    AssetManager assetManager = getAssets();
    InputStream is;
    String fileName = "test.zip";
    String path = Environment.getExternalStorageDirectory() + File.separator + fileName;    //TODO Path to save it to
    try {
        is = assetManager.open(fileName);

        FileOutputStream fo = new FileOutputStream(path);

        byte[] b = new byte[1024];
        int length;
        while((length = is.read(b)) != -1) {
            fo.write(b, 0, length);
        }
        fo.flush();
        fo.close();
        is.close();
    } catch (IOException  e) {
        e.printStackTrace();
    }

    File tileFile = new File(path);
    IArchiveFile[] archives = new IArchiveFile[1];
    archives[0] = ArchiveFileFactory.getArchiveFile(tileFile);

    CustomTileSource customTiles = new CustomTileSource("Mapnik", null, 0, 24, 256, ".png");    // the name should match the name of the folder that is zipped

    MapTileModuleProviderBase[] providers = new MapTileModuleProviderBase[2];
    providers[0] = new MapTileFileArchiveProvider(new SimpleRegisterReceiver(getApplicationContext()), customTiles, archives);
    providers[1] =  new MapTileDownloader(TileSourceFactory.MAPNIK);
    mapView.setUseDataConnection(false);
    mapView.setTileSource(TileSourceFactory.MAPNIK);

    MapTileProviderArray tileProvider = new MapTileProviderArray(customTiles, null, providers);
    TilesOverlay tilesOverlay = new TilesOverlay(tileProvider, getApplicationContext());
    mapView.getOverlays().add(tilesOverlay);
    mapView.invalidate();
}

AND

public class CustomTileSource extends BitmapTileSourceBase {

    public CustomTileSource(String aName, string aResourceId,
            int aZoomMinLevel, int aZoomMaxLevel, int aTileSizePixels,
            String aImageFilenameEnding) {
        super(aName, aResourceId, aZoomMinLevel, aZoomMaxLevel, aTileSizePixels,
                aImageFilenameEnding);
    }

}
Warpzit
  • 27,966
  • 19
  • 103
  • 155
  • mapView.setUseDataConnection(false); can't be helping... Put the zip file (the other formats are far better if you have a lot of data) in the right place and it should just work. – Ifor Nov 08 '12 at 11:28
  • Actually I've tried with both false true and not having it there. None made a difference. The tiles from zip work perfectly but I'd like to get the missing tiles from marverik or similar. – Warpzit Nov 08 '12 at 11:34
  • I don't have access to my code but I don't think I have any custom provider stuffjust the standard Mapnik provider but make sure the file is copied to /osmdroid directory. The standard provider already looks for suitable files there to use before it falls back to online. – Ifor Nov 08 '12 at 16:13
  • Ye but it works fine with standard provider, and I could also just move the zip to the standard osmdroid folder and it would work but IF a person would have happent to have seen the area I'm trying to show before it would be cached. Then the cached result would be shown instead of my custom tiles. Thats why I'm trying to do this "workaround" with a custom folder and custom local provider. – Warpzit Nov 08 '12 at 19:14

1 Answers1

4

Okay so I've finally found a solution. Its quite complex and long but it works :D

Now inside my OsmDroidFragment (yes map in fragment) I have following:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    RelativeLayout view = (RelativeLayout) inflater.inflate(R.layout.osm_map, container, false);
    RelativeLayout mapContainer = (RelativeLayout) view.findViewById(R.id.osm_map_parent);

    mMapView = new OsmCustomMapView(getActivity(), 256, 10, 13);    // I've made a custom implementation in order to limit zoom, you can just use regular osmdroid mapview
    LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    mMapView.setLayoutParams(params);
    mapContainer.addView(mMapView);

    mMapView.setBuiltInZoomControls(true);
    mMapView.setMultiTouchControls(false);  // pinch zoom works bad on osmdroid

    MapController mapController = mMapView.getController();
    mapController.setZoom(11);  // must set zoom before setCenter, else we get the wrong position
    GeoPoint center = new GeoPoint(0,0);
    mapController.setCenter(center);

    // save zip to sd
    AssetManager assetManager = getActivity().getAssets();
    InputStream is;
    String fileName = "map.zip";    // the zip file lies in assets root
    String path = this.getActivity().getExternalFilesDir(null) + File.separator + fileName; // the path I save SD to

    File tileFile = new File(path);
    if(!tileFile.exists()) {
        try {
            is = assetManager.open(fileName);

            FileOutputStream fo = new FileOutputStream(path);

            byte[] b = new byte[1024];
            int length;
            while((length = is.read(b)) != -1) {
                fo.write(b, 0, length);
            }

            fo.flush();
            fo.close();
            is.close();
        } catch (IOException  e) {
            e.printStackTrace();
        }
    }

    IArchiveFile[] archives = new IArchiveFile[1];
    archives[0] = ArchiveFileFactory.getArchiveFile(tileFile);

    // Simple implementation that extends BitmapTileSourceBase and nothing else
    CustomTileSource customTiles = new CustomTileSource("Maverik", null, 10, 14, 256, ".png");  // Maverik is the name of the folder inside the zip (so zip is map.zip and inside it is a folder called Maverik)

    MapTileModuleProviderBase[] providers = new MapTileModuleProviderBase[2];
    providers[0] = new MapTileFileArchiveProvider(new SimpleRegisterReceiver(getActivity().getApplicationContext()), customTiles, archives);    // this one is for local tiles (zip etc.)
    providers[1] =  new MapTileDownloader(TileSourceFactory.MAPNIK);    // MAPNIK web tile source

    mMapView.setUseDataConnection(true);

    MapTileProviderArray tileProvider = new MapTileProviderArray(customTiles, 
            new SimpleRegisterReceiver(getActivity().getApplicationContext()), providers);
    TilesOverlay tilesOverlay = new TilesOverlay(tileProvider, getActivity().getApplicationContext());
    tilesOverlay.setLoadingBackgroundColor(Color.TRANSPARENT);  // this makes sure that the invisble tiles of local tiles are transparent so we can see tiles from web, transparent have a minor performance decline.

    mMapView.getOverlays().add(tilesOverlay);

    mMapView.invalidate();

    return view;
}
Warpzit
  • 27,966
  • 19
  • 103
  • 155
  • Hey...! I was wondering if you could nudge me in the right direction with regards to my error...? It seems like I have to use super.onCreateView() method or it will cause the error I'm having, but I can't use that... or at least I'm not sure how to do it? http://stackoverflow.com/questions/14984617/nulpointerexception-on-implementing-fragments-for-osmdroid – lyk Feb 20 '13 at 17:12