package org.osmdroid.tileprovider.modules; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.util.Log; import org.osmdroid.api.IMapView; import org.osmdroid.tileprovider.MapTile; import org.osmdroid.tileprovider.tilesource.ITileSource; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import java.util.HashSet; import java.util.Set; /** * This is the OSMdroid style database provider. It's an extremely simply sqlite database schema. * CREATE TABLE tiles (key INTEGER PRIMARY KEY, provider TEXT, tile BLOB) * where the key is the X/Y/Z coordinates bitshifted using the following algorithm * key = ((z << z) + x << z) + y; * @see SqlTileWriter */ public class DatabaseFileArchive implements IArchiveFile { public static final String TABLE="tiles"; public static final String COLUMN_PROVIDER = "provider"; public static final String COLUMN_TILE = "tile"; public static final String COLUMN_KEY = "key"; static final String[] tile_column = {"tile"}; private SQLiteDatabase mDatabase; public DatabaseFileArchive(){} private DatabaseFileArchive(final SQLiteDatabase pDatabase) { mDatabase = pDatabase; } public static DatabaseFileArchive getDatabaseFileArchive(final File pFile) throws SQLiteException { return new DatabaseFileArchive(SQLiteDatabase.openDatabase(pFile.getAbsolutePath(), null, SQLiteDatabase.OPEN_READONLY & SQLiteDatabase.NO_LOCALIZED_COLLATORS)); } public Set<String> getTileSources(){ Set<String> ret = new HashSet<String>(); try { final Cursor cur = mDatabase.rawQuery("SELECT distinct provider FROM " + TABLE, null); while(cur.moveToNext()) { ret.add(cur.getString(0)); } cur.close(); } catch (final Exception e) { Log.w(IMapView.LOGTAG,"Error getting tile sources: ", e); } return ret; } @Override public void init(File pFile) throws Exception { mDatabase=SQLiteDatabase.openDatabase(pFile.getAbsolutePath(), null, SQLiteDatabase.OPEN_READONLY | SQLiteDatabase.NO_LOCALIZED_COLLATORS); } public byte[] getImage(final ITileSource pTileSource, final MapTile pTile) { try { byte[] bits=null; final String[] tile = {COLUMN_TILE}; final long x = (long) pTile.getX(); final long y = (long) pTile.getY(); final long z = (long) pTile.getZoomLevel(); final long index = ((z << z) + x << z) + y; final Cursor cur = mDatabase.query(TABLE, tile, COLUMN_KEY+" = " + index + " and "+COLUMN_PROVIDER+" = '" + pTileSource.name() + "'", null, null, null, null); if(cur.getCount() != 0) { cur.moveToFirst(); bits = (cur.getBlob(0)); } cur.close(); if(bits != null) { return bits; } } catch(final Throwable e) { Log.w(IMapView.LOGTAG,"Error getting db stream: " + pTile, e); } return null; } @Override public InputStream getInputStream(final ITileSource pTileSource, final MapTile pTile) { try { InputStream ret = null; byte[] bits=getImage(pTileSource, pTile); if (bits!=null) ret = new ByteArrayInputStream(bits); if(ret != null) { return ret; } } catch(final Throwable e) { Log.w(IMapView.LOGTAG,"Error getting db stream: " + pTile, e); } return null; } @Override public void close() { mDatabase.close(); } @Override public String toString() { return "DatabaseFileArchive [mDatabase=" + mDatabase.getPath() + "]"; } }