我想展示一个使用OpenStreetMap的简单离线地图。但是我在网上找不到正确的工具来创建地图瓦片,并将其用于在Android上显示地图。我已经下载了不同的资源,但似乎不知道从哪里开始。我想使用JOSM集成OpenStreetMap的图像,但不确定是否可以在Android上使用。
我能使用Mapnik吗?谢谢您的帮助。
我想展示一个使用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
如果您的osm_map.xml布局看起来像这样:
<?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>
关于实际的地图瓦片,有一个非常酷的程序叫做Mobile Atlas Creator,它允许你为上面实现的离线Android地图生成必要的地图瓦片。
一旦你安装了该应用程序,并且你想创建一个新的地图集,你将被要求选择你的"期望的地图集格式"。当这个窗口弹出时,选择"Osmdroid zip"。
一旦所有内容加载完成,选择地图上的一个区域,选择你想要的瓦片缩放级别,然后点击左侧栏中的"添加选择"按钮,接着点击"创建地图集"。
哦,还有,根据来源的不同,你可能需要勾选"创建/调整地图瓦片"复选框以将瓦片导出为PNG格式 -- 有人知道是否可以在OSM中使用JPG格式吗?
一旦ZIP文件已经生成,我将其重命名为"Mapnik.zip"并将其移动到我Eclipse Android项目工作区中新创建的"tiles"文件夹中。为了使其正常工作,我还需要打开zip文件,将顶层文件夹从类似于"Google Earth"(取决于你使用的地图源)的名称改为"Mapnik",以便在我的Android应用程序中显示瓦片。
但是,为了将瓦片实际加载到你的手机上,你需要使用终端中的ADB工具。在ADB工具目录中,你需要运行类似于以下命令(每个命令换一行):
./adb shell rm -r /sdcard/osmdroid/
./adb shell mkdir /sdcard/osmdroi/
./adb push ~/path/to/your/mapnik.zip /sdcard/osmdroid
根据地图大小和手机内存总线的速度,这一步可能需要几分钟到一小时不等的时间才能完成。完成后,您的地图应该可以正常工作--希望如此!正如我提到的,这是我第一次使用OSM API,所以我对它并不是很了解,我只能评论我成功的经验。希望这可以帮助您入门! <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>
而且您可能还想将此添加到清单中,尽管这并不是必要的:
<supports-screens
android:anyDensity="true"
android:resizeable="false"
android:largeScreens="true"
android:normalScreens="true"
/>
在<uses-sdk ... />
部分之后添加以下内容。
此外,请确保导入以下两个JAR库:
osmdroid-android-3.0.3.jar // Or whatever version you're using...
和
slf4j-android-1.5.8.jar // Or whatever the latest version is...
如果没有这个最后的JAR(Java归档文件),我的代码会一直崩溃,直到我想起要加入它为止。
确保修改默认坐标,以便它们指向您实际拥有地图瓦片的位置,否则除了一个白色画布之外,您将看不到任何东西。
很抱歉我没有先在自己的端上运行该代码!
/mnt/sdcard/osmdroid/
目录中。<org.osmdroid.views.MapView
android:id="@+id/mapview"
android:layout_width="match_parent"
android:layout_height="match_parent"
tilesource="Mapnik"
/>
或者以编程方式创建MapView:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
mResourceProxy = new ResourceProxyImpl(inflater.getContext().getApplicationContext());
mMapView = new MapView(inflater.getContext(), 256, mResourceProxy);
return mMapView;
}
<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" />