1

我正在尝试使用运行时资源覆盖 (RRO) 机制来覆盖使用自定义属性和自定义命名空间的 xml 资源。在构建覆盖 APK 时,aapt2(链接)会引发属性未找到错误。

我如何知道从主应用程序到叠加层的自定义属性?
甚至可以在叠加层中使用自定义属性吗?

详细信息:
覆盖包含两个文件:

AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="de.test.simpleappoverlay">

    <overlay
        android:targetPackage="de.test.simpleapp"
        android:targetName="Test"/>
</manifest>

和 xml 文件 res/xml/my_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<MyConfig xmlns:app="http://schemas.android.com/apk/res/de.test.simpleapp"
    app:text="hello">
</MyConfig>

<!-- I also tried: xmlns:app="http://schemas.android.com/apk/res-auto" -->

应用程序在 res/values/attrs.xml 中定义属性文本:

...
<declare-styleable name="MyConfig">
    <attr name="text" format="string" />
</declare-styleable>

此外,它在 res/values/overlayable.xml 中定义了可覆盖标签:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <overlayable name="Test">
        <policy type="public">
            <item type="xml" name="my_config"/>
        </policy>
    </overlayable>
</resources>    

要构建叠加层,我这样做:

aapt2 编译 -v --dir app/src/main/res/ -o SimpleAppOverlay.flata

aapt2 链接 -v --no-resource-removal
-I ~/Library/Android/sdk/platforms/android-29/android.jar
--manifest app/src/main/AndroidManifest.xml
-o sao.apk SimpleAppOverlay.flata

这导致以下输出:

注意:包括/Users/bernd/Library/Android/sdk/platforms/android-29/android.jar
aapt2 W 09-01 14:33:06 20083 694697 ApkAssets.cpp:138] resources.arsc 在 APK '/Users/ bernd/Library/Android/sdk/platforms/android-29/android.jar' 被压缩
注意:使用包 ID 7f 链接包 'de.test.simpleappoverlay' 注意:合并存档
SimpleAppOverlay.flata 注意:合并'xml/my_config'从编译文件 app/src/main/res/xml/my_config.xml
注意:启用 pre-O 功能拆分 ID 重写 AndroidManifest.xml:
注意:写入存档 (keep_raw_values=false)
注意:将 AndroidManifest.xml 写入存档 注意:链接 app/src/main/res/xml/my_config.xml (de.test.simpleappoverlay:xml/my_config)
app/src/main/res/xml/my_config.xml:2:错误:找不到属性文本(又名 de.test.simpleappoverlay:text)
错误:链接文件资源失败。

4

3 回答 3

2

我遇到了与此类似的问题,我试图在 Android 10 中使用自定义属性覆盖应用程序并找到解决方案。需要进行两项更改:

第1部分

看起来您的应用名称是de.test.simpleapp,因此您的 my_config.xml 文件应如下所示:

<?xml version="1.0" encoding="utf-8"?>
<MyConfig xmlns:app="http://schemas.android.com/apk/prv/res/de.test.simpleapp"
    app:text="hello">
</MyConfig>

重要的部分是指定“prv/res/ app.packagename ”,因此它使用基本应用程序的命名空间作为私有属性。如果您使用了“apk/res-auto”,它将无法工作,因为它解析为您的应用程序的名称(在这种情况下是覆盖应用程序 de.test.simpleappoverlay),它不包含私有属性的定义。

第2部分

由于您现在在链接时依赖于主应用程序,因此您必须将其包含在链接命令中,并带有 a -I simpleapp.apk(或任何基本应用程序的 APK 名称)。现在您只是在 aapt2 链接步骤中包含 android.jar,它只包含“android”命名空间和属性。因此,您现在需要在包含步骤中添加您的基础应用程序,以便它可以正确链接到其命名空间和属性。

就像其他一些答案一样,这个问题在 Android 11 中消失了,但如果你像我一样被困在 Android 10 上,希望这会有所帮助。

于 2021-06-10T17:38:16.707 回答
0

前段时间,我将我的 AOSP 环境从 Android 10 切换到了 11。Google 对 Overlay 机制进行了相当多的更改。令我惊讶的是,这些更改解决了我在尝试“覆盖”自定义属性时遇到的问题。
在 Android 10 环境中,我在调试时观察到 Android XML 解析器在尝试读取上述属性时返回“null”。使用 idmap 我能够确认属性存在于覆盖层和目标应用程序中,并且它们已正确映射。
所有链接器错误也都消失了。

于 2021-03-27T16:49:16.530 回答
0

我认为当前的 RRO 实现不支持包含新 ID(至少在 Android Q 中)。关于您的错误,aapt 使用 android.jar 为您的叠加层生成 apk。由于它找不到您的新属性,因此会引发错误。为此,我相信您需要使用修改后的 android.jar,包括您的属性。一种方法是修改 AOSP 中的 Android SDK 并创建您自己的版本,然后将其用于 aapt 命令。

于 2021-02-03T10:59:46.747 回答