2

I’m having trouble referencing resources in a dynamic module as a URI.

Something like this:

android.resource://com.redback.dynamic_module/raw/cool_video

doesn’t seem to be valid.

I’m able to load the dynamic feature module and instantiate a class from the base module without drama, and can even reference other raw resources within the dynamic module using an AssetFileDescriptor which is then given to a MediaPlayer like so:

// Playing a raw sound works fine

val soundRawResId = dynamicModuleResourceProvider.coolSound() // sound file is a raw resource in the dynamic feature module
val asset: AssetFileDescriptor = resources.openRawResourceFd(resId)
mediaPlayer.setDataSource(asset.fileDescriptor, asset.startOffset, asset.length) }
mediaPlayer.prepareAsync() 

// Sound plays!

So the module and the resources seem to be loaded ok.

However, I also need to feed some raw resources into a VideoView. For this I need to generate a URI:

val videoRawResId = dynamicModuleResourceProvider.coolVideo()

val uri = Uri.Builder()
                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
                .authority(resources.getResourcePackageName(resId))
                .appendPath(resources.getResourceTypeName(resId))
                .appendPath(resources.getResourceEntryName(resId))
                .build()

// This builds a uri that looks like this: 

/// `android.resource://com.redback.dynamic_module/raw/cool_video`

// But throws an exception:

// Couldn't open android.resource://com.redback.dynamic_module/raw/cool_video
    java.io.FileNotFoundException: No resource found for: android.resource://com.redback.dynamic_module/raw/cool_video

I tried hardcoding a couple of variations on the URI:

android.resource://com.redback/raw/cool_video

android.resource://dynamic_module/raw/cool_video

but to no avail...

This VideoView was working no problems before moving the resources to the dynamic on-demand feature module, and still works fine if I use a video from the base module. Which suggests to me that perhaps the URI just needs to be constructed differently?

The workaround for the moment is to write the resource to a file and give the file to the VideoView.. which is, of course, less than ideal, but demonstrates that the resource is loaded and accessible.

            val name = resources.getResourceEntryName(resId)
            val file = File(context.cacheDir, name)
            if (!file.exists()) {
                val resourceStream = resources.openRawResource(resource.res)
                copyStreamToFile(resourceStream, file)
            }

            setVideoPath(file.absolutePath)

The dynamic module is called ‘dynamic_module’ and package id (in the AndroidManifest) is the same as the base module: ‘com.redback`

shredder
  • 1,438
  • 13
  • 12

1 Answers1

2

Answer from Google Developer Relations fixed the problem:

val uri = Uri.Builder()
                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
                .authority(context.getPackageName()) // Look up the resources in the application with its splits loaded
                .appendPath(resources.getResourceTypeName(resId))
                .appendPath(String.format("%s:%s", resources.getResourcePackageName(resId), resources.getResourceEntryName(resId))) // Look up the dynamic resource in the split namespace.
                .build()
shredder
  • 1,438
  • 13
  • 12