首先在android studio 项目中引入osmdroid:
implementation 'org.osmdroid:osmdroid-android:6.1.0@aar'
在界面中加入控件
<RelativeLayout
android:id="@+id/contentPanel"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.osmdroid.views.MapView
android:id="@+id/myOSMmapview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:enabled="true">
</org.osmdroid.views.MapView>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:orientation="vertical">
<Button
android:id="@+id/btn_dw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="定位" />
<Button
android:id="@+id/btn_sjgz"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="视角跟踪" />
<Button
android:id="@+id/btn_gjhz"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="轨迹绘制" />
</LinearLayout>
</RelativeLayout>
天地图影像图及标注加载
//region 天地图
//影像图
String wz = "tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&tk=[key]";
//影响图标注
String wzbz="tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&style=default&TILEMATRIXSET=w&FORMAT=tiles&tk=[key]";
//影像地图 _W是墨卡托投影 _c是国家2000的坐标系
OnlineTileSourceBase tianDiTuImgTileSource = new XYTileSource("Tian Di Tu Img", 1, 18, 256, "",
new String[]{"https://t0." + wz,
"https://t1." + wz,
"https://t2." + wz,
"https://t3." + wz,
"https://t4." + wz,
"https://t5." + wz,
"https://t6." + wz,
"https://t7." + wz
}) {
@Override
public String getTileURLString(final long pMapTileIndex) {
// Log.d("url", getBaseUrl() + "&TILEROW=" + MapTileIndex.getX(pMapTileIndex) + "&TILECOL=" + MapTileIndex.getY(pMapTileIndex)
// + "&TILEMATRIX=" + MapTileIndex.getZoom(pMapTileIndex));
return getBaseUrl() + "&TILEROW=" + MapTileIndex.getY(pMapTileIndex) + "&TILECOL=" + MapTileIndex.getX(pMapTileIndex)
+ "&TILEMATRIX=" + MapTileIndex.getZoom(pMapTileIndex);
}
};
//影像标注 _W是墨卡托投影 _c是国家2000的坐标系
OnlineTileSourceBase tianDiTuCiaTileSource = new XYTileSource("TianDiTuCia", 1, 18, 768, ".png",
new String[]{"https://t0." + wzbz,
"https://t1." + wzbz,
"https://t2." + wzbz,
"https://t3." + wzbz,
"https://t4." + wzbz,
"https://t5." + wzbz,
"https://t6." + wzbz,
"https://t7." + wzbz
}) {
@Override
public String getTileURLString(final long pMapTileIndex) {
// Log.d("url", getBaseUrl() + "&TILEROW=" + MapTileIndex.getY(pMapTileIndex) + "&TILECOL=" + MapTileIndex.getX(pMapTileIndex)
// + "&TILEMATRIX=" + MapTileIndex.getZoom(pMapTileIndex));
return getBaseUrl() + "&TILEROW=" + MapTileIndex.getY(pMapTileIndex) + "&TILECOL=" + MapTileIndex.getX(pMapTileIndex)
+ "&TILEMATRIX=" + MapTileIndex.getZoom(pMapTileIndex);
}
};
//endregion
//加载天地图
mMapView.setTileSource(tianDiTuImgTileSource);
TilesOverlay tilesOverlay = new TilesOverlay(new MapTileProviderBasic(this, tianDiTuCiaTileSource), this);
mMapView.getOverlayManager().add(tilesOverlay);
加载本地地图
//加载本地地图
public void mapViewOtherData(MapView mapView) {
String strFilepath = Environment.getExternalStorageDirectory().getPath() + "/Download/map.zip";
File exitFile = new File(strFilepath);
String fileName = "map.zip";
if (!exitFile.exists()) {
mapView.setTileSource(TileSourceFactory.MAPNIK);
} else {
fileName = fileName.substring(fileName.lastIndexOf(".") + 1);
if (fileName.length() == 0)
return;
if (ArchiveFileFactory.isFileExtensionRegistered(fileName)) {
try {
OfflineTileProvider tileProvider = new OfflineTileProvider((IRegisterReceiver) new SimpleRegisterReceiver(this), new File[]{exitFile});
mapView.setTileProvider(tileProvider);
String source = "";
IArchiveFile[] archives = tileProvider.getArchives();
if (archives.length > 0) {
Set<String> tileSources = archives[0].getTileSources();
if (!tileSources.isEmpty()) {
source = tileSources.iterator().next();
mapView.setTileSource(FileBasedTileSource.getSource(source));
} else {
mapView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
}
} else
mapView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
//Toast.makeText(this, "Using " + exitFile.getAbsolutePath() + " " + source, Toast.LENGTH_LONG).show();
mapView.invalidate();
return;
} catch (Exception ex) {
ex.printStackTrace();
}
Toast.makeText(this, " did not have any files I can open! Try using MOBAC", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, " dir not found!", Toast.LENGTH_LONG).show();
}
}
}
添加标记、横线
//添加标记
final ArrayList<OverlayItem> items = new ArrayList<OverlayItem>();
items.add(new OverlayItem("滨江道", "滨江道商业街", new GeoPoint(39.124418, 117.204228)));
items.add(new OverlayItem("小白楼", "小白楼商业街", new GeoPoint(39.11013301, 117.20576944)));
addCurrentMarker(items);
GeoPoint startPoint = new GeoPoint(39.114418, 117.204228); //white house
//points.add(startPoint);
Marker startMarker = new Marker(mMapView);
startMarker.setPosition(startPoint);
startMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
Resources resources = this.getResources();
Drawable drawable = resources.getDrawable(R.drawable.ab);
startMarker.setIcon(drawable);
startMarker.setTitle("White House");
startMarker.setSnippet("The White House is the official residence and principal workplace of the President of the United States.");
startMarker.setSubDescription("1600 Pennsylvania Ave NW, Washington, DC 20500");
startMarker.setOnMarkerClickListener(new Marker.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker, MapView mapView) {
marker.showInfoWindow();
return true;
}
});
mMapView.getOverlays().add(startMarker);
//加载横线
Polyline pathOverlay = new Polyline(mMapView);
pathOverlay.setColor(Color.BLUE);
pathOverlay.setWidth(10);
List<GeoPoint> geos = new ArrayList<GeoPoint>();
geos.add(new GeoPoint(39.120418, 117.204228));
//geos.add(new GeoPoint(39.11613301, 117.20576944));
geos.add(new GeoPoint(39.114418, 117.200228));
pathOverlay.setTitle("线条");
pathOverlay.setSnippet("线条片段");
pathOverlay.setSubDescription("线条子描述");
pathOverlay.setPoints(geos);
//pathOverlay.setEnabled(false);//是否可见
pathOverlay.setEnabled(false);
pathOverlay.setVisible(true);
mMapView.getOverlays().add(pathOverlay);
//添加相关的marker
private void addCurrentMarker(ArrayList<OverlayItem> items) {
ItemizedIconOverlay mMyLocationOverlay = new ItemizedIconOverlay<>(items,
new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
@Override
public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
Toast.makeText(getBaseContext(),
"第" + (index + 1) + "个节点\r\n" + item.getTitle() + "\r\n" + item.getSnippet(),
Toast.LENGTH_LONG).show();
return true; // We 'handled' this event.返回true就表示这个点击事件被消费掉了
}
@Override
public boolean onItemLongPress(final int index, final OverlayItem item) {
Toast.makeText(getBaseContext(),
"第" + (index + 1) + "个节点\r\n" + item.getTitle() + "\r\n" + item.getSnippet(),
Toast.LENGTH_LONG).show();
return false;//false表示这个事件可以继续向下传递
}
}, getApplicationContext());
mMapView.getOverlays().add(mMyLocationOverlay);
}
其他设置
//让瓦片适应不同像素密度:默认地图显示的字体小,图片像素高,可设置以下代码,使地图适应不同像素密度,更美观
mMapView.setTilesScaledToDpi(true);
//添加指南针
CompassOverlay mCompassOverlay = new CompassOverlay(MainActivity.this, new InternalCompassOrientationProvider(MainActivity.this), mMapView);
mMapView.getOverlays().add(mCompassOverlay);
mCompassOverlay.enableCompass();
//添加比例尺
ScaleBarOverlay mScaleBarOverlay = new ScaleBarOverlay(mMapView);
mMapView.getOverlays().add(mScaleBarOverlay);
//添加上面代码后,比例尺显示在左上角,而且不美观,可以继续添加下面代码,使比例尺显示在左下角
mScaleBarOverlay.setAlignBottom(true);
mScaleBarOverlay.setLineWidth(1 * (getResources().getDisplayMetrics()).density);
mScaleBarOverlay.setMaxLength(0.85f);
//(1)、设置缩放界别
mMapController.setZoom(15);//设置缩放级别
//(2)、设置缩放按钮可见
mMapView.setBuiltInZoomControls(true);//设置缩放按钮可见
//(3)、设置多指触控可用
mMapView.setMultiTouchControls(true);//设置多指触控可用
//(4)、关闭硬件加速
//mMapView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);//关闭硬件加速(绘制轨迹时需要)
//(5)、地图可旋转
// RotationGestureOverlay mRotationGestureOverlay = new RotationGestureOverlay(this, mMapView);
// mRotationGestureOverlay.setEnabled(true);
// mMapView.getOverlays().add(mRotationGestureOverlay);
设置地图中心
private void setCenter(MapController mMapController) {
//设置地图中心
GeoPoint geopoint = new GeoPoint(location.getLatitude(), location.getLongitude());
mMapController.setCenter(geopoint);//设置地图中心
}
GPS定位、跟踪、轨迹绘制
//region GPS
LocationManager locationManager;
String provider;
private String initlocationGps() throws Exception {
String result = "";
//此处的判定是主要问题,API23之后需要先判断之后才能调用locationManager中的方法
// 包括这里的getLastKnewnLocation方法和requestLocationUpdates方法
//if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
//获取定位服务
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
//获取当前可用的位置控制器
List<String> list = locationManager.getProviders(true);
if (list.contains(LocationManager.NETWORK_PROVIDER)) {
//是否为网络位置控制器
provider = LocationManager.NETWORK_PROVIDER;
} else if (list.contains(LocationManager.GPS_PROVIDER)) {
//是否为GPS位置控制器
provider = LocationManager.GPS_PROVIDER;
} else {
throw new Exception("请检查网络或GPS是否打开");
}
// provider = LocationManager.NETWORK_PROVIDER;
location = locationManager.getLastKnownLocation(provider);
if (location != null) {
//获取当前位置,这里只用到了经纬度
result = location.getLatitude() + ","
+ location.getLongitude();
}
//绑定定位事件,监听位置是否改变
// 第一个参数为控制器类型第二个参数为监听位置变化的时间间隔(单位:毫秒)
// 第三个参数为位置变化的间隔(单位:米)第四个参数为位置监听器
locationManager.requestLocationUpdates(provider, 2000, 2, locationListener);
}
return result;
}
public LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
try {
GeoPoint geopoint = new GeoPoint(location.getLatitude(), location.getLongitude());
if (is_sjgz) {
//设置地图中心 //地图移动到某个点
mMapView.getController().animateTo(geopoint);
}
if (is_gjhz) {
pathOverlay.addPoint(geopoint);
}
} catch (Exception ex) {
Toast.makeText(MainActivity.this, "定位更新", Toast.LENGTH_LONG).show();
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
};
//endregion