I was wondering whether it was possible to do such a thing. I know that one would need to modify some of the existing code to pull this off but I was wondering if anyone had any direction on where to look and how to do this.
I am placing a few custom tiles on a specific area on the map as a replacement for OSM tiles providers but need them to be stored in the /assets/ folder. Any ideas?
I use the nexts classes to do that.
import java.io.InputStream;
import org.osmdroid.ResourceProxy.string;
import org.osmdroid.tileprovider.util.StreamUtils;
import android.content.res.AssetManager;
import android.graphics.drawable.Drawable;
public class AssetsTileSource extends CustomBitmapTileSourceBase {
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, aResourceId, 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;
}
}
MapTileFileAssetsProvider.java
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() : MAXIMUM_ZOOMLEVEL;
}
@Override
public int getMaximumZoomLevel() {
return mTileSource != null ? mTileSource.getMaximumZoomLevel() : MINIMUM_ZOOMLEVEL;
}
@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;
}
}
}
And
import java.io.File;
import java.io.InputStream;
import java.util.Random;
import org.osmdroid.ResourceProxy;
import org.osmdroid.ResourceProxy.string;
import org.osmdroid.tileprovider.ExpirableBitmapDrawable;
import org.osmdroid.tileprovider.MapTile;
import org.osmdroid.tileprovider.constants.OpenStreetMapTileProviderConstants;
import org.osmdroid.tileprovider.tilesource.ITileSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
public abstract class CustomBitmapTileSourceBase implements ITileSource,
OpenStreetMapTileProviderConstants {
private static final Logger logger = LoggerFactory.getLogger(CustomBitmapTileSourceBase.class);
private static int globalOrdinal = 0;
private final int mMinimumZoomLevel;
private final int mMaximumZoomLevel;
private final int mOrdinal;
protected final String mName;
protected final String mImageFilenameEnding;
protected final Random random = new Random();
private final int mTileSizePixels;
private final string mResourceId;
public CustomBitmapTileSourceBase(final String aName, final string aResourceId,
final int aZoomMinLevel, final int aZoomMaxLevel, final int aTileSizePixels,
final String aImageFilenameEnding) {
mResourceId = aResourceId;
mOrdinal = globalOrdinal++;
mName = aName;
mMinimumZoomLevel = aZoomMinLevel;
mMaximumZoomLevel = aZoomMaxLevel;
mTileSizePixels = aTileSizePixels;
mImageFilenameEnding = aImageFilenameEnding;
}
@Override
public int ordinal() {
return mOrdinal;
}
@Override
public String name() {
return mName;
}
public String pathBase() {
return mName;
}
public String imageFilenameEnding() {
return mImageFilenameEnding;
}
@Override
public int getMinimumZoomLevel() {
return mMinimumZoomLevel;
}
@Override
public int getMaximumZoomLevel() {
return mMaximumZoomLevel;
}
@Override
public int getTileSizePixels() {
return mTileSizePixels;
}
@Override
public String localizedName(final ResourceProxy proxy) {
return proxy.getString(mResourceId);
}
@Override
public Drawable getDrawable(final String aFilePath) {
try {
// default implementation will load the file as a bitmap and create
// a BitmapDrawable from it
final Bitmap bitmap = BitmapFactory.decodeFile(aFilePath);
if (bitmap != null) {
return new ExpirableBitmapDrawable(bitmap);
} else {
// if we couldn't load it then it's invalid - delete it
try {
new File(aFilePath).delete();
} catch (final Throwable e) {
logger.error("Error deleting invalid file: " + aFilePath, e);
}
}
} catch (final OutOfMemoryError e) {
logger.error("OutOfMemoryError loading bitmap: " + aFilePath);
System.gc();
}
return null;
}
@Override
public String getTileRelativeFilenameString(final MapTile tile) {
final StringBuilder sb = new StringBuilder();
sb.append(pathBase());
sb.append('/');
sb.append(tile.getX());
sb.append('_');
sb.append(tile.getY());
sb.append('_');
sb.append(tile.getZoomLevel());
sb.append(imageFilenameEnding());
return sb.toString();
}
@Override
public Drawable getDrawable(final InputStream aFileInputStream) {
try {
// default implementation will load the file as a bitmap and create
// a BitmapDrawable from it
final Bitmap bitmap = BitmapFactory.decodeStream(aFileInputStream);
if (bitmap != null) {
return new ExpirableBitmapDrawable(bitmap);
}
System.gc();
} catch (final OutOfMemoryError e) {
logger.error("OutOfMemoryError loading bitmap");
System.gc();
//throw new LowMemoryException(e);
}
return null;
}
public final class LowMemoryException extends Exception {
private static final long serialVersionUID = 146526524087765134L;
public LowMemoryException(final String pDetailMessage) {
super(pDetailMessage);
}
public LowMemoryException(final Throwable pThrowable) {
super(pThrowable);
}
}
}
Modify method getTileRelativeFilenameString() to get yout tiles (i use the next format: x_y_zoom.png)
Example:
mapView = new MapView(getApplicationContext(), 256);
mapView.setClickable(true);
mapView.setTag("Mapa");
mapView.setTileSource(TileSourceFactory.MAPNIK);
mapView.setMultiTouchControls(true);
mapView.setUseDataConnection(true);
MapTileModuleProviderBase moduleProvider =
new MapTileFileAssetsProvider(ASSETS_TILE_SOURCE);
SimpleRegisterReceiver simpleReceiver =
new SimpleRegisterReceiver(getApplicationContext());
MapTileProviderArray tileProviderArray =
new MapTileProviderArray(ASSETS_TILE_SOURCE, simpleReceiver,
new MapTileModuleProviderBase[] { moduleProvider });
TilesOverlay tilesOverlay =
new TilesOverlay(tileProviderArray, getApplicationContext());
mapView.getOverlays().add(tilesOverlay);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With