Как я могу запретить Mapnik смешивать источники листов в моем приложении на базе OSMdroid - PullRequest
1 голос
/ 07 ноября 2019

Я создал приложение для карт для личного использования, в котором я могу выбрать один из трех источников карт: OpenTopo, Mapnik или HikeBike. Он в первую очередь предназначен для автономного использования, и для этого я скачал полный набор растровых плиток OpenTopo (.png), охватывающих уровни масштабирования с 11 по 15 для локальных областей, которые меня интересуют больше всего. Режимы карт Mapnik и HikeBike, с другой стороны, я намереваюсь использовать только в режиме онлайн, в основном для планирования туров и т. Д.

Архивы листов OpenTopo хранятся в виде файлов .gemf непосредственно в / storage /extSdCard / osmdroid / (путь, возвращаемый запросом Configuration.getInstance().getOsmdroidBasePath().getAbsolutePath();).

Проблема, с которой я столкнулся сейчас, заключается в том, что два «вспомогательных» режима карты (Mapnik и HikeBike) не полностью «учитывают» источники листов, которые были установлены для них, даже если они подключены кИнтернет. Вместо этого всякий раз, когда локальность и уровни масштабирования, необходимые для просмотра карты, покрыты локально доступными плитками OpenTopo, Mapnik / HikeBike с досадой предпочитают отображать эти плитки.

Я поместил map.setUseDataConnection(true) в onCreate(), что янадеялся, что выборка (отсутствие) тайлов в сети будет использоваться по умолчанию при условии подключения к сети.

Буду признателен за совет ( 1 ), как сделать режимы векторной карты различать междуих собственные правильные тайлы и статические растровые изображения OpenTopo, как и ожидалось. И ( 2 ) как побудить их динамически загружать любые недостающие фрагменты, если они действительно находятся в режиме онлайн.

Вот некоторые потенциально важные фрагменты из 1100+ строк кода в моем приложении MapsActivity. Java-файл:

// ===========================================================
//                      (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

1 Ответ

1 голос
/ 10 ноября 2019

Я решил эту проблему, сначала переместив только кэшированные тайлы из "/ storage / extSdCard / osmodroid / tile" в новый каталог "/ storage / extSdCard / osmXtra / tile", а затем в основном удалил кишки onCreate()и помещая его в отдельную функцию onCreateCommonCode(String tileSourceName_X), которая принимает имя TileSource в качестве параметра.

Эта функция теперь запускается один раз при запуске в onCreate() со стандартными OpenTopoMaps в качестве входных данных, но также (с соответствующим параметром TileSource) всякий раз, когда пользователь вводит команду переключения типа карты. Простой тест " if TileSourceThis затем TilePathTha t" выбирает правильный каталог для поиска файлов архива или кэша плиток.

Возможно, не самое элегантное решение, но, за исключением некоторых мелких странностей, например, как mLocationOverlay.enableFollowLocation() ведет себя после переключения карты, я доволен тем, как оно работает сейчас.

...