博客介绍了一系列的osmdroid开源地图相关的内容,包括地图基本绘制,导航,缩放,加载各种离线地图等等。接下来继续介绍加载离线的gpkg格式地图。gpkg的全称是geopackage。这篇博客也是在之前的基础上添加的测试代码。
geopackage的github官网:https://github.com/ngageoint/geopackage-android
本博客的代码:http://download.csdn.net/detail/qq_16064871/9908233
1,加载的图片效果
默认的路径放在根目录的osmdroid文件夹下面。
实现需要使用的相关代码:
2,调用方式
package com.osmdroid.sample;
import android.content.Context;
import android.content.DialogInterface;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.osmdroid.sample.geopakeage.CustomGeopackageUntil;
import com.osmdroid.sample.geopakeage.GeoPackageMapTileModuleProvider;
import com.osmdroid.sample.geopakeage.GeoPackageProvider;
import com.osmdroid.sample.geopakeage.GeopackageSample;
import com.osmdroid.sample.overlay.SampleSimpleFastPointOverlay;
import org.osmdroid.api.IGeoPoint;
import org.osmdroid.api.IMapView;
import org.osmdroid.config.Configuration;
import org.osmdroid.events.MapListener;
import org.osmdroid.events.ScrollEvent;
import org.osmdroid.events.ZoomEvent;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.tileprovider.tilesource.XYTileSource;
import org.osmdroid.tileprovider.util.StorageUtils;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.ScaleBarOverlay;
import org.osmdroid.views.overlay.compass.CompassOverlay;
import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider;
import org.osmdroid.views.overlay.gestures.RotationGestureOverlay;
import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider;
import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay;
import java.io.File;
import java.io.FileFilter;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 测试加载geopackage
*/
public class GeopackageMapTestActivity extends AppCompatActivity implements View.OnClickListener ,LocationListener{
private MapView mapView;
//地图旋转
private RotationGestureOverlay mRotationGestureOverlay;
//比例尺
private ScaleBarOverlay mScaleBarOverlay;
//指南针方向
private CompassOverlay mCompassOverlay = null;
//设置导航图标的位置
private MyLocationNewOverlay mLocationOverlay;
private LocationManager lm;
private Location currentLocation = null;
private com.osmdroid.sample.geopakeage.GeopackageSample GeopackageSample = null;
TextView textViewCurrentLocation;
GeoPackageProvider.TileSourceBounds tileSourceBounds;
XYTileSource currentSource = null;
GeoPackageProvider geoPackageProvider=null;
public static final DecimalFormat df = new DecimalFormat("#.000000");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_basic_test_geopackage);
initView();
}
private void initView() {
findViewById(R.id.button1).setOnClickListener(this);
findViewById(R.id.button2).setOnClickListener(this);
textViewCurrentLocation = (TextView) findViewById(R.id.textViewCurrentLocation);
mapView = (MapView) findViewById(R.id.mymapview);
mapView.setDrawingCacheEnabled(true);
mapView.setMaxZoomLevel(20);
mapView.setMinZoomLevel(6);
mapView.getController().setZoom(12);
mapView.setTileSource(TileSourceFactory.MAPNIK);
mapView.setUseDataConnection(true);
mapView.setMultiTouchControls(true);// 触控放大缩小
//是否显示地图数据源
mapView.getOverlayManager().getTilesOverlay().setEnabled(true);
//地图自由旋转
mRotationGestureOverlay = new RotationGestureOverlay(mapView);
mRotationGestureOverlay.setEnabled(true);
mapView.getOverlays().add(this.mRotationGestureOverlay);
//比例尺配置
final DisplayMetrics dm = getResources().getDisplayMetrics();
mScaleBarOverlay = new ScaleBarOverlay(mapView);
mScaleBarOverlay.setCentred(true);
mScaleBarOverlay.setAlignBottom(true); //底部显示
mScaleBarOverlay.setScaleBarOffset(dm.widthPixels / 5, 80);
mapView.getOverlays().add(this.mScaleBarOverlay);
//指南针方向
mCompassOverlay = new CompassOverlay(this, new InternalCompassOrientationProvider(this),
mapView);
mCompassOverlay.enableCompass();
mapView.getOverlays().add(this.mCompassOverlay);
//设置导航图标
this.mLocationOverlay = new MyLocationNewOverlay(new GpsMyLocationProvider(this),
mapView);
mapView.getOverlays().add(this.mLocationOverlay);
mLocationOverlay.enableMyLocation(); //设置可视
}
@Override
public void onLocationChanged(Location location) {
currentLocation=location;
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
if (currentLocation != null) {
GeoPoint myPosition = new GeoPoint(currentLocation.getLatitude(), currentLocation.getLongitude());
mapView.getController().animateTo(myPosition);
}
break;
case R.id.button2:
// TODO: 2017/6/19 Fragment形式的图层
// FragmentManager fm = this.getSupportFragmentManager();
// if (fm.findFragmentByTag("GeopackageSample") == null) {
// mapView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
// GeopackageSample = new GeopackageSample();
// fm.beginTransaction().add(R.id.samples_container, GeopackageSample, "SampleGridlines").commit();
// }
addOverlays();
break;
}
}
public void addOverlays() {
//first let's up our map source, mapsforge needs you to explicitly specify which map files to load
//this bit does some basic file system scanning
Set<File> mapfiles = findMapFiles();
//do a simple scan of local storage for .gpkg files.
File[] maps = new File[mapfiles.size()];
maps = mapfiles.toArray(maps);
if (maps.length == 0) {
//show a warning that no map files were found
android.app.AlertDialog.Builder alertDialogBuilder = new android.app.AlertDialog.Builder(this);
// set title
alertDialogBuilder.setTitle("No Geopackage files found");
// set dialog message
alertDialogBuilder
.setMessage("In order to render map tiles, you'll need to either create or obtain .gpkg files. See http://www.geopackage.org/ for more info. Place them in "
+ Configuration.getInstance().getOsmdroidBasePath().getAbsolutePath())
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
// create alert dialog
android.app.AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
} else {
Toast.makeText(this, "Loaded " + maps.length + " map files", Toast.LENGTH_LONG).show();
geoPackageProvider = new GeoPackageProvider(maps, this);
mapView.setTileProvider(geoPackageProvider);
List<GeoPackageMapTileModuleProvider.Container> tileSources = geoPackageProvider.geoPackageMapTileModuleProvider().getTileSources();
//here we're keeping track of the current tile source so we can reference it later, primarly for
//displaying the bounds of the tile set
boolean sourceSet = false;
for (int i = 0; i < tileSources.size(); i++) {
//this is a list of geopackages, since we only support tile tables, pick the first one of those
//ideally this should populate a spinner so that the user can select whatever tile source they want
if (tileSources.get(i) != null && !tileSources.get(i).tiles.isEmpty()) {
currentSource = (XYTileSource) geoPackageProvider.getTileSource(tileSources.get(i).database,
tileSources.get(0).tiles.get(i)
);
mapView.setTileSource(currentSource);
sourceSet = true;
break;
}
}
if (!sourceSet) {
Toast.makeText(this, "No tile source is available, get your geopackages for 'tiles' tables", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Tile source set to " + mapView.getTileProvider().getTileSource().name(), Toast.LENGTH_LONG).show();
//this part will attempt to zoom to bounds of the selected tile source
tileSourceBounds = geoPackageProvider.getTileSourceBounds();
if (tileSourceBounds != null) {
mapView.zoomToBoundingBox(tileSourceBounds.bounds, true);
mapView.getController().setZoom(tileSourceBounds.minzoom);
}
}
}
mapView.setMapListener(new MapListener() {
@Override
public boolean onScroll(ScrollEvent event) {
Log.i(IMapView.LOGTAG, System.currentTimeMillis() + " onScroll " + event.getX() + "," + event.getY());
updateInfo();
return true;
}
@Override
public boolean onZoom(ZoomEvent event) {
Log.i(IMapView.LOGTAG, System.currentTimeMillis() + " onZoom " + event.getZoomLevel());
updateInfo();
return true;
}
});
updateInfo();
}
private void updateInfo() {
StringBuilder sb = new StringBuilder();
IGeoPoint mapCenter = mapView.getMapCenter();
sb.append(df.format(mapCenter.getLatitude()) + "," +
df.format(mapCenter.getLongitude())
+ ",zoom=" + mapView.getZoomLevel());
if (currentSource != null) {
sb.append("\n");
sb.append(currentSource.name() + "," + currentSource.getBaseUrl());
}
if (tileSourceBounds != null) {
sb.append("\n");
sb.append(" minzoom=" + tileSourceBounds.minzoom);
sb.append(" maxzoom=" + tileSourceBounds.maxzoom);
sb.append(" bounds=" + df.format(tileSourceBounds.bounds.getLatNorth())
+ "," + df.format(tileSourceBounds.bounds.getLonEast()) + "," +
df.format(tileSourceBounds.bounds.getLatSouth()) + "," +
df.format(tileSourceBounds.bounds.getLonWest()));
}
textViewCurrentLocation.setText(sb.toString());
}
/**
* simple function to scan for paths that match /something/osmdroid/*.map to find database files
*
* @return
*/
protected static Set<File> findMapFiles() {
Set<File> maps = new HashSet<>();
List<StorageUtils.StorageInfo> storageList = StorageUtils.getStorageList();
for (int i = 0; i < storageList.size(); i++) {
File f = new File(storageList.get(i).path + File.separator + "osmdroid" + File.separator);
if (f.exists()) {
maps.addAll(scan(f));
}
}
return maps;
}
static private Collection<? extends File> scan(File f) {
List<File> ret = new ArrayList<>();
File[] files = f.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if (pathname.getName().toLowerCase().endsWith(".gpkg"))
return true;
return false;
}
});
if (files != null) {
for (int i = 0; i < files.length; i++) {
ret.add(files[i]);
}
}
return ret;
}
@Override
public void onDestroy(){
super.onDestroy();
this.currentSource=null;
if (geoPackageProvider!=null)
geoPackageProvider.detach();
}
@Override
public void onPause() {
super.onPause();
try{
lm.removeUpdates(this);
}catch (Exception ex){}
mCompassOverlay.disableCompass();
mLocationOverlay.disableFollowLocation();
mLocationOverlay.disableMyLocation();
mScaleBarOverlay.enableScaleBar();
}
@Override
public void onResume(){
super.onResume();
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
try{
//this fails on AVD 19s, even with the appcompat check, says no provided named gps is available
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,0l,0f,this);
}catch (Exception ex){}
try{
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0l,0f,this);
}catch (Exception ex){}
mLocationOverlay.enableFollowLocation();
mLocationOverlay.enableMyLocation();
mScaleBarOverlay.disableScaleBar();
}
}
第二种调用方式,使用Fragment形式的图层
// TODO: 2017/6/19 Fragment形式的图层
FragmentManager fm = this.getSupportFragmentManager();
if (fm.findFragmentByTag("GeopackageSample") == null) {
mapView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
GeopackageSample = new GeopackageSample();
fm.beginTransaction().add(R.id.samples_container, GeopackageSample, "SampleGridlines").commit();
}
addOverlays();
3,注意事项
如果编译出现google_play_services_version找不到,记得把资源文件夹下面values文件夹下面values拷贝进去。
这里加载是gpkg地图格式的瓦片数据,就是有生成位图那种。如果是gpkg数据库存储的数据库表,没有转化成titles是加载不出来的。
geopackage的github官网:https://github.com/ngageoint/geopackage-android
作者:qq_16064871 发表于2017/7/24 19:45:58 原文链接
阅读:31 评论:0 查看评论