如何使用ResourcesProvider/ResourcesLoader类动态加载资源?

4

背景

我发现在 Android 11 中有这些新的类 (ResourcesLoaderResourcesProvider),我认为它们可以让你为整个应用程序提供自己的资源加载,这可以帮助您优先使用云端字符串(例如在 Lokalise 和 Crowdin 中),加载主题等...

问题

我找不到如何使用它们的任何示例,并且不确定我所发现的是否正确。

唯一与此相关的是来自“Taming Android Resources and LayoutInflater for string manipulation”文章中的缓存文章:

Android 11 引入了通过 ResourcesLoader 和 ResourcesProvider 动态加载资源的能力。这不仅限于字符串文件,还允许动态加载可绘制图像和其他资源文件。使用这些类的近似方法如下:

val provider = ResourcesProvider.loadFromDirectory("/somepath/", null) // or loadFromApk() 
val loader = ResourcesLoader() loader.addProvider(provider) resources.addLoaders(loader) // Application resources 

目前该API没有提供适当的样例,且仅在Android 11及以上版本可用,因此大部分应用程序要使用此API还需要很长时间。

我发现的

我想尝试使用Lokalise库,该库提供了资源实例(在此写有关其的文章)。

可惜,我卡在了最开始的阶段,无法找到如何使用它以向其提供此实例。

似乎这是一个罕见的用例和新类,几乎没有人写过有关它的内容。即使是2020年发表的一篇文章,也被删除了,我不得不使用其缓存版本...

问题

  1. 这些类可以用于提供动态资源(字符串/主题)的目的吗?
  2. 它可以与Lokalise配合使用,以便我提供其SDK的实例吗?
  3. 是否有这些类的支持库,以便在Android API 30之前使用它们?

编辑:在此处,他们使用加载APK文件以将其资源作为最高优先级使用的示例:

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        
        val file = File(cacheDir, "overrideResources")
        unzip(ZipInputStream(assets.open("override.apk")), file)
  
        val rl = ResourcesLoader()
        rl.addProvider(ResourcesProvider.loadFromDirectory(file.path, null))
        resources.addLoaders(rl)
    }
}
1个回答

1

如何使用ResourcesLoader/ResourceProvide?


  1. 创建编译资源。您可以使用aapt或aapt2等工具。

aapt示例:

./aapt package -f -M AndroidManifest.xml -S ./res -I android.jar -F unsigned.apk

(./res目录必须具有结构层次,例如./res/drawable、./res/layout等,其中包含资源)

使用aapt2的示例:

./aapt2 compile "drawable\your_res_name.xml" -o "drawable"
./aapt2 link -o unsigned.apk -I "android.jar" -R "drawable\your_res_name_drawable.xml.flat" --manifest AndroidManifest.xml -v

AndroidManifest.xml应该与您的主应用程序具有相同的包名称,以便正确工作。 您可以在sdk文件夹中找到android.jar、aapt和aapt2文件。 关于所有标志,您可以阅读-> aapt -h,aapt2 -h

AndroidStudio IDE

示例 - 构建apk的步骤:

  1. 创建一个空项目;
  2. 在AndroidManifest.xml中添加正确的包名称。
<manifest package="your package">

去除不必要的标签

<application android:label, android:icon, etc...>
  1. 将您的资源添加到项目的./res文件夹中;
  2. 删除所有不必要的资源;
  3. 从build.gradle文件中删除所有依赖项。
plugins {
... //your settings
}
android {
...//your settings
}
dependencies {
}
  1. 构建 -> 构建APK。

  1. 然后,您将获得已编译的资源,接着: (或者如何在您的应用程序中动态使用已编译的资源)
File f = new File("unsigned.apk");

ParcelFileDescriptor pfd = ParcelFileDescriptor.open(f, MODE_READ_ONLY);

ResourcesProvider rp = ResourcesProvider.loadFromApk(pfd);

ResourcesLoader rl = new ResourcesLoader();
rl.addProvider(rp);

getResouces().addLoaders(rl);

完成了!您的应用程序中有资源。您可以动态下载资源。

要读取资源,您可以使用:

getResouces().getIdentifier("your_res_name", "drawable", getPackageName());

这些类是否有支持库,以便在 Android API 30 之前使用?

ResourcesLoader 不能在之前的 API 中使用。


IDE不能代替这个吗? - android developer
可以。aapt,aapt2只是一个例子。 - Yevhenii Buhera
你能否请逐步解释一下通过IDE完成所有操作的替代方法,就像你为aapt2命令所做的那样? - android developer
aapt2看起来更容易 - 阅读相关信息 - https://developer.android.com/studio/command-line/aapt2 - Yevhenii Buhera
请解释一下,这个注释看起来非常简短和不清楚。这里需要进行哪些配置和设置? - android developer
显示剩余3条评论

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