Why does my “content://” URI return a null InputStream, even though I can read from the ZipResourceFile object?

只谈情不闲聊 提交于 2021-01-29 05:10:19

问题


I'm setting up Google's APEZProvider to read .PNGs (compressed) and .MP3s (not compressed) from an APK Expansion zip file. File retrieval works just fine if I avoid the URI, and stick to "getAPKExpansionZipFile()" But when I try to retrieve my files using the "content://" API, I am getting a null InputStream. (I need the URI to satisfy the APIs of media players.)

This is for an Android app targeting API 26. In the past I was able to get the content provider working. But I've broken something. I wonder if it might be an issue with module versions not being in sync.

I've tried following a breakpoint through the APEZProvider (a subclass of ContentProvider that Google provides for this case.) The app finds the provider O.K. without any logcat error. So I think my manifest settings are correct.

At first the APEZProvider seems to initialize O.K. It even finds the zip files and correctly populates the mAPKExpansionPack private variable. But somehow when it is time to return an InputStream (in the ContentProvider superclass), I get null.

In my repository:

// This works fine
fun makeSureWeCanReadFromPack() {
     val stream = 
mExpansionPack?.getInputStream("images/species_bubo_bubo.png")
     val bitmap = BitmapFactory.decodeStream(stream)
     if (bitmap == null) {
        // This doesn't happen
        throw DodgyFileException("Couldn't read test image")
     }
}

// This throws an error
fun makeSureContentProviderIsUpAndRunning() {
    val uri = Uri.parse("content://com.company.app.provider.ZipFileContentProvider/images/species_bubo_bubo.png")
    val stream = mContext.getContentResolver().openInputStream(uri)
    val bitmap = BitmapFactory.decodeStream(stream)
    if (bitmap == null) {
        // This happens
        throw DodgyFileException("Couldn't read from content provider")
    }
}

In my Android manifest:

<provider android:authorities="com.company.app.provider.ZipFileContentProvider"
android:name="com.company.app.provider.ZipFileContentProvider"
android:exported = "true"
android:multiprocess = "true"
android:enabled = "true"
>
</provider>

EDIT: Here's the content provider: https://pastebin.com/UjMjtYCD


回答1:


Solution: I needed to change my ZIP file so that it was built with no compression, using

zip -Z store

A big clue was when I realized that Android could get an input stream from the compressed .PNG, but not asset file descriptor.

The documentation hints at this requirement but the truth is a bit elusive. I mistakenly interpretated its advice to mean that you only need to avoid compression when dealing with playback media with offsets and duration, like songs and movies. But it turns out that compression can interfere with retrieving graphics files, too.



来源:https://stackoverflow.com/questions/53997645/why-does-my-content-uri-return-a-null-inputstream-even-though-i-can-read-f

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!