com.mapbox.mapboxsdk.tileprovider.tilesource.MBTilesLayer Maven / Gradle / Ivy
package com.mapbox.mapboxsdk.tileprovider.tilesource;
import android.content.Context;
import android.content.res.AssetManager;
import android.database.sqlite.SQLiteDatabase;
import android.os.Environment;
import android.util.Log;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.tileprovider.MapTile;
import com.mapbox.mapboxsdk.tileprovider.modules.MBTilesFileArchive;
import com.mapbox.mapboxsdk.tileprovider.modules.MapTileDownloader;
import com.mapbox.mapboxsdk.views.util.constants.MapViewConstants;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import uk.co.senab.bitmapcache.CacheableBitmapDrawable;
/**
* A layer that pulls resources from an MBTiles file. Used for offline map tiles,
* like those generated by TileMill.
*/
public class MBTilesLayer extends TileLayer implements MapViewConstants, MapboxConstants {
private static final String TAG = "MBTilesLayer";
MBTilesFileArchive mbTilesFileArchive;
/**
* Initialize a new tile layer, represented by a MBTiles file.
*
* @param url path to a MBTiles file
* @param context the graphics drawing context
*/
public MBTilesLayer(final Context context, final String url) {
super(url.substring(url.lastIndexOf('/') + 1, url.lastIndexOf('.')), url);
initialize(url, context);
}
/**
* Initialize a new tile layer, represented by a MBTiles file.
* This constructor does need a context but as a consequence won't look
* for an asset mbtiles
*
* @param url path to a MBTiles file
*/
public MBTilesLayer(final String url) {
this(null, url);
}
/**
* Initialize a new tile layer, represented by a MBTiles file.
*
* @param file a MBTiles file
*/
public MBTilesLayer(final File file) {
super(file.getName(), file.getAbsolutePath());
initialize(file);
}
/**
* Initialize a new tile layer, represented by a Database file.
*
* @param db a database used as the MBTiles source
*/
public MBTilesLayer(final SQLiteDatabase db) {
super(getFileName(db.getPath()), db.getPath());
initialize(db);
}
/**
* Get the filename of this layer based on the full path
* @param path
* @return the filename of the backing mbtiles file
*/
private static final String getFileName(final String path) {
return path.substring(path.lastIndexOf('/') + 1, path.lastIndexOf('.'));
}
/**
* Creates a file from an input stream by reading it byte by byte.
* todo: same as MapViewFactory's createFileFromInputStream
*/
private static File createFileFromInputStream(InputStream inputStream, String URL) {
try {
File f = new File(URL);
OutputStream outputStream = new FileOutputStream(f);
byte[] buffer = new byte[1024];
int length = 0;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
outputStream.close();
inputStream.close();
return f;
} catch (IOException e) {
Log.e(TAG, "Failed to create file from input stream.", e);
}
return null;
}
/**
* Reads and opens a MBTiles file and loads its tiles into this layer.
* @param file
*/
private void initialize(File file) {
if (file != null) {
mbTilesFileArchive = MBTilesFileArchive.getDatabaseFileArchive(file);
}
if (mbTilesFileArchive != null) {
mMaximumZoomLevel = mbTilesFileArchive.getMaxZoomLevel();
mMinimumZoomLevel = mbTilesFileArchive.getMinZoomLevel();
mName = mbTilesFileArchive.getName();
mDescription = mbTilesFileArchive.getDescription();
mAttribution = mbTilesFileArchive.getAttribution();
mBoundingBox = mbTilesFileArchive.getBounds();
mCenter = mbTilesFileArchive.getCenter();
}
}
/**
* Reads and opens a MBTiles file given by url and loads its tiles into this layer.
*/
private void initialize(final SQLiteDatabase db) {
if (db != null) {
mbTilesFileArchive = new MBTilesFileArchive(db);
}
if (mbTilesFileArchive != null) {
mMaximumZoomLevel = mbTilesFileArchive.getMaxZoomLevel();
mMinimumZoomLevel = mbTilesFileArchive.getMinZoomLevel();
mName = mbTilesFileArchive.getName();
mDescription = mbTilesFileArchive.getDescription();
mAttribution = mbTilesFileArchive.getAttribution();
mBoundingBox = mbTilesFileArchive.getBounds();
mCenter = mbTilesFileArchive.getCenter();
}
}
/**
* Reads and opens a MBTiles file given by url and loads its tiles into this layer.
*/
private void initialize(String url, final Context context) {
initialize(getFile(url, context));
}
private File getFile(String url, final Context context) {
if (context != null) {
//we assume asset here
AssetManager am = context.getAssets();
InputStream inputStream;
try {
inputStream = am.open(url);
return createFileFromInputStream(inputStream,
Environment.getExternalStorageDirectory() + File.separator + url);
} catch (IOException e) {
Log.e(TAG, "MBTiles file not found in assets: " + e.toString());
return null;
}
}
try {
return new File(url);
} catch (Exception e) {
Log.e(TAG, "can't load MBTiles: " + e.toString());
return null;
}
}
@Override
public void detach() {
if (mbTilesFileArchive != null) {
mbTilesFileArchive.close();
mbTilesFileArchive = null;
}
}
@Override
public CacheableBitmapDrawable getDrawableFromTile(final MapTileDownloader downloader,
final MapTile aTile, boolean hdpi) {
if (mbTilesFileArchive != null) {
InputStream stream = mbTilesFileArchive.getInputStream(this, aTile);
if (stream != null) {
CacheableBitmapDrawable result =
downloader.getCache().putTileStream(aTile, stream, null);
if (result == null) {
Log.d(TAG, "error reading stream from mbtiles");
}
return result;
}
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy