OSMdroid 通过 ListView 加载多个离线 MBTIles

OSMdroid Loading Multiple Offline MBTIles Via ListView

我正在使用带有 Offline MBTiles 的 OSMdroid。我需要能够将用户从 ListView 添加到 select 多个 MBtiles。 ListView windows 很简单。但是,我需要帮助根据来自 ListView 的 selected 的 MBtiles 加载不同的 MBtiles。我的 MBTiles 是从 SDCard 加载的。

import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapController;
import org.osmdroid.views.MapView;

import android.app.Activity;
import android.os.Bundle;
import android.widget.RelativeLayout;

public class OfflineMapDemoActivity extends Activity {

    private String MapName;

    public String getMapName(){
        return MapName;
    }
    public void setMapName(String s){
        MapName = s;
    }

    // layout
    private RelativeLayout mapLayout;

    // MapView
    private MapView mapView;
    private MapController mapController;

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


        // init Layout
        setContentView(R.layout.main);
        this.mapLayout = (RelativeLayout) findViewById(R.id.mapLayout);

        // init Offline Map
        MapName="World.sqlitedb";
        this.mapView = new OfflineMapView(this, MapName);
        this.mapController = mapView.getController();

        // set Zoom Countrol
        this.mapView.setBuiltInZoomControls(true);
        // set Touch Control
        this.mapView.setMultiTouchControls(true);
        // zoom to 15
        this.mapController.setZoom(15);
        //add mapview
        this.mapLayout.addView(this.mapView, new RelativeLayout.LayoutParams(
                    android.view.ViewGroup.LayoutParams.FILL_PARENT,
                    android.view.ViewGroup.LayoutParams.FILL_PARENT));

        // scroll to 24082456, 120558472
        GeoPoint geoPoint = new GeoPoint(24082456, 120558472);
        this.mapController.setCenter(geoPoint);

    }
}

我创建了一个全局字符串变量来保存 MapName,其中 Listview class 可以通过 public 方法设置 setMapName().

顺便问一下,有没有一种方法可以自动读取 MBTiles 中心而不是像这样硬编码?

    // scroll to 24082456, 120558472
    GeoPoint geoPoint = new GeoPoint(24082456, 120558472);
    this.mapController.setCenter(geoPoint);

每次用户从 ListView 切换到 OSMdroid 地图以从列表视图加载 selected 离线 MBtiles 地图时,我应该使用哪种方法?上面的 Create 方法只在第一次加载时加载 MBTiles 地图一次?这是列表视图代码。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import android.app.ListActivity;
import android.os.Bundle;
import android.widget.SimpleAdapter;

public class MyTwoListItemsActivity extends ListActivity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ArrayList<Map<String, String>> list = buildData();
        String[] from = { "mapname", "selected" };
        int[] to = { android.R.id.text1, android.R.id.text2 };

        SimpleAdapter adapter = new SimpleAdapter(this, list,
            android.R.layout.simple_list_item_2, from, to);
        setListAdapter(adapter);
    }

    private ArrayList<Map<String, String>> buildData() {
        ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();
        list.add(putData("Map1", "Map1"));
        list.add(putData("Map2", "Map2"));
        list.add(putData("Map3", "Map3"));
        return list;
    } 

    private HashMap<String, String> putData(String name, String purpose) {
        HashMap<String, String> item = new HashMap<String, String>();
        item.put("mapname", mapname);
        item.put("selected", selected);
        return item;
    }

} 

如何集成 MyTwoListItemsActivityOfflineMapDemoActivity 之间的切换?

小世界,我只是做了你想要的。 osmdroid 需要 patch

假设应用了补丁,您需要制作自己的 MapTileProviderBase 扩展(请参阅 MapTileProviderBasic 作为参考)。您需要创建一个接受文件数组的构造函数,然后将其传递给 FileArchiveProvider。从这里开始,一旦用户选择了他们想要用于离线地图的文件,然后将该列表传递给自定义切片提供程序的实例,然后调用 MapView.setTileProvider。

另请注意,/sdcard/osmdroid 可以很好地用于此目的,但是如果您的设备在 kitkat 上并且文件在 /storage/extSdCard 中(例如三星设备),您还需要this

我最终会为我制作的一些适配器提交拉取请求,以简化此过程。

编辑:您的直接问题 "How do I integrate switching between MyTwoListItemsActivity and OfflineMapDemoActivity?" 更像是一个 android 关于如何将数据从一个 activity 传输到另一个的具体问题。意图和共享偏好是此应用程序最有可能的候选者。您可能需要考虑使用某种弹出窗口、菜单、操作栏、对话框等来翻转地图源。 MapView 的构造非常昂贵,防止重新初始化是个好主意。

编辑:这是我使用的代码。

警告 1) 您需要提前知道每个存档的 Tile Source 名称。 Zip 文件通常是地图源名称,例如 OpenStreetMaps。 Sqlite 有一个专栏,等等。如果您的磁贴没有显示,这是最可能的原因。

创建磁贴源。为简单起见,我选择命名文件以准确映射文件源名称。调整以满足您的需求。

public class FileBasedTileSource extends XYTileSource {

    public FileBasedTileSource(String aName, ResourceProxy.string aResourceId, int aZoomMinLevel, int aZoomMaxLevel, int aTileSizePixels, String aImageFilenameEnding, String[] aBaseUrl) {
        super(aName, aResourceId, aZoomMinLevel, aZoomMaxLevel, aTileSizePixels, aImageFilenameEnding, aBaseUrl);
    }

    public static ITileSource getSource(String name) {
        if (name.contains(".")) {
            name = name.substring(0, name.indexOf("."));
        }
        return new FileBasedTileSource(name,
            ResourceProxy.string.mapbox, 0, 18, 256, ".png", new String[]{
            "http://localhost"});
    }
}

然后你会用

创建它
ITileSource src=FileBasedTileSource.getSource("MyTileSource.gemf");

接下来您将需要以下内容 class,我将为其创建拉取请求。这是瓷砖供应商。

public class OfflineTileProvider extends MapTileProviderArray implements IMapTileProviderCallback {

    /**
     * Creates a {@link MapTileProviderBasic}.
     * throws with the source[] is null or empty
     */
    public OfflineTileProvider(final IRegisterReceiver pRegisterReceiver, File[] source
    )
        throws Exception {
        super(FileBasedTileSource.getSource(source[0].getName()), pRegisterReceiver);
        IArchiveFile[] f = new IArchiveFile[source.length];
        for (int i=0; i < source.length; i++)
            f[i]=ArchiveFileFactory.getArchiveFile(source[i]);

        mTileProviderList.add(new MapTileFileArchiveProvider(pRegisterReceiver, getTileSource(), f));

    }
}

然后创建实例如下:

OfflineTileProvider provider = new OfflineTileProvider(new SimpleRegisterReceiver(mContext), myUserSelectedFiles[]));
mMapView.setTileProvider(provider);
mMapView.setUseDataConnection(false);
mMapView.invalidate();

那应该创建一个实例并更新地图视图。

补充说明:IO 异常的可能性更大