Last active
December 12, 2015 01:58
-
-
Save thesjg/4694437 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Needs a tile layer, something like (for Leaflet) .. | |
* | |
* var tl = L.tileLayer("content://com.pahasapatrails.m.tiles/{style}/{z}/{x}/{y}.png", | |
* { style: "XXX", minZoom: 9, maxZoom: 13, tms: true }); | |
* map.addLayer(tl); | |
* | |
* | |
* Also needs a provider entry under the application tag in the Android | |
* Manifest, something like the following .. | |
* | |
* <provider android:name="com.pahasapatrails.m.TileContentProvider" | |
* android:authorities="com.pahasapatrails.m.tiles" /> | |
* | |
*/ | |
package com.pahasapatrails.m; | |
import java.io.BufferedOutputStream; | |
import java.io.File; | |
import java.io.FileNotFoundException; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import android.content.ContentProvider; | |
import android.content.ContentValues; | |
import android.database.Cursor; | |
import android.database.sqlite.SQLiteDatabase; | |
import android.net.Uri; | |
import android.os.ParcelFileDescriptor; | |
import android.util.Log; | |
public class TileContentProvider extends ContentProvider { | |
// private String databaseList[] = null; | |
// private SQLiteDatabase databases[]; | |
private SQLiteDatabase handle; | |
private String query = "SELECT tile_data FROM images INNER JOIN map ON " + | |
"images.tile_id = map.tile_id WHERE zoom_level = ? " + | |
" AND tile_column = ? AND tile_row = ?"; | |
/* | |
* onCreate is called when the application manifest is read at startup time. | |
* Do one-time initialization magic here, the provider will keep running | |
* so we only have to open each database once and cache the handle. | |
*/ | |
@Override | |
public boolean onCreate() | |
{ | |
/* | |
* Delete the cache, just in case anything stuck around somehow | |
*/ | |
File cacheDir = this.getContext().getCacheDir(); | |
String[] children = cacheDir.list(); | |
for (int i = 0; i < children.length; i++) { | |
new File(cacheDir, children[i]).delete(); | |
} | |
/* | |
* Setup the database connection(s) | |
* | |
* XXX: Hardcoded database filename | |
*/ | |
String dbname = "PahaSapaTrailscomMobile9-13.mbtiles"; | |
File dbfile = this.getContext().getDatabasePath(dbname); | |
handle = SQLiteDatabase.openOrCreateDatabase(dbfile, null); | |
return (true); | |
} | |
/* | |
* Query the MBTiles DB and return content-type | |
* | |
* XXX: Does this ever even get called by a webview? | |
*/ | |
@Override | |
public String getType(Uri uri) | |
{ | |
Log.e("error", "TileContentProvider: getType: " + uri); | |
return ("image/png"); | |
} | |
/* | |
* If only concerned with HONEYCOMB and later then openFile could simply | |
* use simpleQueryForBlobFileDescriptor and return that descriptor -- | |
* at least ostensibly, untested. | |
*/ | |
@Override | |
public ParcelFileDescriptor openFile(Uri uri, String mode) | |
throws FileNotFoundException | |
{ | |
if (mode != "r") | |
throw new FileNotFoundException("mode can only be of type read-only"); | |
/* | |
* Parse uri, path looks like /scheme/zoom/x/y.png | |
* | |
* XXX: Assumes png | |
*/ | |
String path[] = uri.getPath().split("/"); | |
String params[] = { path[2], path[3], path[4].replace(".png", "") }; | |
String outfilename = params[0] + "-" + params[1] + "-" + params[2] + ".png"; | |
try { | |
File file = new File(this.getContext().getCacheDir(), outfilename); | |
Cursor cursor = handle.rawQuery(query, params); | |
if (!cursor.moveToFirst()) | |
throw new FileNotFoundException("No results from query"); | |
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); | |
bos.write(cursor.getBlob(0)); | |
cursor.close(); | |
ParcelFileDescriptor ret = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); | |
bos.close(); | |
/* | |
* Unlink underneath? Actual file will *poof* once the | |
* ParcelFileDescriptor we are returning gets closed. | |
*/ | |
file.delete(); | |
handle.setTransactionSuccessful(); | |
return (ret); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
/* Return static error image instead? */ | |
throw new FileNotFoundException("Error setting up tile"); | |
} | |
} | |
/* | |
* query, delete, insert and update operations are specifically not supported, | |
* the application must download the mbtiles database files and place them | |
* in the expected data directory. | |
*/ | |
@Override | |
public Cursor query(Uri uri, String[] arg1, String arg2, String[] arg3, String arg4) | |
{ | |
throw new UnsupportedOperationException("Not supported by this provider"); | |
} | |
@Override | |
public int delete(Uri uri, String arg1, String[] arg2) | |
{ | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public Uri insert(Uri uri, ContentValues arg1) | |
{ | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public int update(Uri uri, ContentValues arg1, String arg2, String[] arg3) | |
{ | |
throw new UnsupportedOperationException(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi,
I didn't know about gist. I just tried your code and it was throwing an exception. I found that the
was the cause, so I added some validation to it :
Here's the end result in a fork : https://gist.github.com/adube/5041097
Thanks for sharing your code.