【问题标题】:OSMdroid : How to render offline map from a local sqlite archiveOSMdroid:如何从本地 sqlite 存档渲染离线地图
【发布时间】:2019-12-16 19:13:41
【问题描述】:

使用 Android Studioosmdroid 库进行编程。 我使用cacheManager.downloadAreaAsync() 方法下载了地图的一部分。此方法将地图片段存储在我选择的 data/data/<package>/osmdroid/tiles 目录中的 sqlite 文件中。 现在我想使用这张地图在移动应用程序中离线加载它。 我尝试过各种课程 (MapTileSqlCacheProvider, XYTileSource, OfflineTileProvider, ...),但无法显示地图。

我该怎么做?

【问题讨论】:

  • 如果您通过Configuration.getInstance().set... 方法适当地设置了目录,并设置了与下载设置中使用的相同的地图图块源,它应该会自动加载。
  • 你能发一个你设置地图的sn-p吗?另外,如果你打开 sqlite 数据库,有一个列会告诉你瓦片源的名称

标签: android android-sqlite openstreetmap osmdroid


【解决方案1】:

要下载地图的一部分,我这样做:

map.setTileSource(TileSourceFactory.OpenTopo);    
outputPath = "/data/data/<package>/files" + File.separator + "osmdroid" + File.separator  + "tiles" + File.separator;
outputName = outputPath + boxE6.name + ".db";

try {
    writer=new SqliteArchiveTileWriter(outputName);
} catch (Exception ex) {
    ex.printStackTrace();
}
CacheManager cacheManager = new CacheManager(map,writer);
cacheManager.downloadAreaAsync(this, boxE6, 7, 13, new CacheManager.CacheManagerCallback() {

    @Override
    public void onTaskComplete() {
        Toast.makeText(ctx, "Download complete!", Toast.LENGTH_LONG).show();

        if (writer!=null)
            writer.onDetach();
    } ...

要检索存储的地图(在这种情况下它位于 usa.db 文件中),我尝试这样做:

map.setUseDataConnection(false);
map.setTileSource(TileSourceFactory.OpenTopo);

File cache = new File(outputName);
Configuration.getInstance().setOsmdroidTileCache(cache);

mapController.setCenter(new GeoPoint((n+s)/2,(e+w)/2));

【讨论】:

    【解决方案2】:

    我将展示我如何存储和加载多个 sqlite Tiles,而不仅仅是一个。

    José Espejo Roig 的上述回答仅对我部分有用。它几乎可以很好地缓存图块,但不能用于读取它们。写下缓存文件虽然也不完整。我创建了自己的代码,例如:来自 OSMDroid Github 的Make a tile archive

    因此,为了在特定目录中存储可能超过 1 个图块,我使用如下代码。它按顺序创建 my_mapX.sqlite,其中 X 只是步进的连续整数。所以我得到了 my_map1.sqlite、my_map2.sqlite 等等。

                private final String MAP_FILE_NAME = "my_map";
                private final String MAP_FILE_EXTENSION = ".sqlite";
    

    // ...

                Context ctx = getActivity();
                mMapView = new MapView(ctx);
                ((ConstraintLayout) view.findViewById(R.id.osm_fragment)).addView(mMapView);
                mMapView.setTileSource(TileSourceFactory.OpenTopo);
    
                ContextWrapper contextWrapper = new ContextWrapper(ctx);
                File root_directory = contextWrapper.getDir(ctx.getFilesDir().getName(), Context.MODE_PRIVATE);
                File directory_osm = new File(root_directory, "osmdroid");
                directory_osm.mkdir();
                File directory = new File(directory_osm, "tiles");
                directory.mkdir();
                File[] nrFiles = directory.listFiles(new FilenameFilter() {
                    @Override
                    public boolean accept(File dir, String name) {
                        if (name.endsWith(MAP_FILE_EXTENSION))
                            return true;
                        return false;
                    }
                });
                String osmdroidTile = directory.getAbsolutePath() + File.separator + MAP_FILE_NAME + (nrFiles.length + 1) + MAP_FILE_EXTENSION;
    
                BoundingBox boxE6 = mMapView.getBoundingBox();
    
                SqliteArchiveTileWriter writer = null;
    
                try {
                    writer = new SqliteArchiveTileWriter(osmdroidTile);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                CacheManager cacheManager = new CacheManager(mMapView, writer);
                SqliteArchiveTileWriter finalWriter = writer;
                int currZoom = (int)mMapView.getZoomLevelDouble();
                cacheManager.downloadAreaAsync(ctx, boxE6, currZoom, currZoom + 1, new CacheManager.CacheManagerCallback() {
                    @Override
                    public void onTaskComplete() {
                        Toast.makeText(ctx, "Download complete!", Toast.LENGTH_LONG).show();
    
                        if (finalWriter != null)
                            finalWriter.onDetach();
                    }
    
                    @Override
                    public void updateProgress(int progress, int currentZoomLevel, int zoomMin, int zoomMax) {
    
                    }
    
                    @Override
                    public void downloadStarted() {
    
                    }
    
                    @Override
                    public void setPossibleTilesInArea(int total) {
    
                    }
    
                    @Override
                    public void onTaskFailed(int errors) {
                        Toast.makeText(getActivity(), "Download complete with " + errors + " errors", Toast.LENGTH_LONG).show();
                        if (finalWriter != null)
                            finalWriter.onDetach();
                    }
                });
    
            }
        });
    

    这样我可以创建任意数量的图块文件。重要的是它们具有“.sqlite”扩展名。 “.db”扩展名对我不起作用。

    现在要阅读这些图块,我再次使用了来自 OSMDroid Github 的示例:Sample SQLITE example。在 OSMDroid Github 示例中,TileSource 是使用 IArchiveFile 确定的。我跳过了这个,因为我假设我知道我使用的是什么 TileSource(在我的例子中,它是 OpenTopo,如您所见)。然后从同一个 TileSource 读取多个离线磁贴(基于 OSMDroid 的示例),我的代码如下所示:

        //first we'll look at the default location for tiles that we support
        Context ctx = getActivity();
        mMapView = new MapView(ctx);
        ((ConstraintLayout) view.findViewById(R.id.osm_fragment)).addView(mMapView);
        mMapView.setUseDataConnection(false);
    
        ContextWrapper contextWrapper = new ContextWrapper(ctx);
        File root_directory = contextWrapper.getDir(ctx.getFilesDir().getName(), Context.MODE_PRIVATE);
        String osmDir = root_directory.getAbsolutePath() + File.separator + "osmdroid" + File.separator + "tiles";
        File f = new File(osmDir);
    
        if (f.exists()) {
    
            File[] list = f.listFiles();
    
            ArrayList<File> sqliteArray = new ArrayList<>();
    
            if (list != null) {
                for (int i = 0; i < list.length; i++) {
                    if (list[i].isDirectory()) {
                        continue;
                    }
                    String name = list[i].getName().toLowerCase();
                    if (!name.contains(".")) {
                        continue; //skip files without an extension
                    }
                    name = name.substring(name.lastIndexOf(".") + 1);
                    if (name.length() == 0) {
                        continue;
                    }
                    //narrow it down to only sqlite tiles
                    if (ArchiveFileFactory.isFileExtensionRegistered(name) && name.equals("sqlite")) {
                        sqliteArray.add(list[i]);
                    }
                }
            }
    
            OfflineTileProvider tileProvider;
            if (sqliteArray.size() > 0) {
                try {
                    tileProvider = new OfflineTileProvider(new SimpleRegisterReceiver(getActivity()), sqliteArray.toArray(new File[0]));
                    mMapView.setTileProvider(tileProvider);
                    mMapView.setTileSource(TileSourceFactory.OpenTopo);
                    mMapView.invalidate();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } else {
            Toast.makeText(getActivity(), f.getAbsolutePath() + " dir not found!", Toast.LENGTH_SHORT).show();
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多