【问题标题】:How to use assets as a source for osmdroid offline maps如何使用资产作为 osmdroid 离线地图的来源
【发布时间】:2023-04-01 11:02:01
【问题描述】:

我正在尝试在我的应用程序中使用 osmdroid 进行离线地图使用,但我找不到的是如何从 /assets 文件夹中设置图块源。 所以我有瓷砖(来自Mobile Atlas Creator),放在/assets/maps.zip 我正在尝试这样的事情:

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); 

.. 这在某种程度上似乎是错误的。那么有人可以指点我如何做到这一点吗?

【问题讨论】:

    标签: android osmdroid


    【解决方案1】:

    好的,这个问题几年前就被问过了,
    但是仍然没有关于如何使用资产文件夹中的离线地图的明确信息。
    所以这是我的解决方案。

    1. 使用 Mobile Atlas Creator 创建地图。
      我使用 Atlas 格式 = osmdroid zip 和地图源 = OpenStreetMap 4UMaps.eu
    2. 解压地图并放入您的资产文件夹:
      assets/map/14,其中 14 - 例如具有相应缩放级别的文件夹(您可能会有多个文件夹)
    3. 添加我在互联网上某处找到的类:

      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;
            }
        }
    }
    
    1. 添加常量:
     // 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 创建的最小和最大缩放级别。

    1. 最后,但并非最不重要的,
      实现代码的sn-p:

          // 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;
              }
          });
      

    【讨论】:

    • 在我的新最小项目(2021 年 8 月)中,org.osmdroid.ResourceProxy 无法解决。
    【解决方案2】:

    资产路径是“file:///android_asset/”,如果您需要输入流,您可以通过 AssetManager 获取。

    【讨论】:

    • 检查原始文件夹。我认为资产不适合这个目的。但我不知道 osmdroid 是否支持这种地图“注入”
    • 事实证明它通常不会:/
    【解决方案3】:

    看看BitmapAssetTileSourceiBurn-2012 也可能有助于查看它的实际效果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-23
      相关资源
      最近更新 更多