sensorsdata/sa-sdk-android

与Realm数据库冲突

Closed this issue · 5 comments

主module
apply plugin: 'com.sensorsdata.analytics.android'
apply plugin: 'realm-android'
其它module
apply plugin: 'realm-android'

同时引入神策和Realm数据库,编译无法通过。
报错信息:
Type io.realm.DefaultRealmModule is defined multiple times: /Users/zhou/workspace/android/JDXL/app/build/intermediates/project_dex_archive/AliyunDebug/out/io/realm/DefaultRealmModule.dex, /Users/zhou/workspace/android/JDXL/app/build/intermediates/mixed_scope_dex_archive/AliyunDebug/out/82421774901896ca028ce13eb6b35e68091364770fddf70cce4d0eb3fc6efcbe_1.jar:classes.dex

@AwakenDragon 感谢反馈,明天工作日研发同学验证下。

@AwakenDragon 本地验证,使用如下版本

classpath "io.realm:realm-gradle-plugin:6.0.2"

以及同时使用 Realm PluginSA Plugin 测试,可以正常通过编译。可能是还有其他因素导致的,你可以将 io.realm包加入到插件处理的黑名单中 再尝试编译一次。
如果还是无法解决,请发一个能复现的 Demo 给我们,我们好排查问题。

冲突出现的具体操作:
1.项目中包含多个module
2.主module和其它module同时引入Realm Plugin,并且每个module中新建几个继承RealmObject的Model。编译,每个module都会自动生成一个DefaultRealmModuleMediator类。此时主module未引入SA Plugin,可以运行,可以打包,没有问题
3.在2条件的基础上引入SA Plugin,无法编译通过,报Type io.realm.DefaultRealmModule is defined multiple times错误
解决方案:子module中,注解@RealmModule的属性library必须设置为true

根据 @RealmModule上的注释来看,在 library moduleapp module同时引入Realm的时候确实需要给这个注解加上 library=true这个属性,这是一个正确的做法:

RealmModules and libraries
Realms default behavior is to automatically create a RealmModule called DefaultRealmModule which contains all classes extending RealmObject in a project. This module is automatically known by Realm.
This behavior is problematic when combining a library project and an app project that both uses Realm. This is because the DefaultRealmModule will be created for both the library project and the app project, which will cause the project to fail with duplicate class definition errors.
Library authors are responsible for avoiding this conflict by using explicit modules where library = true is set. This disables the generation of the DefaultRealmModule for the library project and allows the library to be included in the app project that also uses Realm. This means that library projects that uses Realm internally are required to specify a specific module using RealmConfiguration.modules().
App developers are not required to specify any modules, as they implicitly use the DefaultRealmModule, but they now has the option of adding the library project classes to their schema using RealmConfiguration.addModule().

至于项目中为啥会在引入 SA Plugin 后出错,从提供的错误日志上看并非插件导致的,插件只会处理字节码,相反在没有引入插件的情况下能够编译通过似乎反而说不通,不知道是否是因为缓存的原因导致的?

本地集成 Realm 验证,在不使用 SA Plugin 以及设置 Library 中 @RealmModule(library=false) 的情况下总是会报如下错误:

java.lang.RuntimeException: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: 
Learn how to resolve the issue at https://developer.android.com/studio/build/dependencies#duplicate_classes.
Program type already present: io.realm.DefaultRealmModuleMediator
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:593)
        at java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:677)
        at java.util.concurrent.ForkJoinTask.join(ForkJoinTask.java:720)
        at com.google.common.collect.ImmutableList.forEach(ImmutableList.java:407)

跟题主反馈的问题相近。另外设置 Library 中 @RealmModule(library=true) 的情况下,加或者不加 SA Plugin 都不会报错。项目使用的 Realm 版本如下:

 classpath "io.realm:realm-gradle-plugin:6.0.2"

暂定此问题与插件关系不大。