如何防止Mapnik在基于OSMdroid的应用程序中混合图块源

问题描述 投票:1回答:1

我制作了一个供个人使用的地图应用程序,在其中可以选择以下三个地图源之一:OpenTopo,Mapnik或HikeBike。它主要供离线使用,为此,我下载了一套完整的OpenTopo位图图块(.png),涵盖了我最感兴趣的局部区域的11到15缩放级别。另一方面,我仅打算在Mapnik和HikeBike地图模式在线时使用,主要用于旅行计划等。

OpenTopo tile存档直接作为.gemf文件存储在/ storage / extSdCard / osmdroid /中(这是通过查询Configuration.getInstance().getOsmdroidBasePath().getAbsolutePath();返回的路径)。

我现在遇到的问题是,即使连接到互联网,两种“辅助”地图模式(Mapnik和HikeBike)也无法完全“尊重”已设置供其使用的图块源。相反,只要地图视图所需的位置和缩放级别被本地可用的OpenTopo磁贴覆盖,Mapnik / HikeBike就会讨厌地显示这些磁贴。

我已将map.setUseDataConnection(true)放入onCreate(),我希望这将使在线获取(丢失)图块成为默认设置,并已授予网络连接。

我希望在(1)上获得建议,如所期望的,如何使基于矢量的地图模式在其自己的正确图块和OpenTopo静态位图之间进行区分。以及(2)如何诱使他们动态下载任何丢失的图块(如果实际上在线的话)。

以下是我的MapsActivity.java文件中1100余行代码中的一些潜在相关片段:

// ===========================================================
//                      (Some) Constants
// ===========================================================

private static final String tileSourceName_MPNK = "Mapnik";
private static final String tileSourceName_HKBK = "HikeBikeMap";
private static final String tileSourceName_OPTP = "OpenTopoMap";

// Pre-select the default (initial) tile source here
public static String activeTileSourceName = tileSourceName_OPTP;


// ===========================================================
//                      (Some) Fields
// ===========================================================

private SharedPreferences mPrefs;
MapView map = null;     
SqliteArchiveTileWriter tileWriter = null;

// Some state booleans
boolean registeredNetworkReceiver = false;
boolean wiffiUp = false;


// ===========================================================
//                    (parts of) onCreate
// ===========================================================

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mContext = this;

    // Load/initialize the osmdroid configuration
    final Context ctx = getApplicationContext();
    Configuration.getInstance().load(ctx, PreferenceManager.getDefaultSharedPreferences(ctx));
    final DisplayMetrics dm = ctx.getResources().getDisplayMetrics();

    mPrefs = ctx.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);

    // Inflate and create the map
    setContentView(R.layout.activity_maps);
    map = findViewById(R.id.map);

    // Set initial map type (tile source)
    map.setTileSource(TileSourceFactory.getTileSource(activeTileSourceName));

    ...

    // Use custom [+][-] buttons
    map.getZoomController().setVisibility(
            CustomZoomButtonsController.Visibility.SHOW_AND_FADEOUT);

    // Scale tiles relative to the current screen's DPI. Should help with readability in "the field"
    map.setTilesScaleFactor(1.2f);          // Compromise scale, better than dpi

    // Store the startup zoom level we just set, so it survives first pass through onResume()
    final SharedPreferences.Editor edit = mPrefs.edit();
    edit.putFloat(PREFS_ZOOM_LEVEL_DOUBLE, (float) map.getZoomLevelDouble());
    edit.apply();

    ....

    // If/when we have a network connection: default to using (missing?) on-line tiles.
    map.setUseDataConnection(true);

    // Register a wiffi networkReceiver
    registerReceiver();
}


// ===========================================================
//                    (parts of) onPause
// ===========================================================

@Override
public void onPause() {

    // Save the current location
    final SharedPreferences.Editor edit = mPrefs.edit();
    edit.putString(PREFS_TILE_SOURCE, map.getTileProvider().getTileSource().name());

}

// ===========================================================
//                    (parts of) onResume
// ===========================================================

@Override
protected void onResume() {
    super.onResume();

    // Set zoom to default level if first pass, else to the latest level stored onPause().
    final float zoomLevel = mPrefs.getFloat(PREFS_ZOOM_LEVEL_DOUBLE, 1);
    map.getController().setZoom(zoomLevel);

}


// ===========================================================
//                    (parts of) onDestroy
// ===========================================================

@Override
protected void onDestroy() {
    unregisterReceiver(networkReceiver);
    ....

    super.onDestroy();
}


// ===========================================================
//            networkReceiver --> onReceive
// ===========================================================

/**
The idea behind the following function is to force a map refresh when switching from offline to online. If the display is not refreshed there may be no attempt to get better tiles */

private final BroadcastReceiver networkReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
                NetworkInfo networkInfo = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
                if (networkInfo != null && networkInfo.getDetailedState() == NetworkInfo.DetailedState.CONNECTED) {
                    Log.d("Network", "Internet YAY !!!!!!!!!!!!!!!!!!");
                    toaster("Internet YAY !!!!!!!!!!!!!!!!!!");
                    wiffiUp = true;
                } else if (networkInfo != null && networkInfo.getDetailedState() == NetworkInfo.DetailedState.DISCONNECTED) {
                    Log.d("Network", "No internet :(");
                    toaster("No internet :(");
                    wiffiUp = false;
                }
                map.invalidate();    // i.e. refresh screen
            }
        }
        catch(NullPointerException e) {
            e.printStackTrace();
        }
    }
};


// ===========================================================
//                      registerReceiver
// ===========================================================

private void registerReceiver() {
    if (registeredNetworkReceiver) {
        return;
    }
    registeredNetworkReceiver = true;
    IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
    MapsActivity.this.registerReceiver(networkReceiver, filter);
}


// ===========================================================
//                      onOptionsItemSelected
// ===========================================================

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id. map1_menu:
            map.setTileSource(TileSourceFactory.getTileSource(tileSourceName_OPTP));
            toaster(" OpenTopo map ");
            return true;

        case R.id. map2_menu:
            map.setTileSource(TileSourceFactory.getTileSource(tileSourceName_MPNK));
            map.invalidate();
            toaster(" Mapnik map ");
            return true;

        case R.id. map3_menu:
            map.setTileSource(TileSourceFactory.getTileSource(tileSourceName_HKBK));
            map.invalidate();
            toaster(" BikeHike map ");
            return true;

        default:
            return super.onOptionsItemSelected(item);
    }
}

编辑2:这是显示/ storage / extSdCard / osmdroid目录结构的屏幕截图:

storage extSdCard.png

osmdroid gemfile mapnik
1个回答
0
投票

我首先通过将缓存的切片从“ / storage / extSdCard / osmodroid / tiles”移动到新目录“ / storage / extSdCard / osmXtra / tiles”,然后从根本上去除了onCreate()和将其放在单独的函数onCreateCommonCode(String tileSourceName_X)中,该函数以TileSource名称作为参数。

现在,此功能在启动时以默认的OpenTopoMaps作为输入在onCreate()中运行一次,并且每当用户命令切换地图类型时(也带有适当的TileSource参数)运行一次。一个简单的“ if TileSourceThis then TilePathTha t”测试将选择正确的目录以搜索存档文件或切片缓存。

也许不是最优雅的解决方案,但除了一些小怪异之处,例如mLocationOverlay.enableFollowLocation()在切换地图后的行为,我对它现在的工作方式感到满意。

© www.soinside.com 2019 - 2024. All rights reserved.