package org.osmdroid.config;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.preference.PreferenceManager;
import android.util.Log;
import org.osmdroid.tileprovider.modules.SqlTileWriter;
import org.osmdroid.tileprovider.util.StorageUtils;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Locale;
import static org.osmdroid.tileprovider.constants.OpenStreetMapTileProviderConstants.HTTP_EXPIRES_HEADER_FORMAT;
/**
* Default configuration provider for osmdroid
* <a href="https://github.com/osmdroid/osmdroid/issues/481">Issue 481</a>
* Created on 11/29/2016.
* @author Alex O'Ree
* @see IConfigurationProvider
* @see Configuration
*/
public class DefaultConfigurationProvider implements IConfigurationProvider {
/*public final String[] preferenceKeys = new String[]{
"osmdroid.basePath",
"osmdroid.cachePath",
"osmdroid.DebugMode",
"osmdroid.DebugDownloading",
"osmdroid.DebugMapView",
"osmdroid.DebugTileProvider",
"osmdroid.HardwareAcceleration",
"osmdroid.userAgentValue",
"osmdroid.gpsWaitTime",
"osmdroid.tileDownloadThreads",
"osmdroid.tileFileSystemThreads",
"osmdroid.tileDownloadMaxQueueSize",
"osmdroid.tileFileSystemMaxQueueSize"
};*/
//<editor-fold>
protected long gpsWaitTime =20000;
protected boolean debugMode= false;
protected boolean debugMapView = false;
protected boolean debugTileProviders = false;
protected boolean debugMapTileDownloader=false;
protected boolean isMapViewHardwareAccelerated=false;
protected String userAgentValue="osmdroid";
protected String userAgentHttpHeader = "User-Agent";
protected short cacheMapTileCount = 9;
protected short tileDownloadThreads = 2;
protected short tileFileSystemThreads = 8;
protected short tileDownloadMaxQueueSize = 40;
protected short tileFileSystemMaxQueueSize = 40;
protected long tileFileSystemCacheMaxBytes = 600L * 1024 * 1024;
protected long tileFileSystemCacheTrimBytes = 500L * 1024 * 1024;
protected SimpleDateFormat httpHeaderDateTimeFormat = new SimpleDateFormat(HTTP_EXPIRES_HEADER_FORMAT, Locale.US);
protected File osmdroidBasePath;
protected File osmdroidTileCache;
protected long expirationAdder = 0;
protected Long expirationOverride=null;
public DefaultConfigurationProvider(){
try {
//StorageUtils.getStorage() can return null when android studio is "previewing" a layout
osmdroidBasePath = new File(StorageUtils.getStorage().getAbsolutePath(), "osmdroid");
osmdroidTileCache = new File(getOsmdroidBasePath(), "tiles");
osmdroidBasePath.mkdirs();
osmdroidTileCache.mkdirs();
}catch (Exception ex){
//IO/permissions issue
//trap for android studio layout editor and some for certain devices
//see https://github.com/osmdroid/osmdroid/issues/508
}
}
/**
* default is 20 seconds
* @return time in ms
*/
@Override
public long getGpsWaitTime() {
return gpsWaitTime;
}
@Override
public void setGpsWaitTime(long gpsWaitTime) {
this.gpsWaitTime = gpsWaitTime;
}
@Override
public boolean isDebugMode() {
return debugMode;
}
@Override
public void setDebugMode(boolean debugMode) {
this.debugMode = debugMode;
}
@Override
public boolean isDebugMapView() {
return debugMapView;
}
@Override
public void setDebugMapView(boolean debugMapView) {
this.debugMapView = debugMapView;
}
@Override
public boolean isDebugTileProviders() {
return debugTileProviders;
}
@Override
public void setDebugTileProviders(boolean debugTileProviders) {
this.debugTileProviders = debugTileProviders;
}
@Override
public boolean isDebugMapTileDownloader() {
return debugMapTileDownloader;
}
@Override
public void setDebugMapTileDownloader(boolean debugMapTileDownloader) {
this.debugMapTileDownloader = debugMapTileDownloader;
}
@Override
public boolean isMapViewHardwareAccelerated() {
return isMapViewHardwareAccelerated;
}
@Override
public void setMapViewHardwareAccelerated(boolean mapViewHardwareAccelerated) {
isMapViewHardwareAccelerated = mapViewHardwareAccelerated;
}
@Override
public String getUserAgentValue() {
return userAgentValue;
}
@Override
public void setUserAgentValue(String userAgentValue) {
this.userAgentValue = userAgentValue;
}
@Override
public short getCacheMapTileCount() {
return cacheMapTileCount;
}
@Override
public void setCacheMapTileCount(short cacheMapTileCount) {
this.cacheMapTileCount = cacheMapTileCount;
}
@Override
public short getTileDownloadThreads() {
return tileDownloadThreads;
}
@Override
public void setTileDownloadThreads(short tileDownloadThreads) {
this.tileDownloadThreads = tileDownloadThreads;
}
@Override
public short getTileFileSystemThreads() {
return tileFileSystemThreads;
}
@Override
public void setTileFileSystemThreads(short tileFileSystemThreads) {
this.tileFileSystemThreads = tileFileSystemThreads;
}
@Override
public short getTileDownloadMaxQueueSize() {
return tileDownloadMaxQueueSize;
}
@Override
public void setTileDownloadMaxQueueSize(short tileDownloadMaxQueueSize) {
this.tileDownloadMaxQueueSize = tileDownloadMaxQueueSize;
}
@Override
public short getTileFileSystemMaxQueueSize() {
return tileFileSystemMaxQueueSize;
}
@Override
public void setTileFileSystemMaxQueueSize(short tileFileSystemMaxQueueSize) {
this.tileFileSystemMaxQueueSize = tileFileSystemMaxQueueSize;
}
@Override
public long getTileFileSystemCacheMaxBytes() {
return tileFileSystemCacheMaxBytes;
}
@Override
public void setTileFileSystemCacheMaxBytes(long tileFileSystemCacheMaxBytes) {
this.tileFileSystemCacheMaxBytes = tileFileSystemCacheMaxBytes;
}
@Override
public long getTileFileSystemCacheTrimBytes() {
return tileFileSystemCacheTrimBytes;
}
@Override
public void setTileFileSystemCacheTrimBytes(long tileFileSystemCacheTrimBytes) {
this.tileFileSystemCacheTrimBytes = tileFileSystemCacheTrimBytes;
}
@Override
public SimpleDateFormat getHttpHeaderDateTimeFormat() {
return httpHeaderDateTimeFormat;
}
@Override
public void setHttpHeaderDateTimeFormat(SimpleDateFormat httpHeaderDateTimeFormat) {
this.httpHeaderDateTimeFormat = httpHeaderDateTimeFormat;
}
@Override
public File getOsmdroidBasePath() {
return osmdroidBasePath;
}
@Override
public void setOsmdroidBasePath(File osmdroidBasePath) {
this.osmdroidBasePath = osmdroidBasePath;
}
@Override
public File getOsmdroidTileCache() {
return osmdroidTileCache;
}
@Override
public void setOsmdroidTileCache(File osmdroidTileCache) {
this.osmdroidTileCache = osmdroidTileCache;
}
@Override
public String getUserAgentHttpHeader() {
return userAgentHttpHeader;
}
@Override
public void setUserAgentHttpHeader(String userAgentHttpHeader) {
this.userAgentHttpHeader = userAgentHttpHeader;
}
//</editor-fold>
@Override
public void load(Context ctx, SharedPreferences prefs) {
//cache management starts here
//check to see if the shared preferences is set for the tile cache
if (!prefs.contains("osmdroid.basePath")){
//this is the first time startup. run the discovery bit
File discoveredBestPath = getOsmdroidBasePath();
File discoveredCachPath = getOsmdroidTileCache();
if (!discoveredBestPath.exists() || !StorageUtils.isWritable(discoveredBestPath)) {
//this should always be writable...
discoveredCachPath=discoveredBestPath=new File("/data/data/" + ctx.getPackageName() + "/osmdroid/");
discoveredCachPath.mkdirs();
}
SharedPreferences.Editor edit = prefs.edit();
edit.putString("osmdroid.basePath",discoveredBestPath.getAbsolutePath());
edit.putString("osmdroid.cachePath",discoveredCachPath.getAbsolutePath());
edit.commit();
setOsmdroidBasePath(discoveredBestPath);
setOsmdroidTileCache(discoveredCachPath);
setUserAgentValue(ctx.getPackageName());
save(ctx,prefs);
} else {
//normal startup, load user preferences and populate the config object
setOsmdroidBasePath(new File(prefs.getString("osmdroid.basePath", getOsmdroidBasePath().getAbsolutePath())));
setOsmdroidTileCache(new File(prefs.getString("osmdroid.cachePath", getOsmdroidTileCache().getAbsolutePath())));
setDebugMode(prefs.getBoolean("osmdroid.DebugMode",false));
setDebugMapTileDownloader(prefs.getBoolean("osmdroid.DebugDownloading", false));
setDebugMapView(prefs.getBoolean("osmdroid.DebugMapView", false));
setDebugTileProviders(prefs.getBoolean("osmdroid.DebugTileProvider",false));
setMapViewHardwareAccelerated(prefs.getBoolean("osmdroid.HardwareAcceleration",false));
setUserAgentValue(prefs.getString("osmdroid.userAgentValue",ctx.getPackageName()));
setGpsWaitTime(prefs.getLong("osmdroid.gpsWaitTime", gpsWaitTime));
setTileDownloadThreads((short)(prefs.getInt("osmdroid.tileDownloadThreads",tileDownloadThreads)));
setTileFileSystemThreads((short)(prefs.getInt("osmdroid.tileFileSystemThreads",tileFileSystemThreads)));
setTileDownloadMaxQueueSize((short)(prefs.getInt("osmdroid.tileDownloadMaxQueueSize",tileDownloadMaxQueueSize)));
setTileFileSystemMaxQueueSize((short)(prefs.getInt("osmdroid.tileFileSystemMaxQueueSize",tileFileSystemMaxQueueSize)));
setExpirationExtendedDuration((long)prefs.getLong("osmdroid.ExpirationExtendedDuration", expirationAdder));
if (prefs.contains("osmdroid.ExpirationOverride")) {
expirationOverride = prefs.getLong("osmdroid.ExpirationOverride",-1);
if (expirationOverride!=null && expirationOverride==-1)
expirationOverride=null;
}
}
long cacheSize=-1;
if (Build.VERSION.SDK_INT >= 9) {
//unfortunately API 8 doesn't support File.length()
//https://github/osmdroid/osmdroid/issues/435
//On startup, we auto set the max cache size to be the current cache size + free disk space
//this reduces the chance of osmdroid completely filling up the storage device
//if the default max cache size is greater than the available free space
//reduce it to 95% of the available free space + the size of the cache
File dbFile = new File(getOsmdroidTileCache().getAbsolutePath() + File.separator + SqlTileWriter.DATABASE_FILENAME);
if (dbFile.exists()) {
cacheSize = dbFile.length();
long freeSpace = getOsmdroidTileCache().getFreeSpace();
//Log.i(TAG, "Current cache size is " + cacheSize + " free space is " + freeSpace);
if (getTileFileSystemCacheMaxBytes() > (freeSpace + cacheSize)){
setTileFileSystemCacheMaxBytes((long)((freeSpace + cacheSize) * 0.95));
setTileFileSystemCacheTrimBytes((long)((freeSpace + cacheSize) * 0.90));
}
} else {
//this is probably the first time running osmdroid
long freeSpace = getOsmdroidTileCache().length();
if (getTileFileSystemCacheMaxBytes() > (freeSpace)){
setTileFileSystemCacheMaxBytes((long)((freeSpace) * 0.95));
setTileFileSystemCacheMaxBytes((long)((freeSpace) * 0.90));
}
}
}
}
@Override
public void save(Context ctx, SharedPreferences prefs) {
SharedPreferences.Editor edit = prefs.edit();
edit.putString("osmdroid.basePath",getOsmdroidBasePath().getAbsolutePath());
edit.putString("osmdroid.cachePath",getOsmdroidTileCache().getAbsolutePath());
edit.putBoolean("osmdroid.DebugMode",isDebugMode());
edit.putBoolean("osmdroid.DebugDownloading",isDebugMapTileDownloader());
edit.putBoolean("osmdroid.DebugMapView",isDebugMapView());
edit.putBoolean("osmdroid.DebugTileProvider",isDebugTileProviders());
edit.putBoolean("osmdroid.HardwareAcceleration", isMapViewHardwareAccelerated());
edit.putString("osmdroid.userAgentValue", getUserAgentValue());
edit.putLong("osmdroid.gpsWaitTime",gpsWaitTime);
edit.putInt("osmdroid.cacheMapTileCount", cacheMapTileCount);
edit.putInt("osmdroid.tileDownloadThreads", tileDownloadThreads);
edit.putInt("osmdroid.tileFileSystemThreads",tileFileSystemThreads);
edit.putInt("osmdroid.tileDownloadMaxQueueSize",tileDownloadMaxQueueSize);
edit.putInt("osmdroid.tileFileSystemMaxQueueSize",tileFileSystemMaxQueueSize);
edit.putLong("osmdroid.ExpirationExtendedDuration",expirationAdder);
if (expirationOverride!=null)
edit.putLong("osmdroid.ExpirationOverride",expirationOverride);
//TODO save other fields?
edit.commit();
}
@Override
public long getExpirationExtendedDuration() {
return expirationAdder ;
}
@Override
public void setExpirationExtendedDuration(final long period) {
if (period < 0)
expirationAdder=0;
else
expirationAdder=period;
}
@Override
public void setExpirationOverrideDuration(Long period) {
expirationOverride=period;
}
@Override
public Long getExpirationOverrideDuration() {
return expirationOverride;
}
}