好的,这个问题几年前就被问过了,
但仍然没有关于如何使用资产文件夹中的离线地图的明确信息。
所以这是我的解决方案。
- 使用 Mobile Atlas Creator 创建地图。
我使用 Atlas 格式 = osmdroid zip 和地图源 = OpenStreetMap 4UMaps.eu
- 解压缩地图并放入您的资产文件夹:
assets/map/14,其中 14 - 例如具有相应缩放级别的文件夹(您可能会有多个文件夹)
添加我在互联网上某处找到的类:
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;
}
}
和
/**
* 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";
您可能已经猜到了,它们代表了我们之前使用 Mobile Atlas Creator 创建的最小和最大缩放级别。
最后但并非最不重要
的实现代码片段:
// 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;
}
});