I’m implementing a cloud media provider by subclassing Android’s CloudMediaProvider
to support a custom cloud storage (in my case, for OneDrive-like functionality). The query and preview operations work as expected—the PhotoPicker calls my overridden methods such as onQueryMedia()
and onOpenPreview()
, and I see appropriate log output.
However, when a user selects a media item to "open" (i.e. to retrieve the full-resolution file), the system does not call my overridden onOpenMedia()
method at all. Instead, the PhotoPicker (in SelectedMediaPreloader
) fails with the following exception:
Could not open FileDescriptor for content://media/picker/0/ch.nikleberg.bettershared.cloudpicker/media/ID_1 (Ask Gemini)
java.io.FileNotFoundException: File not found for uri: content://media/picker/0/ch.nikleberg.bettershared.cloudpicker/media/ID_1
at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:151)
at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:780)
at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:2053)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1868)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1784)
at com.android.providers.media.photopicker.SelectedMediaPreloader.openFileDescriptor(SelectedMediaPreloader.java:262)
at com.android.providers.media.photopicker.SelectedMediaPreloader.-$$Nest$mopenFileDescriptor(SelectedMediaPreloader.java:0)
at com.android.providers.media.photopicker.SelectedMediaPreloader$4.run(SelectedMediaPreloader.java:214)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at java.lang.Thread.run(Thread.java:1012)
at com.android.providers.media.photopicker.SelectedMediaPreloader$5$1.run(SelectedMediaPreloader.java:334)
SelectedMediaPreloader com...ndroid.providers.media.module D openFileDescriptor() DONE, took 12 ms, content://media/picker/0/ch.nikleberg.bettershared.cloudpicker/media/ID_1
SelectedMediaPreloader com...ndroid.providers.media.module D Preloaded 1 (of 1) items
What I’ve Tried:
Cursor
colums when onQueryMedia()
is called, we can return a MEDIA_STORE_URI
. This should be NULL
for cloud-only files. I tried to set this to an arbitrary content uri, but the exception did not change.CloudMediaProvider
in a plain ContentProvider
and added logs to every possible call. The calls for preview functionality show up in logcat. Calls for the actual retrieval of the media are none to be found. I expected a call to query()
or to openTypedAssetFile()
.To answer my own question: I had a slight error in how the CloudMediaProvider
was returning a MEDIA_COLLECTION_ID
which prevented android from fully enabling the provider. If fully enabled it forwards requests to the internal photo picker URI: content://media/picker/0/ch.nikleberg.bettershared.cloudpicker/media/ID_1
to the actual URI of the provider: content://ch.nikleberg.bettershared.cloudpicker/media/ID_1
.
The reason that android did not fully enable my provider was, because there are two different ways of returning the required MEDIA_COLLECTION_ID
. When called in onGetMediaCollectionInfo()
one has to add the id to the Bundle
with the key CloudMediaProviderContract.MediaCollectionInfo.MEDIA_COLLECTION_ID
. But for calls to onQueryAlbums()
and onQueryMedia()
one has to use the slightly different key CloudMediaProviderContract.EXTRA_MEDIA_COLLECTION_ID
.