Android 数据绑定:为混淆的 AAR 生成了错误的 BR class
Android Data Binding: Wrong BR class generated for obfuscated AAR
我想提供一个使用 Android 数据绑定的混淆 AAR 库。当我从测试应用程序中使用该库时,只要该库未被 ProGuard 缩小,一切都可以正常工作。但是,在启用 ProGuard 之后,测试应用程序不再编译,因为无法找到生成的数据绑定 classes 中的 BR 字段。
由于找不到关于此 "specific" 主题的任何官方文档,我试图了解 Android 数据绑定背后的魔力。机制好像是这样的(如有错误请指正):
- 为了在 AAR 库中使用数据绑定,嵌入应用程序也必须启用数据绑定。
- 这是因为包含数据绑定指令的布局资源未经修改就包含在 AAR 中。
- 因此,嵌入应用程序有责任为库中的布局生成相应的数据绑定 classes。 (这就是为什么 lib 的视图模型 classes 不能被混淆,顺便说一句。)
- Android 数据绑定生成器面临的挑战是区分库和嵌入应用程序的包名称:库的 BR class 必须在库的包中生成(例如com.example.lib.databinding),因为这个 class 是从库的视图模型 classes 访问的。另一方面,嵌入应用程序的 BR class 通常应在应用程序包内生成 (com.example.app.databinding)。
这正是我的问题开始的地方。我不知道 Android 能完全应对这一挑战,我只知道在我的情况下,它适用于未混淆的库,而不适用于混淆的库。当我查看嵌入应用程序的生成源时,我看到:
- 使用未混淆的库时,BR 和所有 *Binding.java classes 都在库的包中生成,应用程序编译。
- 使用混淆库时,BR 和所有 *Binding.java classes 都在应用程序包中生成。更糟糕的是,BR 仅包含 XML 资源中模型变量名称的常量,而不包含视图模型 classes 中的属性。因此,该应用程序无法编译。
- 我试图在 XML 声明中将数据绑定 classes 的包明确设置为 lib 的包,但这并没有解决不完整的 BR class.
我不知道这些差异从何而来,我已经担心唯一的解决方案可能是从库中删除我所有不错的数据绑定内容...是否有人有过类似的经历并可以给我提示,请问?
这些是我已经添加到我的库中的 ProGuard 异常:
-keep public class **.BR { public *; }
-keep public class **.BR$* { public *; }
-keepclassmembers class **.BR$* {
public static <fields>;
}
-keepclassmembers class **.R$* {
public static <fields>;
}
-keep class android.databinding.** { *; }
-keep class * extends android.databinding.** { *; }
-keep class com.example.lib.databinding.** { *; }
同时我设法做到了 运行,但是 "solution" 太奇怪了,我真的不想把它带到一个生产版本...
比较混淆后和未混淆的库的 AAR 文件时,我注意到未混淆的 classes.jar 包含以下三个文件:
- /com/example/lib/com.example.lib-br.bin
- /com/example/lib/com.example.lib-layoutinfo.bin
- /com/example/lib/com.example.lib-setter_store.bin
这些二进制文件包含我的一些数据绑定 class 名称,显然对代码生成过程很重要。我只是尝试将这些文件复制到我的混淆 AAR 的相应位置并且......它成功了!!!
但这不可能是最终的解决方案。如果我可以说服 ProGuard 将这些非 class 文件简单地保留在 classes.jar 中,至少它会比应对更可靠。任何想法如何做到这一点?
如果能得到一些关于这种机制背景的信息,以及是否有可能避免这种丑陋的低级操作来解决一个实际上应该是标准的问题,我将不胜感激。
提前感谢您的回答!
显然 Google 已经解决了 Gradle 插件 2.3.0 的问题,参见 https://code.google.com/p/android/issues/detail?id=229684。
我想提供一个使用 Android 数据绑定的混淆 AAR 库。当我从测试应用程序中使用该库时,只要该库未被 ProGuard 缩小,一切都可以正常工作。但是,在启用 ProGuard 之后,测试应用程序不再编译,因为无法找到生成的数据绑定 classes 中的 BR 字段。
由于找不到关于此 "specific" 主题的任何官方文档,我试图了解 Android 数据绑定背后的魔力。机制好像是这样的(如有错误请指正):
- 为了在 AAR 库中使用数据绑定,嵌入应用程序也必须启用数据绑定。
- 这是因为包含数据绑定指令的布局资源未经修改就包含在 AAR 中。
- 因此,嵌入应用程序有责任为库中的布局生成相应的数据绑定 classes。 (这就是为什么 lib 的视图模型 classes 不能被混淆,顺便说一句。)
- Android 数据绑定生成器面临的挑战是区分库和嵌入应用程序的包名称:库的 BR class 必须在库的包中生成(例如com.example.lib.databinding),因为这个 class 是从库的视图模型 classes 访问的。另一方面,嵌入应用程序的 BR class 通常应在应用程序包内生成 (com.example.app.databinding)。
这正是我的问题开始的地方。我不知道 Android 能完全应对这一挑战,我只知道在我的情况下,它适用于未混淆的库,而不适用于混淆的库。当我查看嵌入应用程序的生成源时,我看到:
- 使用未混淆的库时,BR 和所有 *Binding.java classes 都在库的包中生成,应用程序编译。
- 使用混淆库时,BR 和所有 *Binding.java classes 都在应用程序包中生成。更糟糕的是,BR 仅包含 XML 资源中模型变量名称的常量,而不包含视图模型 classes 中的属性。因此,该应用程序无法编译。
- 我试图在 XML 声明中将数据绑定 classes 的包明确设置为 lib 的包,但这并没有解决不完整的 BR class.
我不知道这些差异从何而来,我已经担心唯一的解决方案可能是从库中删除我所有不错的数据绑定内容...是否有人有过类似的经历并可以给我提示,请问?
这些是我已经添加到我的库中的 ProGuard 异常:
-keep public class **.BR { public *; }
-keep public class **.BR$* { public *; }
-keepclassmembers class **.BR$* {
public static <fields>;
}
-keepclassmembers class **.R$* {
public static <fields>;
}
-keep class android.databinding.** { *; }
-keep class * extends android.databinding.** { *; }
-keep class com.example.lib.databinding.** { *; }
同时我设法做到了 运行,但是 "solution" 太奇怪了,我真的不想把它带到一个生产版本...
比较混淆后和未混淆的库的 AAR 文件时,我注意到未混淆的 classes.jar 包含以下三个文件:
- /com/example/lib/com.example.lib-br.bin
- /com/example/lib/com.example.lib-layoutinfo.bin
- /com/example/lib/com.example.lib-setter_store.bin
这些二进制文件包含我的一些数据绑定 class 名称,显然对代码生成过程很重要。我只是尝试将这些文件复制到我的混淆 AAR 的相应位置并且......它成功了!!!
但这不可能是最终的解决方案。如果我可以说服 ProGuard 将这些非 class 文件简单地保留在 classes.jar 中,至少它会比应对更可靠。任何想法如何做到这一点?
如果能得到一些关于这种机制背景的信息,以及是否有可能避免这种丑陋的低级操作来解决一个实际上应该是标准的问题,我将不胜感激。
提前感谢您的回答!
显然 Google 已经解决了 Gradle 插件 2.3.0 的问题,参见 https://code.google.com/p/android/issues/detail?id=229684。