我的离线地图数据源格式是MBTiles。数据库有2个表: Table1名称是存储数据的首选项,如: 名称,值
表2名称是存储数据的图块,如:
tileKey,缩放,行,列,图像
然后我创建一个类
公共类MBTileSource扩展了BitmapTileSourceBase {
// Log log log log ...
private static final Logger logger = LoggerFactory
.getLogger(MBTileSource.class);
// Database related fields
public final static String TABLE_TILES = "tiles";
public final static String COL_TILES_ZOOM_LEVEL = "zoom";
public final static String COL_TILES_TILE_COLUMN = "col";
public final static String COL_TILES_TILE_ROW = "row";
public final static String COL_TILES_TILE_DATA = "image";
protected SQLiteDatabase database;
protected File archive;
// Reasonable defaults ..
public static final int minZoom = 8;
public static final int maxZoom = 15;
public static final int tileSizePixels = 256;
// Required for the superclass
public static final string resourceId = ResourceProxy.string.offline_mode;
/**
* The reason this constructor is protected is because all parameters,
* except file should be determined from the archive file. Therefore a
* factory method is necessary.
*
* @param minZoom
* @param maxZoom
* @param tileSizePixels
* @param file
*/
protected MBTileSource(int minZoom, int maxZoom, int tileSizePixels,
File file, SQLiteDatabase db) {
super("sqlite", resourceId, minZoom, maxZoom, tileSizePixels, ".png");
archive = file;
database = db;
}
/**
* Creates a new MBTileSource from file.
*
* Parameters minZoom, maxZoom en tileSizePixels are obtained from the
* database. If they cannot be obtained from the DB, the default values as
* defined by this class are used.
*
* @param file
* @return
*/
public static MBTileSource createFromFile(File file) {
SQLiteDatabase db;
int flags = SQLiteDatabase.NO_LOCALIZED_COLLATORS
| SQLiteDatabase.OPEN_READONLY;
// int value;
int minZoomLevel=minZoom;
int maxZoomLevel=maxZoom;
int tileSize = tileSizePixels;
InputStream is = null;
// Open the database
db = SQLiteDatabase.openDatabase(file.getAbsolutePath(), null, flags);
// Get the minimum zoomlevel from the MBTiles file
Cursor pCursor = db.rawQuery("SELECT * FROM preferences;", null);
try {
if (pCursor.getCount() != 0) {
pCursor.moveToFirst();
do {
String name=pCursor.getString(pCursor.getColumnIndex("name"));
if(name.equalsIgnoreCase("map.minZoom")){
minZoomLevel=pCursor.getInt(pCursor.getColumnIndex("value"));
}else if(name.equalsIgnoreCase("map.maxZoom")){
maxZoomLevel=pCursor.getInt(pCursor.getColumnIndex("value"));
}else if(name.equalsIgnoreCase("map.tileSideLength")){
tileSize=pCursor.getInt(pCursor.getColumnIndex("value"));
}
} while (pCursor.moveToNext());
}
pCursor.close();
} catch (Exception e) {
// TODO: handle exception
}
return new MBTileSource(minZoomLevel, maxZoomLevel, tileSize, file, db);
}
public InputStream getInputStream(MapTile pTile) {
try {
InputStream ret = null;
final String[] tile = { COL_TILES_TILE_DATA };
final String[] xyz = {
Integer.toString(pTile.getX()),
Double.toString(Math.pow(2, pTile.getZoomLevel())
- pTile.getY() - 1),
Integer.toString(pTile.getZoomLevel()) };
final Cursor cur = database.query(TABLE_TILES, tile,
"col=? and row=? and zoom=?", xyz, null,
null, null);
if (cur.getCount() != 0) {
cur.moveToFirst();
ret = new ByteArrayInputStream(cur.getBlob(0));
}
cur.close();
if (ret != null) {
return ret;
}
} catch (final Throwable e) {
logger.warn("Error getting db stream: " + pTile, e);
}
return null;
}
}
它可以很好地显示离线地图。只有一个问题是:渲染速度非常慢
有什么建议吗? 感谢。
答案 0 :(得分:1)
您不想扩展BitmapTileSourceBase
。您想要创建一个包含MapTileFileArchiveProvider
和您自己的IArchiveFile
的切片提供程序链。有关支持数据库IArchiveFile
的示例,请参阅DatabaseFileArchive.java。
如果您仍然遇到速度问题,您应该运行探查器以查看减速的位置。
答案 1 :(得分:0)
你的mbtiles文件上有任何索引吗? Kurtzmarc的答案会起作用,但这条路走得很乱。我已经开始工作,性能还可以,但我想要一个更清洁的解决方案。我想从XYTileSource开始并从那里继续前进。