Reputation: 871
I'm trying to use osmdroid for offline map usage in my app, but the thing which I'm not able to find is how to set the tile source from the /assets
folder.
So I've got the tiles (from Mobile Atlas Creator), placed in /assets/maps.zip
and I'm trying something like this:
final ITileSource tileSource =
new XYTileSource("maps", null, 15, 17, 256, "png", "/assets");
mapview.setBuiltInZoomControls(true);
mapview.setTileSource(tileSource);
mapview.getController().setZoom(15);
mapview.setUseDataConnection(false);
.. which seems to be wrong some way. So can anybody point me on how to do that?
Upvotes: 1
Views: 2613
Reputation: 15046
OK, the question has been asked a couple of years ago,
but there is still no clear info on how to use offline maps from the assets folder.
So here is my solution.
Add classes which I found somewhere on the internet:
import android.content.res.AssetManager;
import android.graphics.drawable.Drawable;
import org.osmdroid.ResourceProxy.string;
import org.osmdroid.tileprovider.tilesource.BitmapTileSourceBase;
import org.osmdroid.tileprovider.util.StreamUtils;
import java.io.InputStream;
/**
* Custom tile source,
* used to load map tiles from the assets
*/
public class AssetsTileSource extends BitmapTileSourceBase {
private final AssetManager mAssetManager;
public AssetsTileSource(final AssetManager assetManager, final String aName, final string aResourceId,
final int aZoomMinLevel, final int aZoomMaxLevel, final int aTileSizePixels,
final String aImageFilenameEnding) {
super(aName, aZoomMinLevel, aZoomMaxLevel, aTileSizePixels, aImageFilenameEnding);
mAssetManager = assetManager;
}
@Override
public Drawable getDrawable(final String aFilePath) {
InputStream inputStream = null;
try {
inputStream = mAssetManager.open(aFilePath);
if (inputStream != null) {
final Drawable drawable = getDrawable(inputStream);
return drawable;
}
} catch (final Throwable e) {
// Tile does not exist in assets folder.
// Ignore silently
} finally {
if (inputStream != null) {
StreamUtils.closeStream(inputStream);
}
}
return null;
}
}
and
/**
* Map tile provider, loads tile from assets folder
*/
public class MapTileFileAssetsProvider extends MapTileModuleProviderBase {
protected ITileSource mTileSource;
public MapTileFileAssetsProvider(final ITileSource pTileSource) {
super(OpenStreetMapTileProviderConstants.NUMBER_OF_TILE_FILESYSTEM_THREADS, OpenStreetMapTileProviderConstants.TILE_FILESYSTEM_MAXIMUM_QUEUE_SIZE);
mTileSource = pTileSource;
}
@Override
public boolean getUsesDataConnection() {
return false;
}
@Override
protected String getName() {
return "Assets Folder Provider";
}
@Override
protected String getThreadGroupName() {
return "assetsfolder";
}
@Override
protected Runnable getTileLoader() {
return new TileLoader();
}
@Override
public int getMinimumZoomLevel() {
return mTileSource != null ? mTileSource.getMinimumZoomLevel() : Constants.MAP_ZOOM_ZOOM_MAX;
}
@Override
public int getMaximumZoomLevel() {
return mTileSource != null ? mTileSource.getMaximumZoomLevel() : Constants.MAP_ZOOM_ZOOM_MIN;
}
@Override
public void setTileSource(final ITileSource pTileSource) {
mTileSource = pTileSource;
}
private class TileLoader extends MapTileModuleProviderBase.TileLoader {
@Override
public Drawable loadTile(final MapTileRequestState pState) throws CantContinueException {
if (mTileSource == null) {
return null;
}
final MapTile pTile = pState.getMapTile();
String path = mTileSource.getTileRelativeFilenameString(pTile);
Drawable drawable;
try {
drawable = mTileSource.getDrawable(path);
} catch (final LowMemoryException e) {
// low memory so empty the queue
throw new CantContinueException(e);
}
return drawable;
}
}
}
// map min zoom level
public static final int MAP_ZOOM_ZOOM_MIN = 12;
// map max zoom level
public static final int MAP_ZOOM_ZOOM_MAX = 14;
// maps folder name in assets
public static final String MAP_ASSETS_FOLDER_NAME = "map";
As you probably guessed, they represent minimum and maximum zoom level, which we previously created with the Mobile Atlas Creator.
The last, but not the least,
the snippet of implementation code:
// making the map not use internet
mBinding.mapView.setUseDataConnection(false);
// Initializing the tile provider to use offline maps from the assets
// This will load for instance from /map/14/12345/12345.png
AssetsTileSource tileSource = new AssetsTileSource(
getAssets(),
Constants.MAP_ASSETS_FOLDER_NAME,
ResourceProxy.string.offline_mode,
Constants.MAP_ZOOM_ZOOM_MIN,
Constants.MAP_ZOOM_ZOOM_MAX,
256, ".png");
MapTileModuleProviderBase moduleProvider = new
MapTileFileAssetsProvider(tileSource);
SimpleRegisterReceiver simpleReceiver = new
SimpleRegisterReceiver(this);
MapTileProviderArray tileProviderArray = new
MapTileProviderArray(tileSource, simpleReceiver, new
MapTileModuleProviderBase[] { moduleProvider });
mBinding.mapView.setTileProvider(tileProviderArray);
// not forget to invalidate the map on zoom
mBinding.mapView.setMapListener(new MapListener() {
@Override
public boolean onScroll(ScrollEvent scrollEvent) {
return false;
}
@Override
public boolean onZoom(ZoomEvent zoomEvent) {
mBinding.mapView.invalidate();
return false;
}
});
Upvotes: 2
Reputation: 51804
Take a look at BitmapAssetTileSource
. Also the iBurn-2012 might be useful to see it in action.
Upvotes: 0
Reputation: 1382
asset path is "file:///android_asset/" if you need a inputstream you get it via AssetManager.
Upvotes: 0