package org.osmdroid.samplefragments.tileproviders;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import org.mapsforge.map.android.graphics.AndroidGraphicFactory;
import org.mapsforge.map.android.rendertheme.AssetsRenderTheme;
import org.mapsforge.map.rendertheme.XmlRenderTheme;
import org.osmdroid.config.Configuration;
import org.osmdroid.mapsforge.MapsForgeTileProvider;
import org.osmdroid.mapsforge.MapsForgeTileSource;
import org.osmdroid.samplefragments.BaseSampleFragment;
import org.osmdroid.tileprovider.util.SimpleRegisterReceiver;
import org.osmdroid.tileprovider.util.StorageUtils;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
*
* An example of using MapsForge in osmdroid
* created on 1/12/2017.
*
* @author Alex O'Ree
*/
public class MapsforgeTileProviderSample extends BaseSampleFragment {
MapsForgeTileSource fromFiles=null;
MapsForgeTileProvider forge=null;
@Override
public String getSampleTitle() {
return "Mapsforge tiles";
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(false);
Log.d(TAG, "onCreate");
/**
* super important to configure some of the mapsforge settings first
*/
MapsForgeTileSource.createInstance(this.getActivity().getApplication());
/*
not sure how important these are....
MapFile.wayFilterEnabled = true;
MapFile.wayFilterDistance = 20;
MapWorkerPool.DEBUG_TIMING = true;
MapWorkerPool.NUMBER_OF_THREADS = MapWorkerPool.DEFAULT_NUMBER_OF_THREADS;
*/
}
@Override
public void addOverlays(){
super.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 .map files.
File[] maps = new File[mapfiles.size()];
maps = mapfiles.toArray(maps);
if (maps==null || maps.length==0){
//show a warning that no map files were found
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
getContext());
// set title
alertDialogBuilder.setTitle("No Mapsforge files found");
// set dialog message
alertDialogBuilder
.setMessage("In order to render map tiles, you'll need to either create or obtain mapsforge .map files. See https://github.com/mapsforge/mapsforge for more info. Store them in "
+ Configuration.getInstance().getOsmdroidBasePath().getAbsolutePath())
.setCancelable(false)
.setPositiveButton("Yes",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
else {
Toast.makeText(getContext(), "Loaded " + maps.length + " map files", Toast.LENGTH_LONG).show();
//this creates the forge provider and tile sources
//protip: when changing themes, you should also change the tile source name to prevent cached tiles
//null is ok here, uses the default rendering theme if it's not set
XmlRenderTheme theme = null;
try {
theme = new AssetsRenderTheme(getContext().getApplicationContext(), "renderthemes/", "rendertheme-v4.xml");
} catch (Exception ex) {
ex.printStackTrace();
}
fromFiles = MapsForgeTileSource.createFromFiles(maps, theme, "rendertheme-v4");
forge = new MapsForgeTileProvider(
new SimpleRegisterReceiver(getContext()),
fromFiles, null);
mMapView.setTileProvider(forge);
//now for a magic trick
//since we, the silly little osmdroid developers have no idea what will be on the
//user's device and what geographic area it is, this will attempt to center the map
//on whatever the map data provides
mMapView.getController().setZoom(fromFiles.getMinimumZoomLevel());
mMapView.zoomToBoundingBox(fromFiles.getBoundsOsmdroid(), true);
}
}
@Override
public boolean skipOnCiTests(){
//FIXME temporary fix until we iron out what is leaking on this
return false;
}
@Override
public void onDestroy(){
super.onDestroy();
if (fromFiles!=null)
fromFiles.dispose();
if (forge!=null)
forge.detach();
AndroidGraphicFactory.clearResourceMemoryCache();
}
/**
* simple function to scan for paths that match /something/osmdroid/*.map to find mapforge 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(".map"))
return true;
return false;
}
});
if (files != null) {
for (int i = 0; i < files.length; i++) {
ret.add(files[i]);
}
}
return ret;
}
}