从主模块访问动态特性模块的drawable文件夹中的图形。

6
我正在尝试使用动态模块分割API交付来将我的游戏应用分解为即时和可安装版本。我一直在遵循这里的Codelabs教程https://codelabs.developers.google.com/codelabs/on-demand-dynamic-delivery/index.html#0。不幸的是,它使用Kotlin编写MainActivity代码,相对于Java而言较为笼统,但如果您已经完成了Kotlin教程,仍然可以跟随。该示例包括访问“assets”功能模块中的“assets”文件夹中的文本文件,具体如下:
private const val packageName = "com.google.android.samples.dynamicfeatures.ondemand"

val assetManager = createPackageContext(packageName, 0).assets
// Now treat it like any other asset file.
val assets = assetManager.open("assets.txt")
val assetContent = assets.bufferedReader()
           .use {
               it.readText()
           }

现在我只想访问动态功能模块中可绘制文件夹中的图形文件。我将仅使用我的动态功能模块来存储大型图形,这些图形会使我超过即时应用程序下载的10 MG限制。最清洁的方法是什么?

主要“应用”模块:

enter image description here

'app'中的Java代码:

loadTexture(R.drawable.aaa_image);

Bitmap bitmap;
public void loadTexture(final int resourceId){
    bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
    ***

动态提供的“installationassets”模块:

enter image description here

仍然有Java代码在'app'中,无法到达:

 loadTexture(R.drawable.testgraphic);
 cannot resolve symbol 'testgraphic'
5个回答

9
我发现一种有效的解决方法,可以从功能模块资源中加载可绘制对象。诀窍是使用正确的模块包名称。
例如:
- 基本模块的包名称为“com.project” - 在build.gradle中定义的功能模块名为“FeatureModule” - 功能模块的包名称为“com.project.FeatureModule”
build.gradle文件中的代码如下:
dynamicFeatures = [":FeatureModule"]
Java代码。
int drawableResId = context.getResources().getIdentifier("your_drawable_name", "drawable", "com.project.FeatureModule");
context.getDrawable(drawableResId);

Reference article


2
传统上,您无法访问另一个模块的资源,只能访问原始资产(存储为原始数据)。现在显然可以,但这很混乱。然而,拆分API安排的整个重点是,您确实可以像它们是一个模块一样访问所有部分(模块)的代码和资源。我发现对于资产文件夹来说是正确的,因为您不需要为动态模块引用动态创建新上下文。我发现,如果您恰好在主要的动态即时模块资产文件夹和动态模块中具有相同标题的资产,则会从动态模块中提取它们。
然而,我仍然无法从动态模块资源(R)中提取,但我将提供一个解决方法作为自己问题的答案,直到我找到示例或得到更好的答案。您可以将图像文件放入您的动态模块的资产文件夹中,然后按如下方式提取和转换它们:
loadTextureResource("testimage.png");//include file type (.png)

Bitmap bitmap;
public void loadTextureResource(String imagename){

    ImageView mImage=new ImageView(context);
    InputStream ims;

    try {
        // get input stream
        ims = context.getAssets().open(imagename);
        // load image as Drawable
        Drawable d = Drawable.createFromStream(ims, null);
        // set image to ImageView
        mImage.setImageDrawable(d);

        bitmap = ((BitmapDrawable)mImage.getDrawable()).getBitmap();
        ***

这个源代码实验室(source codelabs.developers.google.com/codelabs/…)并不是最适合创建即时应用程序的。自从发布这个问题以来,我现在已经发现了更简单的方法,只需创建一个标记为可安装交付的模块,并将其包含在您的应用程序的安装版本中即可。希望这个模块在这种情况下不像典型的动态特性模块那样孤立,因为它随着可安装的应用程序(而不是即时应用程序)一起提供,所以希望我可以访问它的drawable。不过,我必须为它包括一个插件:'com.android.dynamic-feature',所以显然它是“动态”的。感谢评论。 - Androidcoder
我找到了答案,请见下文。 - pumnao

1

这是对@pumnao发布的答案的进一步完善,但我仍然觉得有点困惑。也许这会帮助下一个疲惫的旅行者。

如果你的应用程序/基础build.gradle文件包括以下内容:

dynamicFeatures = [':dynamicfeature']

然后,您可以像这样从dynamicfeature加载资源:
val splitManager = SplitInstallManagerFactory.create(context)
val featureName = "dynamicfeature"
val installed = splitManager.installedModules.contains(featureName)

if (installed) {
  val refreshedContext = context.createPackageContext(context.packageName, 0)
  val packageName = "${context.applicationContext.packageName}.$featureName"

  val drawableId = refreshedContext.resources.getIdentifier(
    "your_drawable_name", "drawable", packageName
  )
  val drawable = refreshedContext.getDrawable(drawableId)
}


以下是有趣的一行。请注意,我们使用applicationContextpackageName作为前缀。
val packageName = "${context.applicationContext.packageName}.$featureName"

0

这必须是一个向量路径。 对我来说,它是这样工作的。

ic_effect_oval.xml

 fun Context.moduleRes(drawable_name: String):Int{
    val refreshedContext = createPackageContext(packageName, 0)
    val packageName = "${applicationContext.packageName}.$module_name"
    return refreshedContext.resources.getIdentifier(
        drawable_name, "drawable", packageName
    )
}

图像视图

 val intRes = context.moduleRes("ic_effect_oval")
 your_ImageView.setImageResource(intRes)
 your_ImageView.setColorFilter(R.color.black)     

或者在组合函数中

 val context = LocalContext.current
 val intRes = context.moduleRes("ic_effect_oval")
   Icon(
       modifier = Modifier
       .size(100.dp),
       painter = painterResource(id = intRes),
       contentDescription = animDescription,
       tint = Color.Blue
   )

0

com.android.application 模块不应访问 com.android.dynamic-feature 模块的资源,因为动态特性模块的资源表对应用程序不可访问。


似乎是可能的,可以看下面的答案。 - pumnao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接