OSMdroid:如何从本地sqlite存档呈现脱机地图

时间:2019-12-16 19:13:41

标签: android android-sqlite openstreetmap osmdroid

使用 Android Studio array1.find(x => callback(x))库进行编程。 我使用osmdroid方法下载了地图的一部分。此方法将地图片段存储在我选择的cacheManager.downloadAreaAsync()目录中的sqlite文件中。 现在,我想使用此地图将其离线加载到移动应用程序中。 我尝试通过各种类(data/data/<package>/osmdroid/tiles)来做到这一点,但我无法显示地图。

我应该怎么做?

2 个答案:

答案 0 :(得分:0)

要下载部分地图,请执行以下操作:

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

答案 1 :(得分:0)

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

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

因此,为了在特定目录中存储可能超过 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();
    }