ContentResolver.openFileDescriptor() does not call ContentProvider.openFIle
Asked Answered
T

1

6

I implemented a ContentProvider by overriding openFile(...) method. Then I tested it by using ContentResolver.openFileDescriptor(...) method. As specified in the javadoc, openFileDescriptor suppose to call ContentProvider.openFile:

"...Open a raw file descriptor to access data under a URI. This is like openAssetFileDescriptor(Uri, String), but uses the underlying openFile(Uri, String) ContentProvider.openFile() method..."

The problem is the openFile() method was never called. Instead I observed that openAssetFile() was called instead. I tested it with android 4.1.2r1. When I review the source code for the android class ContentResolver (4.1.2) I see that openFileDescriptor() will just call openAssetFileDescriptor(), and I cannot find any execution path where ContentProvider.openFile() would be called at all.

Anybody has any idea where I was wrong? - Thanks

Here is my test method call:

context.getContentResolver().openFileDescriptor(bitmapUri, "r").getFileDescriptor();

My bitmapUri is something like this "content://com.myprovider.authority/filename"

Torose answered 19/11, 2013 at 19:18 Comment(4)
see whats done in openAssetFileDescriptor(), it explains everythingHopehopeful
I actually looked at openAssetFileDescriptor() as well. In some cases an AssetFileDescriptor will be created directly (such as when the Uri scheme is "File" I belive). In other cases openTypedAssetFileDescriptor will be called. In any case, I cannot find any path that results in ContentProvider.openFile beeing called. If you know it can you elaborate?Torose
look for SCHEME_CONTENTHopehopeful
Have the exact same problem. Any ideas?Midian
C
6

That seems like a bug in openFileDescriptor() to me. I ended up calling ContentResolver.openInputStream()/ContentResolver.openOutputStream(). These methods correclty call openFile() to get to the file.

Alternatively you can do something like this:

ContentResolver resolver = context.getContentResolver();
ContentProviderClient providerClient = resolver.acquireContentProviderClient(uri);
ParcelFileDescriptor descriptor = providerClient.openFile(uri, "r");

Dont forget to release ContentProviderClient.

Calv answered 9/2, 2014 at 10:8 Comment(1)
The documentation is very misleading, making it look like a bug. What happens is that calling ContentResolver.openFileDescriptor() first tries ContentProvider.openAssetFile(). If openAssetFile() fails, then it falls back to openFile(). What this means is that if your ContentProvider has implemented openAssetFile(), then openFile() will never get called. So you can either do some pass-through where openAssetFile() calls openFile() manually, or just don't implment openAssetFile(). The trick with ContentProviderClient also works.Newsdealer

© 2022 - 2024 — McMap. All rights reserved.