仅使用 Proguard:无法初始化 DaoConfig => ArrayIndexOutOfBoundsException

Only using Proguard: Could not init DaoConfig => ArrayIndexOutOfBoundsException

提问人:muetzenflo 提问时间:2/3/2017 最后编辑:muetzenflo 更新时间:10/28/2021 访问量:3287

问:

我正在使用以下 ProGuard 规则:

-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao { *; }
-keep class **$Properties

-keep class org.greenrobot.greendao.**
-keepclassmembers class org.greenrobot.greendao.** { *; }

# If you do not use SQLCipher:
-dontwarn org.greenrobot.greendao.database.**

# If you do not use RxJava:
-dontwarn rx.**

启动应用程序时,我收到以下崩溃日志:

java.lang.RuntimeException: Unable to create application my.app.package.MyApplication: org.greenrobot.greendao.DaoException: Could not init DAOConfig
   at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4569)
   at android.app.ActivityThread.access$1500(ActivityThread.java:148)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:135)
   at android.app.ActivityThread.main(ActivityThread.java:5272)
   at java.lang.reflect.Method.invoke(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:372)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:909)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:704)
Caused by: org.greenrobot.greendao.DaoException: Could not init DAOConfig
   at org.greenrobot.greendao.internal.DaoConfig.(Unknown Source)
   at org.greenrobot.greendao.AbstractDaoMaster.registerDaoClass(Unknown Source)
   at my.app.package.database.model.DaoMaster.(Unknown Source)
   at my.app.package.database.model.DaoMaster.(Unknown Source)
   at my.app.package.ZamgApplication.onCreate(Unknown Source)
   at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1011)
   at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4566)
   at android.app.ActivityThread.access$1500(ActivityThread.java:148) 
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
   at android.os.Handler.dispatchMessage(Handler.java:102) 
   at android.os.Looper.loop(Looper.java:135) 
   at android.app.ActivityThread.main(ActivityThread.java:5272) 
   at java.lang.reflect.Method.invoke(Native Method) 
   at java.lang.reflect.Method.invoke(Method.java:372) 
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:909) 
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:704) 
Caused by: java.lang.ArrayIndexOutOfBoundsException: length=5; index=6
   at org.greenrobot.greendao.internal.DaoConfig.reflectProperties(Unknown Source)
   at org.greenrobot.greendao.internal.DaoConfig.(Unknown Source) 
   at org.greenrobot.greendao.AbstractDaoMaster.registerDaoClass(Unknown Source) 
   at my.app.package.database.model.DaoMaster.(Unknown Source) 
   at my.app.package.database.model.DaoMaster.(Unknown Source) 
   at my.app.package.ZamgApplication.onCreate(Unknown Source) 
   at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1011) 
   at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4566) 
   at android.app.ActivityThread.access$1500(ActivityThread.java:148) 
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
   at android.os.Handler.dispatchMessage(Handler.java:102) 
   at android.os.Looper.loop(Looper.java:135) 
   at android.app.ActivityThread.main(ActivityThread.java:5272) 
   at java.lang.reflect.Method.invoke(Native Method) 
   at java.lang.reflect.Method.invoke(Method.java:372) 
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:909) 
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:704) 

在没有 ProGuard 的情况下编译应用程序时,一切正常。

我在这里缺少任何配置吗?我找不到任何关于谷歌的东西......

安卓 android-proguard greendao greendao-generator

评论

1赞 muetzenflo 2/13/2017
fwiw:经过 2 天的挖掘,我决定将数据库切换到 realm.io

答:

3赞 Mike Laren 2/7/2017 #1

似乎指令:

-keep class org.greenrobot.greendao.**

未应用。正如您在日志中看到的,这些行如下:

at org.greenrobot.a.c.a.a(Unknown Source)
at org.greenrobot.a.c.a.(Unknown Source) 
at org.greenrobot.a.b.a(Unknown Source) 

显示下面的类正在被混淆,而您的 ProGuard 指令正在告诉(或应该告诉)ProGuard 保持它们不变。要解决此问题,请确保在 Android 配置部分中正确引用了定义此问题的 ProGuard 规则文件:org.greenrobot.greendaoproguardFiles

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

并且您的发布配置使用相同的文件。proguard-rules.pro

评论

0赞 muetzenflo 2/7/2017
谢谢,我更新了我的规则集,以保留 greendao 的几乎所有内容。日志文件现在有点冗长,但错误不断发生。我用新的日志和规则更新了我的问题。
14赞 tesla1984 2/15/2017 #2

你是项目中的类吗?
如果没有,你像这样放你的类
的包
keepEntitykeepEntity
-keep class com.xxx.xxx.model.* {*;}

评论

0赞 muetzenflo 2/15/2017
是的,我愿意。出于测试目的,我甚至保持了我的整个数据库包不被混淆,但无济于事。由于经过一周的尝试和搜索后我无法解决这个问题,所以我改用了 realm.io。他们在库中拥有所有 proguard 规则,开发人员无需做任何事情。
0赞 Qing 12/28/2021
完美地解决了我的问题!这个 proguard 规则应该添加到 greendao 官方文档中推荐的 proguard 规则中。greenrobot.org/greendao/documentation/......
1赞 Devendra Singh 2/17/2017 #3

你可以试试这个

-dontwarn org.greenrobot.greendao.**
-keepclassmembers class * extends de.greenrobot.dao.AbstractDao {

}
-keep class **$Properties

使用更新版本

apply plugin: 'org.greenrobot.greendao'

compile 'org.greenrobot:greendao:3.2.0'

此处此处以及 StackOverflow 上列出了相同的问题

9赞 ssynhtn 6/25/2019 #4

我遇到了同样的问题

似乎只能保证保留类本身,但其成员仍可能被删除-keep class

在我的例子中,一个类的一些静态最终字段被删除,这最终导致索引越界异常CustomDao$Properties

取代

-keep class **$Properties

-keep class **$Properties { *; }

解决了我的问题

评论

2赞 mrstif 8/7/2019
使用 R8 时,我的应用程序开始因此问题而从无到有崩溃。这修复了它。谢谢!🙏
0赞 NoHarmDan 9/11/2019
正如@mrstif所说,这个问题在 R8 发布后开始意外发生(即使我不知道它是否被使用),这是解决它的唯一方法。我相信它适用于更多的情况,而不仅仅是这个特定的 GreenDao 问题。
1赞 Jonathan Campos 8/14/2019 #5
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/** 
 * DAO for table "addresses".
*/
public class DbAddressDao extends AbstractDao<DbAddress, Long> {

    public static final String TABLENAME = "addresses";

    /**
     * Properties of entity DbAddress.<br/>
     * Can be used for QueryBuilder and for referencing column names.
    */
    public static class Properties {
        public final static Property Id = new Property(0, long.class, "id", true, "_id");
        public final static Property AddressLine = new Property(3, String.class, "addressLine", false, "ADDRESS_LINE");
    }

如果你查看 GreenDao 库自动生成的 Dao 类 您可以注意到,它创建了一个名为 Properties 的内部类,其中包含数据库表中的每个字段,如上例所示。

你注意这些字段,你会注意到它们没有被用于代码的任何部分,因为 GreenDao 通过 DaoConfig 类使用反射来获取这些字段。请参阅 DaoConfig 中的 reflectProperties 方法。

问题是,当您启用 Proguard 时,它会理解属性中的所有这些字段都没有在任何地方使用,因此 Proguard 会将其删除。

因此,为避免这种情况发生,请将以下行添加到您的 Proguard 文件中:

-keep class **$Properties
-keepclassmembers class **$Properties {
    public static <fields>;
}

这应该可以解决问题。

0赞 Douglas Flores 10/28/2021 #6

在下面添加的行 proguard-rules.pro 为我解决了这个问题。

-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
public static java.lang.String TABLENAME;
}
-keep class **$Properties

谢谢@mgpx