ckozl
ckozl

Reputation: 6761

Correct use of Android SQLiteStatement's simpleQueryForBlobFileDescriptor()

The function simpleQueryForBlobFileDescriptor() in Android's SQLiteStatement is a mystery to me. And no one seems to use it anywhere. It seems as though it would be a fast method for individual blob access and in terms of performance (if the documentation is to be believed) the combination of SQLiteStatement and Parcel should yield a very fast result when used to stream blob data out of a db. I don't know because I can't get the thing to work so that I could test... Any help with this or insight would be appreciated:

SQLiteStatement get = mDb.compileStatement(
    "SELECT blobColumn" + 
    " FROM tableName" +
    " WHERE _id = 1" +
    " LIMIT 1"
);

ParcelFileDescriptor result = get.simpleQueryForBlobFileDescriptor();
// now what?

I should probably note that I am using and only really care about Honeycomb (3.2) and thank you in advance for any insight.

Upvotes: 2

Views: 1803

Answers (1)

ckozl
ckozl

Reputation: 6761

SQLiteStatement get = mDb.compileStatement(
    "SELECT blobColumn" + 
    " FROM tableName" +
    " WHERE _id = 1" +
    " LIMIT 1"
);

ParcelFileDescriptor result = get.simpleQueryForBlobFileDescriptor();
FileInputStream fis = new FileInputStream(result.getFileDescriptor()); // read like any other

and I can verify that this is very fast for my use cases.

Where I found this particularly useful (if you need to create your own custom offline webview file cache like I did) was in the openFile override for a content provider where you can just return the descriptor straight up (or ideally override openTypedAssetFile())

examples: files is a DB helper and getFileDescriptor(String) is similar to the code above

public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, android.os.Bundle opts) throws FileNotFoundException {
    ParcelFileDescriptor pfd = files.getFileDescriptor(uri.toString());
    if (pfd != null) {
        return new AssetFileDescriptor(pfd, 0, AssetFileDescriptor.UNKNOWN_LENGTH);
    }
    return null;
}

or another great use for a similar problem: (where you want to serve custom file from a db to a webview)

private WebViewClient webViewClient = new WebViewClient() {
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {

        ParcelFileDescriptor pfd = files.getFileDescriptor(url);
        if (pfd != null) {
            return new WebResourceResponse(null, null, new FileInputStream(pfd.getFileDescriptor()));
        }

        return null; 
    }

Upvotes: 2

Related Questions