osmdroid 加载gpkg格式的离线底图

博客介绍了一系列的osmdroid开源地图相关的内容,包括地图基本绘制,导航,缩放,加载各种离线地图等等。接下来继续介绍加载离线的gpkg格式地图。gpkg的全称是geopackage。这篇博客也是在之前的基础上添加的测试代码。

geopackage的github官网:https://github.com/ngageoint/geopackage-android

本博客的代码:http://download.csdn.net/detail/qq_16064871/9908233


android osmdroid 加载常用离线地图格式(开源的在线地图)
android osmdroid 加载离线地图map格式以及地图网格绘制

android 开源库osmdroid绘制点线面(比例尺,缩小放大,导航图标等)



1,加载的图片效果


osmdroid 加载gpkg格式的离线底图_第1张图片


默认的路径放在根目录的osmdroid文件夹下面。

实现需要使用的相关代码:

osmdroid 加载gpkg格式的离线底图_第2张图片

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 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 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 findMapFiles() {
        Set maps = new HashSet<>();
        List 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 scan(File f) {
        List 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

本博客的代码:http://download.csdn.net/detail/qq_16064871/9908233


android osmdroid 加载常用离线地图格式(开源的在线地图)
android osmdroid 加载离线地图map格式以及地图网格绘制

android 开源库osmdroid绘制点线面(比例尺,缩小放大,导航图标等)












你可能感兴趣的:(Android,开源框架或者开源库使用,Android,开源库学习)