Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
c9bcaab40e
8 changed files with 418 additions and 238 deletions
|
@ -1,28 +1,31 @@
|
|||
package net.osmand.map;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface ITileSource {
|
||||
|
||||
|
||||
public int getMaximumZoomSupported();
|
||||
|
||||
|
||||
public String getName();
|
||||
|
||||
|
||||
public int getTileSize();
|
||||
|
||||
|
||||
public String getUrlToLoad(int x, int y, int zoom);
|
||||
|
||||
|
||||
public byte[] getBytes(int x, int y, int zoom, String dirWithTiles) throws IOException;
|
||||
|
||||
public int getMinimumZoomSupported();
|
||||
|
||||
|
||||
public String getTileFormat();
|
||||
|
||||
|
||||
public int getBitDensity();
|
||||
|
||||
|
||||
public boolean isEllipticYTile();
|
||||
|
||||
|
||||
public boolean couldBeDownloadedFromInternet();
|
||||
|
||||
|
||||
public int getExpirationTimeMillis();
|
||||
|
||||
|
||||
public int getExpirationTimeMinutes();
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package net.osmand.map;
|
|||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
|
@ -18,6 +19,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
@ -215,6 +217,27 @@ public class TileSourceManager {
|
|||
public String getRule() {
|
||||
return rule;
|
||||
}
|
||||
|
||||
public String calculateTileId(int x, int y, int zoom) {
|
||||
StringBuilder builder = new StringBuilder(getName());
|
||||
builder.append('/');
|
||||
builder.append(zoom).append('/').append(x).append('/').append(y).append(getTileFormat()).append(".tile"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes(int x, int y, int zoom, String dirWithTiles) throws IOException {
|
||||
File f = new File(dirWithTiles, calculateTileId(x, y, zoom));
|
||||
if (!f.exists())
|
||||
return null;
|
||||
|
||||
ByteArrayOutputStream bous = new ByteArrayOutputStream();
|
||||
FileInputStream fis = new FileInputStream(f);
|
||||
Algorithms.streamCopy(fis, bous);
|
||||
fis.close();
|
||||
bous.close();
|
||||
return bous.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, String> readMetaInfoFile(File dir) {
|
||||
|
|
|
@ -2,6 +2,8 @@ package net.osmand.core.android;
|
|||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
@ -19,247 +21,272 @@ import net.osmand.core.jni.SWIGTYPE_p_QByteArray;
|
|||
import net.osmand.core.jni.SWIGTYPE_p_bool;
|
||||
import net.osmand.core.jni.SwigUtilities;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.util.Algorithms;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.content.res.AssetManager;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
// This class provides reverse mapping from 'embed-resources.list' to files&folders scheme used by OsmAndCore_android.aar package
|
||||
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
|
||||
public class CoreResourcesFromAndroidAssetsCustom extends interface_ICoreResourcesProvider {
|
||||
private static final String TAG = "CoreResourcesFromAndroidAssets";
|
||||
private static final String NATIVE_TAG = "CoreResourcesFromAndroidAssets";
|
||||
private static final String TAG = "CoreResourcesFromAndroidAssets";
|
||||
private static final String NATIVE_TAG = "CoreResourcesFromAndroidAssets";
|
||||
|
||||
private CoreResourcesFromAndroidAssetsCustom(final Context context) {
|
||||
_context = context;
|
||||
}
|
||||
private CoreResourcesFromAndroidAssetsCustom(final Context context) {
|
||||
_context = context;
|
||||
}
|
||||
|
||||
private boolean load() {
|
||||
final AssetManager assetManager = _context.getResources().getAssets();
|
||||
private boolean load() {
|
||||
final AssetManager assetManager = _context.getResources().getAssets();
|
||||
|
||||
PackageInfo packageInfo = null;
|
||||
try {
|
||||
packageInfo = _context.getPackageManager().getPackageInfo(_context.getPackageName(), 0);
|
||||
} catch(NameNotFoundException e) {
|
||||
Log.e(TAG, "Failed to get own package info", e);
|
||||
return false;
|
||||
}
|
||||
_bundleFilename = packageInfo.applicationInfo.sourceDir;
|
||||
Log.i(TAG, "Located own package at '" + _bundleFilename + "'");
|
||||
|
||||
// Load the index
|
||||
final List<String> resourcesInBundle = new LinkedList<String>();
|
||||
try {
|
||||
final InputStream resourcesIndexStream = assetManager.open("OsmAndCore_ResourcesBundle.index", AssetManager.ACCESS_BUFFER);
|
||||
PackageInfo packageInfo = null;
|
||||
try {
|
||||
packageInfo = _context.getPackageManager().getPackageInfo(_context.getPackageName(), 0);
|
||||
} catch (NameNotFoundException e) {
|
||||
Log.e(TAG, "Failed to get own package info", e);
|
||||
return false;
|
||||
}
|
||||
_bundleFilename = packageInfo.applicationInfo.sourceDir;
|
||||
Log.i(TAG, "Located own package at '" + _bundleFilename + "'");
|
||||
|
||||
final BufferedReader resourcesIndexBufferedReader = new BufferedReader(new InputStreamReader(resourcesIndexStream));
|
||||
String resourceInBundle;
|
||||
while ((resourceInBundle = resourcesIndexBufferedReader.readLine()) != null)
|
||||
resourcesInBundle.add(resourceInBundle);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to read bundle index", e);
|
||||
return false;
|
||||
}
|
||||
Log.i(TAG, "Application contains " + resourcesInBundle.size() + " resources");
|
||||
// Load the index
|
||||
final List<String> resourcesInBundle = new LinkedList<String>();
|
||||
try {
|
||||
final InputStream resourcesIndexStream = assetManager.open("OsmAndCore_ResourcesBundle.index",
|
||||
AssetManager.ACCESS_BUFFER);
|
||||
|
||||
// Parse resources index
|
||||
final Pattern resourceNameWithQualifiersRegExp = Pattern.compile("(?:\\[(.*)\\]/)(.*)");
|
||||
for (String resourceInBundle : resourcesInBundle) {
|
||||
// Process resource name
|
||||
String pureResourceName = resourceInBundle;
|
||||
String[] qualifiers = null;
|
||||
final Matcher resourceNameComponentsMatcher = resourceNameWithQualifiersRegExp.matcher(resourceInBundle);
|
||||
if (resourceNameComponentsMatcher.matches()) {
|
||||
qualifiers = resourceNameComponentsMatcher.group(1).split(";");
|
||||
pureResourceName = resourceNameComponentsMatcher.group(2);
|
||||
}
|
||||
final BufferedReader resourcesIndexBufferedReader = new BufferedReader(new InputStreamReader(
|
||||
resourcesIndexStream));
|
||||
String resourceInBundle;
|
||||
while ((resourceInBundle = resourcesIndexBufferedReader.readLine()) != null)
|
||||
resourcesInBundle.add(resourceInBundle);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to read bundle index", e);
|
||||
return false;
|
||||
}
|
||||
Log.i(TAG, "Application contains " + resourcesInBundle.size() + " resources");
|
||||
|
||||
// Get location of this resource
|
||||
final String path = "OsmAndCore_ResourcesBundle/" + resourceInBundle + ".qz";
|
||||
final File res = ((OsmandApplication) _context.getApplicationContext()).getAppPath(path);
|
||||
final ResourceData resourceData = new ResourceData();
|
||||
if (!res.exists()) {
|
||||
// Parse resources index
|
||||
final Pattern resourceNameWithQualifiersRegExp = Pattern.compile("(?:\\[(.*)\\]/)(.*)");
|
||||
for (String resourceInBundle : resourcesInBundle) {
|
||||
// Process resource name
|
||||
String pureResourceName = resourceInBundle;
|
||||
String[] qualifiers = null;
|
||||
final Matcher resourceNameComponentsMatcher = resourceNameWithQualifiersRegExp.matcher(resourceInBundle);
|
||||
if (resourceNameComponentsMatcher.matches()) {
|
||||
qualifiers = resourceNameComponentsMatcher.group(1).split(";");
|
||||
pureResourceName = resourceNameComponentsMatcher.group(2);
|
||||
}
|
||||
|
||||
// Get location of this resource
|
||||
final String path = "OsmAndCore_ResourcesBundle/" + resourceInBundle + ".qz";
|
||||
final File extractedPath = ((OsmandApplication) _context.getApplicationContext()).getAppPath(path);
|
||||
final ResourceData resourceData = new ResourceData();
|
||||
if (!extractedPath.exists()) {
|
||||
try {
|
||||
|
||||
final AssetFileDescriptor resourceFd = assetManager.openFd(path);
|
||||
long declaredSize = resourceFd.getDeclaredLength();
|
||||
resourceData.size = resourceFd.getLength();
|
||||
resourceData.offset = resourceFd.getStartOffset();
|
||||
if(resourceData.offset == 0) {
|
||||
Log.e(NATIVE_TAG, "Offset 0 is not properly supported!");
|
||||
continue;
|
||||
}
|
||||
resourceData.path = new File(_bundleFilename);
|
||||
resourceFd.close();
|
||||
if (declaredSize != resourceData.size) {
|
||||
Log.e(NATIVE_TAG, "Declared size does not match size for '" + resourceInBundle + "'");
|
||||
continue;
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
try {
|
||||
final File containgDir = extractedPath.getParentFile();
|
||||
if (containgDir != null && !containgDir.exists())
|
||||
containgDir.mkdirs();
|
||||
extractedPath.createNewFile();
|
||||
|
||||
final InputStream resourceStream = assetManager.open(path, AssetManager.ACCESS_STREAMING);
|
||||
final FileOutputStream fileStream = new FileOutputStream(extractedPath);
|
||||
Algorithms.streamCopy(resourceStream, fileStream);
|
||||
Algorithms.closeStream(fileStream);
|
||||
Algorithms.closeStream(resourceStream);
|
||||
} catch (IOException e2) {
|
||||
if (extractedPath.exists())
|
||||
extractedPath.delete();
|
||||
|
||||
Log.e(NATIVE_TAG, "Failed to extract '" + resourceInBundle + "'", e2);
|
||||
continue;
|
||||
}
|
||||
resourceData.offset = 0;
|
||||
resourceData.path = extractedPath;
|
||||
resourceData.size = resourceData.path.length();
|
||||
} catch (IOException e) {
|
||||
Log.e(NATIVE_TAG, "Failed to locate '" + resourceInBundle + "'", e);
|
||||
continue;
|
||||
}
|
||||
|
||||
} else {
|
||||
resourceData.offset = 0;
|
||||
resourceData.path = res;
|
||||
resourceData.path = extractedPath;
|
||||
resourceData.size = resourceData.path.length();
|
||||
}
|
||||
|
||||
// Get resource entry for this resource
|
||||
ResourceEntry resourceEntry = _resources.get(pureResourceName);
|
||||
if (resourceEntry == null) {
|
||||
resourceEntry = new ResourceEntry();
|
||||
_resources.put(pureResourceName, resourceEntry);
|
||||
}
|
||||
if (qualifiers == null) {
|
||||
resourceEntry.defaultVariant = resourceData;
|
||||
} else {
|
||||
for (String qualifier : qualifiers) {
|
||||
final String[] qualifierComponents = qualifier.trim().split("=");
|
||||
|
||||
if (qualifierComponents.length == 2 && qualifierComponents[0].equals("ddf")) {
|
||||
float ddfValue;
|
||||
try {
|
||||
ddfValue = Float.parseFloat(qualifierComponents[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
Log.e(TAG, "Unsupported value '" + qualifierComponents[1] + "' for DDF qualifier", e);
|
||||
continue;
|
||||
}
|
||||
// Get resource entry for this resource
|
||||
ResourceEntry resourceEntry = _resources.get(pureResourceName);
|
||||
if (resourceEntry == null) {
|
||||
resourceEntry = new ResourceEntry();
|
||||
_resources.put(pureResourceName, resourceEntry);
|
||||
}
|
||||
if (qualifiers == null) {
|
||||
resourceEntry.defaultVariant = resourceData;
|
||||
} else {
|
||||
for (String qualifier : qualifiers) {
|
||||
final String[] qualifierComponents = qualifier.trim().split("=");
|
||||
|
||||
if (resourceEntry.variantsByDisplayDensityFactor == null)
|
||||
resourceEntry.variantsByDisplayDensityFactor = new TreeMap<Float, ResourceData>();
|
||||
resourceEntry.variantsByDisplayDensityFactor.put(ddfValue, resourceData);
|
||||
} else {
|
||||
Log.w(TAG, "Unsupported qualifier '" + qualifier.trim() + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (qualifierComponents.length == 2 && qualifierComponents[0].equals("ddf")) {
|
||||
float ddfValue;
|
||||
try {
|
||||
ddfValue = Float.parseFloat(qualifierComponents[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
Log.e(TAG, "Unsupported value '" + qualifierComponents[1] + "' for DDF qualifier", e);
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private final Context _context;
|
||||
private String _bundleFilename;
|
||||
private final HashMap<String, ResourceEntry> _resources = new HashMap<String, ResourceEntry>();
|
||||
|
||||
private final class ResourceData {
|
||||
public File path;
|
||||
public long offset;
|
||||
public long size;
|
||||
}
|
||||
private final class ResourceEntry {
|
||||
public ResourceData defaultVariant;
|
||||
public TreeMap<Float, ResourceData> variantsByDisplayDensityFactor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWIGTYPE_p_QByteArray getResource(String name, float displayDensityFactor, SWIGTYPE_p_bool ok_) {
|
||||
final BoolPtr ok = BoolPtr.frompointer(ok_);
|
||||
|
||||
final ResourceEntry resourceEntry = _resources.get(name);
|
||||
if (resourceEntry == null || resourceEntry.variantsByDisplayDensityFactor == null) {
|
||||
Log.w(TAG, "Requested resource [ddf=" + displayDensityFactor + "]'" + name + "' was not found");
|
||||
if (ok != null)
|
||||
ok.assign(false);
|
||||
return SwigUtilities.emptyQByteArray();
|
||||
}
|
||||
|
||||
Map.Entry<Float, ResourceData> resourceDataEntry = resourceEntry.variantsByDisplayDensityFactor.ceilingEntry(displayDensityFactor);
|
||||
if (resourceDataEntry == null)
|
||||
resourceDataEntry = resourceEntry.variantsByDisplayDensityFactor.lastEntry();
|
||||
ResourceData resourceData = resourceDataEntry.getValue();
|
||||
Log.d(TAG, "Using ddf=" + resourceDataEntry.getKey() + " while looking for " + displayDensityFactor + " of '" + name + "'");
|
||||
System.out.println(resourceData.path.getAbsolutePath());
|
||||
final SWIGTYPE_p_QByteArray data ;
|
||||
if(resourceData.offset == 0){
|
||||
data = SwigUtilities.qDecompress(SwigUtilities.readEntireFile(
|
||||
resourceData.path.getAbsolutePath()));
|
||||
} else {
|
||||
data = SwigUtilities.qDecompress(SwigUtilities.readPartOfFile(
|
||||
resourceData.path.getAbsolutePath(), resourceData.offset, resourceData.size));
|
||||
if (resourceEntry.variantsByDisplayDensityFactor == null)
|
||||
resourceEntry.variantsByDisplayDensityFactor = new TreeMap<Float, ResourceData>();
|
||||
resourceEntry.variantsByDisplayDensityFactor.put(ddfValue, resourceData);
|
||||
} else {
|
||||
Log.w(TAG, "Unsupported qualifier '" + qualifier.trim() + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data == null) {
|
||||
Log.e(TAG, "Failed to load data of '" + name + "'");
|
||||
if (ok != null)
|
||||
ok.assign(false);
|
||||
return SwigUtilities.emptyQByteArray();
|
||||
}
|
||||
|
||||
if (ok != null)
|
||||
ok.assign(true);
|
||||
return data;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWIGTYPE_p_QByteArray getResource(String name, SWIGTYPE_p_bool ok_) {
|
||||
final BoolPtr ok = BoolPtr.frompointer(ok_);
|
||||
|
||||
final ResourceEntry resourceEntry = _resources.get(name);
|
||||
if (resourceEntry == null) {
|
||||
Log.w(TAG, "Requested resource '" + name + "' was not found");
|
||||
if (ok != null)
|
||||
ok.assign(false);
|
||||
return SwigUtilities.emptyQByteArray();
|
||||
}
|
||||
private final Context _context;
|
||||
private String _bundleFilename;
|
||||
private final HashMap<String, ResourceEntry> _resources = new HashMap<String, ResourceEntry>();
|
||||
|
||||
if (resourceEntry.defaultVariant == null) {
|
||||
Log.w(TAG, "Requested resource '" + name + "' was not found");
|
||||
if (ok != null)
|
||||
ok.assign(false);
|
||||
return SwigUtilities.emptyQByteArray();
|
||||
}
|
||||
private final class ResourceData {
|
||||
public File path;
|
||||
public long offset;
|
||||
public long size;
|
||||
}
|
||||
|
||||
private final class ResourceEntry {
|
||||
public ResourceData defaultVariant;
|
||||
public TreeMap<Float, ResourceData> variantsByDisplayDensityFactor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWIGTYPE_p_QByteArray getResource(String name, float displayDensityFactor, SWIGTYPE_p_bool ok_) {
|
||||
final BoolPtr ok = BoolPtr.frompointer(ok_);
|
||||
|
||||
final ResourceEntry resourceEntry = _resources.get(name);
|
||||
if (resourceEntry == null || resourceEntry.variantsByDisplayDensityFactor == null) {
|
||||
Log.w(TAG, "Requested resource [ddf=" + displayDensityFactor + "]'" + name + "' was not found");
|
||||
if (ok != null)
|
||||
ok.assign(false);
|
||||
return SwigUtilities.emptyQByteArray();
|
||||
}
|
||||
|
||||
Map.Entry<Float, ResourceData> resourceDataEntry = resourceEntry.variantsByDisplayDensityFactor
|
||||
.ceilingEntry(displayDensityFactor);
|
||||
if (resourceDataEntry == null)
|
||||
resourceDataEntry = resourceEntry.variantsByDisplayDensityFactor.lastEntry();
|
||||
ResourceData resourceData = resourceDataEntry.getValue();
|
||||
Log.d(TAG, "Using ddf=" + resourceDataEntry.getKey() + " while looking for " + displayDensityFactor + " of '"
|
||||
+ name + "'");
|
||||
System.out.println(resourceData.path.getAbsolutePath());
|
||||
final SWIGTYPE_p_QByteArray data;
|
||||
if (resourceData.offset == 0 && resourceData.size == resourceData.path.length()) {
|
||||
data = SwigUtilities.qDecompress(SwigUtilities.readEntireFile(resourceData.path.getAbsolutePath()));
|
||||
} else {
|
||||
data = SwigUtilities.qDecompress(SwigUtilities.readPartOfFile(resourceData.path.getAbsolutePath(),
|
||||
resourceData.offset, resourceData.size));
|
||||
}
|
||||
if (data == null) {
|
||||
Log.e(TAG, "Failed to load data of '" + name + "'");
|
||||
if (ok != null)
|
||||
ok.assign(false);
|
||||
return SwigUtilities.emptyQByteArray();
|
||||
}
|
||||
|
||||
if (ok != null)
|
||||
ok.assign(true);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWIGTYPE_p_QByteArray getResource(String name, SWIGTYPE_p_bool ok_) {
|
||||
final BoolPtr ok = BoolPtr.frompointer(ok_);
|
||||
|
||||
final ResourceEntry resourceEntry = _resources.get(name);
|
||||
if (resourceEntry == null) {
|
||||
Log.w(TAG, "Requested resource '" + name + "' was not found");
|
||||
if (ok != null)
|
||||
ok.assign(false);
|
||||
return SwigUtilities.emptyQByteArray();
|
||||
}
|
||||
|
||||
if (resourceEntry.defaultVariant == null) {
|
||||
Log.w(TAG, "Requested resource '" + name + "' was not found");
|
||||
if (ok != null)
|
||||
ok.assign(false);
|
||||
return SwigUtilities.emptyQByteArray();
|
||||
}
|
||||
System.out.println(resourceEntry.defaultVariant.path.getAbsolutePath());
|
||||
final SWIGTYPE_p_QByteArray bt ;
|
||||
if(resourceEntry.defaultVariant.offset == 0){
|
||||
final SWIGTYPE_p_QByteArray bt;
|
||||
if (resourceEntry.defaultVariant.offset == 0
|
||||
&& resourceEntry.defaultVariant.size == resourceEntry.defaultVariant.path.length()) {
|
||||
bt = SwigUtilities.readEntireFile(resourceEntry.defaultVariant.path.getAbsolutePath());
|
||||
} else {
|
||||
bt = SwigUtilities.readPartOfFile(resourceEntry.defaultVariant.path.getAbsolutePath(),
|
||||
resourceEntry.defaultVariant.offset, resourceEntry.defaultVariant.size);
|
||||
}
|
||||
final SWIGTYPE_p_QByteArray data = SwigUtilities.qDecompress(bt);
|
||||
if (data == null) {
|
||||
Log.e(TAG, "Failed to load data of '" + name + "'");
|
||||
if (ok != null)
|
||||
ok.assign(false);
|
||||
return SwigUtilities.emptyQByteArray();
|
||||
}
|
||||
if (data == null) {
|
||||
Log.e(TAG, "Failed to load data of '" + name + "'");
|
||||
if (ok != null)
|
||||
ok.assign(false);
|
||||
return SwigUtilities.emptyQByteArray();
|
||||
}
|
||||
|
||||
if (ok != null)
|
||||
ok.assign(true);
|
||||
return data;
|
||||
}
|
||||
if (ok != null)
|
||||
ok.assign(true);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsResource(String name, float displayDensityFactor) {
|
||||
final ResourceEntry resourceEntry = _resources.get(name);
|
||||
if (resourceEntry == null || resourceEntry.variantsByDisplayDensityFactor == null)
|
||||
return false;
|
||||
@Override
|
||||
public boolean containsResource(String name, float displayDensityFactor) {
|
||||
final ResourceEntry resourceEntry = _resources.get(name);
|
||||
if (resourceEntry == null || resourceEntry.variantsByDisplayDensityFactor == null)
|
||||
return false;
|
||||
|
||||
// If there's variant for any DDF, it will be used
|
||||
return true;
|
||||
}
|
||||
// If there's variant for any DDF, it will be used
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsResource(String name) {
|
||||
final ResourceEntry resourceEntry = _resources.get(name);
|
||||
if (resourceEntry == null)
|
||||
return false;
|
||||
@Override
|
||||
public boolean containsResource(String name) {
|
||||
final ResourceEntry resourceEntry = _resources.get(name);
|
||||
if (resourceEntry == null)
|
||||
return false;
|
||||
|
||||
if (resourceEntry.defaultVariant == null)
|
||||
return false;
|
||||
if (resourceEntry.defaultVariant == null)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static CoreResourcesFromAndroidAssetsCustom loadFromCurrentApplication(final Context context) {
|
||||
final CoreResourcesFromAndroidAssetsCustom bundle = new CoreResourcesFromAndroidAssetsCustom(context);
|
||||
public static CoreResourcesFromAndroidAssetsCustom loadFromCurrentApplication(final Context context) {
|
||||
final CoreResourcesFromAndroidAssetsCustom bundle = new CoreResourcesFromAndroidAssetsCustom(context);
|
||||
|
||||
if (!bundle.load())
|
||||
return null;
|
||||
if (!bundle.load())
|
||||
return null;
|
||||
|
||||
return bundle;
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package net.osmand.core.android;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.core.jni.AlphaChannelPresence;
|
||||
import net.osmand.core.jni.SWIGTYPE_p_QByteArray;
|
||||
import net.osmand.core.jni.SwigUtilities;
|
||||
import net.osmand.core.jni.TileId;
|
||||
import net.osmand.core.jni.ZoomLevel;
|
||||
import net.osmand.core.jni.interface_ImageMapLayerProvider;
|
||||
import net.osmand.map.ITileSource;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
|
||||
public class TileSourceProxyProvider extends interface_ImageMapLayerProvider {
|
||||
|
||||
private final OsmandApplication app;
|
||||
private final ITileSource tileSource;
|
||||
|
||||
public TileSourceProxyProvider(OsmandApplication app, ITileSource tileSource) {
|
||||
this.app = app;
|
||||
this.tileSource = tileSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZoomLevel getMinZoom() {
|
||||
return ZoomLevel.swigToEnum(tileSource.getMinimumZoomSupported());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZoomLevel getMaxZoom() {
|
||||
return ZoomLevel.swigToEnum(tileSource.getMaximumZoomSupported());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWIGTYPE_p_QByteArray obtainImage(TileId tileId, ZoomLevel zoom) {
|
||||
byte[] image;
|
||||
try {
|
||||
image = tileSource.getBytes(tileId.getX(), tileId.getY(), zoom.swigValue(),
|
||||
app.getAppPath(IndexConstants.TILES_INDEX_DIR).getAbsolutePath());
|
||||
} catch(IOException e) {
|
||||
return SwigUtilities.emptyQByteArray();
|
||||
}
|
||||
if (image == null)
|
||||
return SwigUtilities.emptyQByteArray();
|
||||
|
||||
return SwigUtilities.createQByteArrayAsCopyOf(image);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTileSize() {
|
||||
return tileSource.getTileSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getTileDensityFactor() {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlphaChannelPresence getAlphaChannelPresence() {
|
||||
return AlphaChannelPresence.Unknown;
|
||||
}
|
||||
}
|
|
@ -14,7 +14,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.StateChangedListener;
|
||||
import net.osmand.data.LatLon;
|
||||
|
@ -28,6 +27,7 @@ import net.osmand.plus.api.SettingsAPI.SettingsEditor;
|
|||
import net.osmand.plus.render.RendererRegistry;
|
||||
import net.osmand.plus.routing.RouteProvider.RouteService;
|
||||
import net.osmand.render.RenderingRulesStorage;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.hardware.Sensor;
|
||||
|
@ -989,18 +989,18 @@ public class OsmandSettings {
|
|||
public final CommonPreference<Boolean> SHOW_DESTINATION_ARROW = new BooleanPreference("show_destination_arrow", false).makeProfile();
|
||||
|
||||
// this value string is synchronized with settings_pref.xml preference name
|
||||
public final CommonPreference<String> MAP_OVERLAY = new StringPreference("map_overlay", null).makeGlobal();
|
||||
public final CommonPreference<String> MAP_OVERLAY = new StringPreference("map_overlay", null).makeGlobal().cache();
|
||||
|
||||
// this value string is synchronized with settings_pref.xml preference name
|
||||
public final CommonPreference<String> MAP_UNDERLAY = new StringPreference("map_underlay", null).makeGlobal();
|
||||
public final CommonPreference<String> MAP_UNDERLAY = new StringPreference("map_underlay", null).makeGlobal().cache();
|
||||
|
||||
// this value string is synchronized with settings_pref.xml preference name
|
||||
public final CommonPreference<Integer> MAP_OVERLAY_TRANSPARENCY = new IntPreference("overlay_transparency",
|
||||
100).makeGlobal();
|
||||
100).makeGlobal().cache();
|
||||
|
||||
// this value string is synchronized with settings_pref.xml preference name
|
||||
public final CommonPreference<Integer> MAP_TRANSPARENCY = new IntPreference("map_transparency",
|
||||
255).makeGlobal();
|
||||
255).makeGlobal().cache();
|
||||
|
||||
// this value string is synchronized with settings_pref.xml preference name
|
||||
public final CommonPreference<String> MAP_TILE_SOURCES = new StringPreference("map_tile_sources",
|
||||
|
@ -1160,6 +1160,7 @@ public class OsmandSettings {
|
|||
return writableSecondaryStorage;
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public String getMatchingExternalFilesDir(String dir) {
|
||||
// only API 19 !!
|
||||
try {
|
||||
|
@ -1183,6 +1184,7 @@ public class OsmandSettings {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public List<String> getWritableSecondaryStorageDirectorys() {
|
||||
// only API 19 !!
|
||||
// primary external storage directory
|
||||
|
|
|
@ -18,7 +18,6 @@ import net.osmand.plus.api.SQLiteAPI.SQLiteCursor;
|
|||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.http.client.protocol.ClientContext;
|
||||
|
||||
import android.database.sqlite.SQLiteDiskIOException;
|
||||
import android.graphics.Bitmap;
|
||||
|
@ -262,7 +261,7 @@ public class SQLiteTileSource implements ITileSource {
|
|||
return db.isDbLockedByOtherThreads();
|
||||
}
|
||||
|
||||
public Bitmap getImage(int x, int y, int zoom, long[] timeHolder) {
|
||||
public byte[] getBytes(int x, int y, int zoom, String dirWithTiles, long[] timeHolder) throws IOException {
|
||||
SQLiteConnection db = getDatabase();
|
||||
if(db == null){
|
||||
return null;
|
||||
|
@ -283,15 +282,7 @@ public class SQLiteTileSource implements ITileSource {
|
|||
}
|
||||
}
|
||||
cursor.close();
|
||||
if (blob != null) {
|
||||
Bitmap bmp = null;
|
||||
bmp = BitmapFactory.decodeByteArray(blob, 0, blob.length);
|
||||
if(bmp == null) {
|
||||
// broken image delete it
|
||||
db.execSQL("DELETE FROM tiles WHERE x = ? AND y = ? AND z = ?", params);
|
||||
}
|
||||
return bmp;
|
||||
}
|
||||
return blob;
|
||||
}
|
||||
return null;
|
||||
} finally {
|
||||
|
@ -301,6 +292,35 @@ public class SQLiteTileSource implements ITileSource {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes(int x, int y, int zoom, String dirWithTiles) throws IOException {
|
||||
return getBytes(x, y, zoom, dirWithTiles, null);
|
||||
}
|
||||
|
||||
public Bitmap getImage(int x, int y, int zoom, long[] timeHolder) {
|
||||
SQLiteConnection db = getDatabase();
|
||||
if(db == null){
|
||||
return null;
|
||||
}
|
||||
String[] params = new String[] { x + "", y + "", getFileZoom(zoom) + "" };
|
||||
byte[] blob;
|
||||
try {
|
||||
blob = getBytes(x, y, zoom, null, timeHolder);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
if (blob != null) {
|
||||
Bitmap bmp = null;
|
||||
bmp = BitmapFactory.decodeByteArray(blob, 0, blob.length);
|
||||
if(bmp == null) {
|
||||
// broken image delete it
|
||||
db.execSQL("DELETE FROM tiles WHERE x = ? AND y = ? AND z = ?", params);
|
||||
}
|
||||
return bmp;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ITileSource getBase() {
|
||||
return base;
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
package net.osmand.plus.render;
|
||||
|
||||
import net.osmand.core.android.MapRendererView;
|
||||
import net.osmand.core.android.TileSourceProxyProvider;
|
||||
import net.osmand.core.jni.MapLayerConfiguration;
|
||||
import net.osmand.core.jni.PointI;
|
||||
import net.osmand.data.QuadPointDouble;
|
||||
import net.osmand.data.RotatedTileBox;
|
||||
import net.osmand.map.ITileSource;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.resources.ResourceManager;
|
||||
import net.osmand.plus.views.BaseMapLayer;
|
||||
import net.osmand.plus.views.MapTileLayer;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
import net.osmand.plus.views.corenative.NativeCoreContext;
|
||||
import net.osmand.util.Algorithms;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
|
@ -20,17 +25,20 @@ public class MapVectorLayer extends BaseMapLayer {
|
|||
private OsmandMapTileView view;
|
||||
private ResourceManager resourceManager;
|
||||
private Paint paintImg;
|
||||
|
||||
|
||||
private RectF destImage = new RectF();
|
||||
private final MapTileLayer tileLayer;
|
||||
private boolean visible = false;
|
||||
private boolean oldRender = false;
|
||||
|
||||
public MapVectorLayer(MapTileLayer tileLayer, boolean oldRender){
|
||||
private String cachedUnderlay;
|
||||
private Integer cachedMapTransparency;
|
||||
private String cachedOverlay;
|
||||
private Integer cachedOverlayTransparency;
|
||||
|
||||
public MapVectorLayer(MapTileLayer tileLayer, boolean oldRender) {
|
||||
this.tileLayer = tileLayer;
|
||||
this.oldRender = oldRender;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void destroyLayer() {
|
||||
|
@ -49,43 +57,39 @@ public class MapVectorLayer extends BaseMapLayer {
|
|||
paintImg.setFilterBitmap(true);
|
||||
paintImg.setAlpha(getAlpha());
|
||||
}
|
||||
|
||||
|
||||
public boolean isVectorDataVisible() {
|
||||
return visible && view.getZoom() >= view.getSettings().LEVEL_TO_SWITCH_VECTOR_RASTER.get();
|
||||
return visible && view.getZoom() >= view.getSettings().LEVEL_TO_SWITCH_VECTOR_RASTER.get();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean isVisible() {
|
||||
return visible;
|
||||
}
|
||||
|
||||
|
||||
public void setVisible(boolean visible) {
|
||||
this.visible = visible;
|
||||
if(!visible){
|
||||
if (!visible) {
|
||||
resourceManager.getRenderer().clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMaximumShownMapZoom() {
|
||||
return 23;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMinimumShownMapZoom() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas, RotatedTileBox tilesRect, DrawSettings drawSettings) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tilesRect,
|
||||
DrawSettings drawSettings) {
|
||||
public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tilesRect, DrawSettings drawSettings) {
|
||||
if (!visible) {
|
||||
return;
|
||||
}
|
||||
|
@ -96,10 +100,46 @@ public class MapVectorLayer extends BaseMapLayer {
|
|||
final MapRendererView mapRenderer = view.getMapRenderer();
|
||||
if (mapRenderer != null && !oldRender) {
|
||||
NativeCoreContext.getMapRendererContext().setNightMode(drawSettings.isNightMode());
|
||||
OsmandSettings st = view.getApplication().getSettings();
|
||||
if (!Algorithms.objectEquals(st.MAP_UNDERLAY.get(), cachedUnderlay)) {
|
||||
cachedUnderlay = st.MAP_UNDERLAY.get();
|
||||
ITileSource tileSource = st.getTileSourceByName(cachedUnderlay, false);
|
||||
if (tileSource != null) {
|
||||
TileSourceProxyProvider prov = new TileSourceProxyProvider(view.getApplication(), tileSource);
|
||||
mapRenderer.setMapLayerProvider(-1, prov.instantiateProxy(true));
|
||||
prov.swigReleaseOwnership();
|
||||
} else {
|
||||
mapRenderer.resetMapLayerProvider(-1);
|
||||
}
|
||||
}
|
||||
if (st.MAP_TRANSPARENCY.get() != cachedMapTransparency) {
|
||||
cachedMapTransparency = st.MAP_TRANSPARENCY.get();
|
||||
MapLayerConfiguration mapLayerConfiguration = new MapLayerConfiguration();
|
||||
mapLayerConfiguration.setOpacity(((float)cachedMapTransparency) / 255.0f);
|
||||
mapRenderer.setMapLayerConfiguration(0, mapLayerConfiguration);
|
||||
}
|
||||
if (!Algorithms.objectEquals(st.MAP_OVERLAY.get(), cachedOverlay)) {
|
||||
cachedOverlay = st.MAP_OVERLAY.get();
|
||||
ITileSource tileSource = st.getTileSourceByName(cachedOverlay, false);
|
||||
if (tileSource != null) {
|
||||
TileSourceProxyProvider prov = new TileSourceProxyProvider(view.getApplication(), tileSource);
|
||||
mapRenderer.setMapLayerProvider(1, prov.instantiateProxy(true));
|
||||
prov.swigReleaseOwnership();
|
||||
} else {
|
||||
mapRenderer.resetMapLayerProvider(1);
|
||||
}
|
||||
}
|
||||
if (st.MAP_OVERLAY_TRANSPARENCY.get() != cachedOverlayTransparency) {
|
||||
cachedOverlayTransparency = st.MAP_OVERLAY_TRANSPARENCY.get();
|
||||
MapLayerConfiguration mapLayerConfiguration = new MapLayerConfiguration();
|
||||
mapLayerConfiguration.setOpacity(((float)cachedOverlayTransparency) / 255.0f);
|
||||
mapRenderer.setMapLayerConfiguration(1, mapLayerConfiguration);
|
||||
}
|
||||
// opengl renderer
|
||||
mapRenderer.setTarget(new PointI(tilesRect.getCenter31X(), tilesRect.getCenter31Y()));
|
||||
mapRenderer.setAzimuth(-tilesRect.getRotate());
|
||||
mapRenderer.setZoom((float) (tilesRect.getZoom() /*+ tilesRect.getZoomScale() */+ tilesRect.getZoomAnimation()));
|
||||
mapRenderer.setZoom((float) (tilesRect.getZoom() /* + tilesRect.getZoomScale() */+ tilesRect
|
||||
.getZoomAnimation()));
|
||||
} else {
|
||||
if (!view.isZooming()) {
|
||||
if (resourceManager.updateRenderedMapNeeded(tilesRect, drawSettings)) {
|
||||
|
@ -122,7 +162,7 @@ public class MapVectorLayer extends BaseMapLayer {
|
|||
private boolean drawRenderedMap(Canvas canvas, Bitmap bmp, RotatedTileBox bmpLoc, RotatedTileBox currentViewport) {
|
||||
boolean shown = false;
|
||||
if (bmp != null && bmpLoc != null) {
|
||||
float rot = - bmpLoc.getRotate();
|
||||
float rot = -bmpLoc.getRotate();
|
||||
int cz = currentViewport.getZoom();
|
||||
canvas.rotate(rot, currentViewport.getCenterPixelX(), currentViewport.getCenterPixelY());
|
||||
final RotatedTileBox calc = currentViewport.copy();
|
||||
|
@ -134,7 +174,7 @@ public class MapVectorLayer extends BaseMapLayer {
|
|||
final float y1 = calc.getPixYFromTile(lt.x, lt.y, cz);
|
||||
final float y2 = calc.getPixYFromTile(rb.x, rb.y, cz);
|
||||
destImage.set(x1, y1, x2, y2);
|
||||
if(!bmp.isRecycled()){
|
||||
if (!bmp.isRecycled()) {
|
||||
canvas.drawBitmap(bmp, null, destImage, paintImg);
|
||||
shown = true;
|
||||
}
|
||||
|
@ -143,15 +183,14 @@ public class MapVectorLayer extends BaseMapLayer {
|
|||
return shown;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
super.setAlpha(alpha);
|
||||
if (paintImg != null) {
|
||||
paintImg.setAlpha(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongPressEvent(PointF point, RotatedTileBox tileBox) {
|
||||
return false;
|
||||
|
|
|
@ -12,6 +12,7 @@ import net.osmand.plus.R;
|
|||
import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin;
|
||||
import net.osmand.plus.resources.ResourceManager;
|
||||
import net.osmand.util.MapUtils;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
|
@ -110,6 +111,7 @@ public class MapTileLayer extends BaseMapLayer {
|
|||
return mapTileAdapter;
|
||||
}
|
||||
|
||||
@SuppressLint("WrongCall")
|
||||
@Override
|
||||
public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox,
|
||||
DrawSettings drawSettings) {
|
||||
|
|
Loading…
Reference in a new issue