Merge remote-tracking branch 'origin/integration'

This commit is contained in:
Victor Shcherb 2014-12-11 20:33:36 +01:00
commit 4400f2c3b2
8 changed files with 418 additions and 238 deletions

View file

@ -1,5 +1,6 @@
package net.osmand.map;
import java.io.IOException;
public interface ITileSource {
@ -11,6 +12,8 @@ public interface ITileSource {
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();

View file

@ -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) {

View file

@ -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,14 +21,18 @@ 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";
@ -41,7 +47,7 @@ public class CoreResourcesFromAndroidAssetsCustom extends interface_ICoreResourc
PackageInfo packageInfo = null;
try {
packageInfo = _context.getPackageManager().getPackageInfo(_context.getPackageName(), 0);
} catch(NameNotFoundException e) {
} catch (NameNotFoundException e) {
Log.e(TAG, "Failed to get own package info", e);
return false;
}
@ -51,9 +57,11 @@ public class CoreResourcesFromAndroidAssetsCustom extends interface_ICoreResourc
// Load the index
final List<String> resourcesInBundle = new LinkedList<String>();
try {
final InputStream resourcesIndexStream = assetManager.open("OsmAndCore_ResourcesBundle.index", AssetManager.ACCESS_BUFFER);
final InputStream resourcesIndexStream = assetManager.open("OsmAndCore_ResourcesBundle.index",
AssetManager.ACCESS_BUFFER);
final BufferedReader resourcesIndexBufferedReader = new BufferedReader(new InputStreamReader(resourcesIndexStream));
final BufferedReader resourcesIndexBufferedReader = new BufferedReader(new InputStreamReader(
resourcesIndexStream));
String resourceInBundle;
while ((resourceInBundle = resourcesIndexBufferedReader.readLine()) != null)
resourcesInBundle.add(resourceInBundle);
@ -77,33 +85,49 @@ public class CoreResourcesFromAndroidAssetsCustom extends interface_ICoreResourc
// Get location of this resource
final String path = "OsmAndCore_ResourcesBundle/" + resourceInBundle + ".qz";
final File res = ((OsmandApplication) _context.getApplicationContext()).getAppPath(path);
final File extractedPath = ((OsmandApplication) _context.getApplicationContext()).getAppPath(path);
final ResourceData resourceData = new ResourceData();
if (!res.exists()) {
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();
}
@ -150,6 +174,7 @@ public class CoreResourcesFromAndroidAssetsCustom extends interface_ICoreResourc
public long offset;
public long size;
}
private final class ResourceEntry {
public ResourceData defaultVariant;
public TreeMap<Float, ResourceData> variantsByDisplayDensityFactor;
@ -167,19 +192,20 @@ public class CoreResourcesFromAndroidAssetsCustom extends interface_ICoreResourc
return SwigUtilities.emptyQByteArray();
}
Map.Entry<Float, ResourceData> resourceDataEntry = resourceEntry.variantsByDisplayDensityFactor.ceilingEntry(displayDensityFactor);
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 + "'");
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()));
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));
data = SwigUtilities.qDecompress(SwigUtilities.readPartOfFile(resourceData.path.getAbsolutePath(),
resourceData.offset, resourceData.size));
}
if (data == null) {
Log.e(TAG, "Failed to load data of '" + name + "'");
@ -212,8 +238,9 @@ public class CoreResourcesFromAndroidAssetsCustom extends interface_ICoreResourc
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(),

View file

@ -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;
}
}

View file

@ -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;
@ -987,18 +987,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",
@ -1158,6 +1158,7 @@ public class OsmandSettings {
return writableSecondaryStorage;
}
@SuppressLint("NewApi")
public String getMatchingExternalFilesDir(String dir) {
// only API 19 !!
try {
@ -1181,6 +1182,7 @@ public class OsmandSettings {
}
}
@SuppressLint("NewApi")
public List<String> getWritableSecondaryStorageDirectorys() {
// only API 19 !!
// primary external storage directory

View file

@ -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,6 +282,34 @@ public class SQLiteTileSource implements ITileSource {
}
}
cursor.close();
return blob;
}
return null;
} finally {
if(log.isDebugEnabled()) {
log.debug("Load tile " + x + "/" + y + "/" + zoom + " for " + (System.currentTimeMillis() - ts)
+ " ms ");
}
}
}
@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);
@ -292,14 +319,7 @@ public class SQLiteTileSource implements ITileSource {
}
return bmp;
}
}
return null;
} finally {
if(log.isDebugEnabled()) {
log.debug("Load tile " + x + "/" + y + "/" + zoom + " for " + (System.currentTimeMillis() - ts)
+ " ms ");
}
}
}
public ITileSource getBase() {

View file

@ -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;
@ -25,13 +30,16 @@ public class MapVectorLayer extends BaseMapLayer {
private final MapTileLayer tileLayer;
private boolean visible = false;
private boolean oldRender = false;
private String cachedUnderlay;
private Integer cachedMapTransparency;
private String cachedOverlay;
private Integer cachedOverlayTransparency;
public MapVectorLayer(MapTileLayer tileLayer, boolean oldRender){
public MapVectorLayer(MapTileLayer tileLayer, boolean oldRender) {
this.tileLayer = tileLayer;
this.oldRender = oldRender;
}
@Override
public void destroyLayer() {
}
@ -54,14 +62,13 @@ public class MapVectorLayer extends BaseMapLayer {
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();
}
}
@ -76,16 +83,13 @@ public class MapVectorLayer extends BaseMapLayer {
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,7 +183,6 @@ public class MapVectorLayer extends BaseMapLayer {
return shown;
}
@Override
public void setAlpha(int alpha) {
super.setAlpha(alpha);

View file

@ -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) {