背景
我发现了Android 11的这些新类(ResourcesLoader和ResourcesProvider),我认为它们可以让你为整个应用程序提供自己的资源加载,这可以帮助你更喜欢来自云的字符串(如Lokalise和Crowdin)、加载主题等
问题
我找不到任何关于如何使用它们的例子,也找不到我所发现的是否正确。
我发现的关于它的唯一一件事是从这篇缓存的";驯服Android资源和布局充气器用于字符串操作":
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库中尝试一下,它提供了Resources的一个实例(在这里写了关于这个的)。
遗憾的是,我一开始就陷入了困境,无法找到如何使用它来为它提供这个实例。
这似乎是一个罕见的用例和新类,几乎没有人愿意写它。即使是关于我从2020年发现的文章,它也被删除了,我不得不使用它的缓存版本…
问题
- 这些类确实可以用于动态提供资源(字符串/主题)的目的吗
- 它能和Lokalise一起使用吗?这样我就可以给它一个SDK的实例了
- 是否有这些类的支持库,以便在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)
}
}
如何使用ResourcesLoader/ResourceProvide?
- 创建编译的资源。例如,您可以使用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 "drawableyour_res_name.xml" -o "drawable"
./aapt2 link -o unsigned.apk -I "android.jar" -R "drawableyour_res_name_drawable.xml.flat" --manifest AndroidManifest.xml -v
AndroidManifest.xml应该具有相同的包名称,以便正确使用您的主应用程序。你可以在sdk文件夹中找到android.jar、aapt、aapt2文件。关于您可以阅读的所有标志->aapt-h,aapt2-h
AndroidStudio IDE
示例-构建apk的步骤:
- 创建一个空项目
- 将正确的包名称添加到AndroidManifest.xml
<manifest package="your package">
删除不必要的标签
<application android:label, android:icon, etc...>
- 将您的资源添加到项目中/res文件夹
- 清除所有不必要的资源
- 从build.gradle文件中删除所有依赖项
plugins {
... //your settings
}
android {
...//your settings
}
dependencies {
}
- 构建->构建APK
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之前使用?
在以前的API中不能使用ResourcesLoader。