Java 如何从OpenStreetMap离线创建地图分幅,并在Android上显示?

Java 如何从OpenStreetMap离线创建地图分幅,并在Android上显示?,java,android,map,openstreetmap,Java,Android,Map,Openstreetmap,我想要的是使用OpenStreetMap显示一个简单的离线地图。我在网上找不到合适的工具来创建地图分幅并用它在Android中显示地图。我下载了不同的资源,但似乎我不知道从哪里开始。我想使用JOSM集成OpenStreetMap中的图像,但我不知道是否可以在Android上使用它 我能用Mapnik吗?非常感谢您的帮助。我目前正在使用OpenStreetMap(OSM)API开发(我的第一个)Android应用程序,因此虽然我无法帮助您使用JSOM,但我可以尝试帮助您使用OSM部分: 假设您希望

我想要的是使用OpenStreetMap显示一个简单的离线地图。我在网上找不到合适的工具来创建地图分幅并用它在Android中显示地图。我下载了不同的资源,但似乎我不知道从哪里开始。我想使用JOSM集成OpenStreetMap中的图像,但我不知道是否可以在Android上使用它

我能用Mapnik吗?非常感谢您的帮助。

我目前正在使用OpenStreetMap(OSM)API开发(我的第一个)Android应用程序,因此虽然我无法帮助您使用JSOM,但我可以尝试帮助您使用OSM部分:

假设您希望在android应用程序中创建一个新的活动,该活动仅显示OSM地图,您可以从以下内容开始:

package example.stackoverflow.osmdroid;

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

import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;

public class YourMap extends Activity {
    // The MapView variable:
    private MapView m_mapView;

    // Default map zoom level:
    private int MAP_DEFAULT_ZOOM = 15;

    // Default map Latitude:
    private double MAP_DEFAULT_LATITUDE = 38.535350;

    // Default map Longitude:
    private double MAP_DEFAULT_LONGITUDE = -121.753807;

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

        // Specify the XML layout to use:
        setContentView(R.layout.osm_map);

        // Find the MapView controller in that layout:
        m_mapView = (MapView) findViewById(R.id.mapview);

        // Setup the mapView controller:
        m_mapView.setBuiltInZoomControls(true);
        m_mapView.setMultiTouchControls(true);
        m_mapView.setClickable(true);
        m_mapView.setUseDataConnection(false);
        m_mapView.getController().setZoom(MAP_DEFAULT_ZOOM);
        m_mapView.getController().setCenter(
            new GeoPoint(MAP_DEFAULT_LATITUDE, MAP_DEFAULT_LONGITUDE));
        m_mapView.setTileSource(TileSourceFactory.MAPNIK);
    } // end onCreate()
} // end class YourMap
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

        <org.osmdroid.views.MapView
            android:id="@+id/mapview"
            android:layout_width="match_parent" 
            android:layout_height="match_parent"
            android:enabled="true"      
            android:clickable="true"
        />  
</RelativeLayout>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
您的osm_map.xml布局可能如下所示:

package example.stackoverflow.osmdroid;

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

import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;

public class YourMap extends Activity {
    // The MapView variable:
    private MapView m_mapView;

    // Default map zoom level:
    private int MAP_DEFAULT_ZOOM = 15;

    // Default map Latitude:
    private double MAP_DEFAULT_LATITUDE = 38.535350;

    // Default map Longitude:
    private double MAP_DEFAULT_LONGITUDE = -121.753807;

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

        // Specify the XML layout to use:
        setContentView(R.layout.osm_map);

        // Find the MapView controller in that layout:
        m_mapView = (MapView) findViewById(R.id.mapview);

        // Setup the mapView controller:
        m_mapView.setBuiltInZoomControls(true);
        m_mapView.setMultiTouchControls(true);
        m_mapView.setClickable(true);
        m_mapView.setUseDataConnection(false);
        m_mapView.getController().setZoom(MAP_DEFAULT_ZOOM);
        m_mapView.getController().setCenter(
            new GeoPoint(MAP_DEFAULT_LATITUDE, MAP_DEFAULT_LONGITUDE));
        m_mapView.setTileSource(TileSourceFactory.MAPNIK);
    } // end onCreate()
} // end class YourMap
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

        <org.osmdroid.views.MapView
            android:id="@+id/mapview"
            android:layout_width="match_parent" 
            android:layout_height="match_parent"
            android:enabled="true"      
            android:clickable="true"
        />  
</RelativeLayout>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
根据地图的大小和手机内存总线的速度,最后一步可能需要几分钟到一小时才能完成。一旦完成,你的地图应该会工作——我希望

正如我所提到的,这是我第一次使用OSMAPI,所以我绝对不是OSMAPI方面的专家,我只能评论对我有用的东西

希望这将帮助您开始

编辑:

我没有机会实际运行我昨天编写的代码,所以我没有发现一些错误。我刚刚在Eclipse中创建了一个新项目,将我的代码转储到其中,修复了一些问题,并将其启动并运行。我所做的所有更改都反映在上面的代码中!我忘记了几个基本的导入语句,也忘记了向manifest.xml文件添加权限

my manifest.xml的最后几行现在如下所示:

package example.stackoverflow.osmdroid;

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

import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;

public class YourMap extends Activity {
    // The MapView variable:
    private MapView m_mapView;

    // Default map zoom level:
    private int MAP_DEFAULT_ZOOM = 15;

    // Default map Latitude:
    private double MAP_DEFAULT_LATITUDE = 38.535350;

    // Default map Longitude:
    private double MAP_DEFAULT_LONGITUDE = -121.753807;

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

        // Specify the XML layout to use:
        setContentView(R.layout.osm_map);

        // Find the MapView controller in that layout:
        m_mapView = (MapView) findViewById(R.id.mapview);

        // Setup the mapView controller:
        m_mapView.setBuiltInZoomControls(true);
        m_mapView.setMultiTouchControls(true);
        m_mapView.setClickable(true);
        m_mapView.setUseDataConnection(false);
        m_mapView.getController().setZoom(MAP_DEFAULT_ZOOM);
        m_mapView.getController().setCenter(
            new GeoPoint(MAP_DEFAULT_LATITUDE, MAP_DEFAULT_LONGITUDE));
        m_mapView.setTileSource(TileSourceFactory.MAPNIK);
    } // end onCreate()
} // end class YourMap
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

        <org.osmdroid.views.MapView
            android:id="@+id/mapview"
            android:layout_width="match_parent" 
            android:layout_height="match_parent"
            android:enabled="true"      
            android:clickable="true"
        />  
</RelativeLayout>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>

没有最后一个JAR,我的代码不断崩溃,直到我记得包含它

确保修改默认坐标,使其指向实际具有贴图分幅的位置,否则除了白色画布之外,您将看不到任何东西


对不起,没有先在我这边运行代码

以下是一个逐步解决方案:

简言之:

1-必须使用下载地图分幅。我已经解释了步骤

2-将生成的zip文件移动到设备上的
/mnt/sdcard/osmdroid/

3-在项目中添加和生成路径

4-添加地图视图:您可以将地图视图添加到xml布局中

<org.osmdroid.views.MapView
    android:id="@+id/mapview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tilesource="Mapnik"
    />
不要忘记将这些权限添加到清单中:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

这是一个好主意。 希望有帮助;)

重要

正如@Scai所提到的:最近开放的街道地图发布了一些问题:

此工具会导致OSM磁贴服务器的流量过大,并且可能会被阻止。 请不要用它


或者,为了映射分幅,您还可以为脱机地图使用矢量数据,例如mapsforge或Mapbox Android SDK。有关和的更多信息,请咨询OSM wiki。

是的,您可以使用Mapnik。但这个问题在这里是离题的。你应该继续问。我不认为这是离题的,但是你在help.openstreetmap.org可能更喜欢OSM专家的评论。你还可以在这个主题中添加其他想法吗?我可以显示地图,但使用internet“”。嗨,蒂姆先生。你真是太棒了。感谢您分享您的代码和想法。我真的很兴奋能尝试一下。你的程序非常清楚,信息也非常丰富。先生,请更新您的状态。谢谢。我有以下错误:[2011-10-05 22:22:58-OsmNavigator]Dx 1错误;中止[2011-10-05 22:22:58-OsmNavigator]到Dalvik格式的转换失败,错误为1[2011-10-05 22:26:07-YourMap]Dx意外的顶级异常:java.lang.IllegalArgumentException:已添加:Lorg/osmdroid/tileprovider/tilesource/bing/BingMapTileSource;[2011-10-05 22:26:07-YourMap]Dx在com.android.Dx.dex.file.classdefsection.add(classdefsection.java:123)[2011-10-05 22:26:07-YourMap]Dx在com.android.Dx.dex.file.DexFile.add(DexFile.java:143)Hi rahstame,根据您发布的输出判断,您可能试图包括两个共享一些相同包和类的JAR;换句话说,所包含的一些JAR文件之间存在冲突。请看一下本文中的建议。当我右键单击项目>属性>java构建路径>库时。然后我发现我使用了不同的库osmdroid-android-3.0.1.jar和osmdroid-android-3.0.5.jar。我删除了3.0.5.jar。然后我就可以编译了,但是当我转到emulator屏幕时,它会显示“抱歉,应用程序意外运行”。注意,MOBAC对OSM磁贴服务器非常不利,您可能会被阻止。有关更多信息,请参阅。