如何通过Relocation/Shadow解决React Native重复类错误?
解决React Native包中
com.realsil.sdk.*重复类冲突方案 核心思路
针对IDO和CRP SDK重复的com.realsil.sdk.*类,使用Shadow插件对其中一个SDK的重复类进行包路径重定位,避免类冲突。以下是具体Gradle配置修改步骤:
1. 正确应用Shadow插件
在build.gradle中添加Shadow插件应用(仅在rootProject的buildscript中添加classpath不够,需单独应用插件):
apply plugin: 'com.android.library' apply plugin: 'maven-publish' apply plugin: 'com.github.johnrengelman.shadow' // 新增这行
2. 配置类重定位规则
在android块之后添加Shadow插件配置,指定要重定位的包路径(以CRP SDK为例,将其com.realsil.sdk.*重命名为com.crp.realsil.sdk.*):
shadowJar { // 重定位CRP SDK中的重复包 relocate 'com.realsil.sdk', 'com.crp.realsil.sdk' // 仅处理CRP相关依赖,避免影响其他库 configurations = [project.configurations.crpShadow] } // 创建单独配置用于Shadow处理 configurations { crpShadow customConfig.extendsFrom implementation }
3. 调整依赖配置
将CRP SDK的implementation改为crpShadow配置,确保Shadow插件只处理该依赖:
dependencies { // ... 其他依赖保持不变 // CRP -- SDK--need 修改依赖配置 crpShadow fileTree(dir: 'libs/crpblesdk', include: ['*.aar', '*.jar'], exclude: []) // 将处理后的Shadow jar加入implementation implementation shadowJar }
4. 适配Android库变体
在afterEvaluate块中添加代码,关联Shadow任务与Android库变体构建流程:
afterEvaluate { project -> // ... 原有代码保持不变 // 确保Shadow任务在变体编译前执行 android.libraryVariants.all { variant -> variant.javaCompileProvider.get().dependsOn(shadowJar) } }
完整修改后的关键代码片段
def DEFAULT_COMPILE_SDK_VERSION = 31 def DEFAULT_BUILD_TOOLS_VERSION = '28.0.3' def DEFAULT_MIN_SDK_VERSION = 23 def DEFAULT_TARGET_SDK_VERSION = 31 def safeExtGet(prop, fallback) { rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback } def safeExtHasProp(prop){ rootProject.ext.has(prop) } apply plugin: 'com.android.library' apply plugin: 'maven-publish' apply plugin: 'com.github.johnrengelman.shadow' // 新增 buildscript { if (project == rootProject) { repositories { google() jcenter() maven { url = uri("https://plugins.gradle.org/m2/") } } dependencies { classpath 'com.android.tools.build:gradle:3.5.4' classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1" classpath "com.github.johnrengelman:shadow:8.1.0" } } } android { compileSdkVersion safeExtGet('compileSdkVersion', DEFAULT_COMPILE_SDK_VERSION) buildToolsVersion safeExtGet('buildToolsVersion', DEFAULT_BUILD_TOOLS_VERSION) defaultConfig { minSdkVersion safeExtGet('minSdkVersion', DEFAULT_MIN_SDK_VERSION) targetSdkVersion safeExtGet('targetSdkVersion', DEFAULT_TARGET_SDK_VERSION) versionCode 1 versionName "1.0" multiDexEnabled true ndk { abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" } } lintOptions { abortOnError false } sourceSets { main { assets.srcDirs = ['assets'] } } compileOptions { coreLibraryDesugaringEnabled true sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } } // Shadow插件配置 shadowJar { relocate 'com.realsil.sdk', 'com.crp.realsil.sdk' configurations = [project.configurations.crpShadow] } configurations { crpShadow // 新增配置 customConfig.extendsFrom implementation } repositories { mavenLocal() maven { url "$rootDir/../node_modules/react-native/android" } maven { url "$rootDir/../node_modules/jsc-android/dist" } google() jcenter() } dependencies { implementation 'com.facebook.react:react-native:+' implementation 'org.greenrobot:greendao:3.2.2' implementation 'com.alibaba:fastjson:1.2.35' implementation 'com.squareup.okhttp3:okhttp:3.4.1' implementation 'com.squareup.okio:okio:1.9.0' implementation 'com.google.code.gson:gson:2.8.0' implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' implementation 'com.tencent.bugly:crashreport:latest.release' //KCT -- SDK--need implementation fileTree(dir: 'libs/kctblesdk', include: ['*.aar', '*.jar'], exclude: []) //IDO -- SDK--need implementation fileTree(dir: 'libs/idoblesdk', include: ['*.jar'], exclude: []) //SMA -- SDK--need debugImplementation fileTree(dir: 'libs/smablesdk/debug', include: ['*.aar', '*.jar'], exclude: []) releaseImplementation fileTree(dir: 'libs/smablesdk/release', include: ['*.aar', '*.jar'], exclude: []) //CRP -- SDK--need 修改依赖配置 crpShadow fileTree(dir: 'libs/crpblesdk', include: ['*.aar', '*.jar'], exclude: []) implementation shadowJar // 加入处理后的jar if(safeExtHasProp('iotLibsVersion')){ implementation fileTree(dir: 'libs/smablesdk/iot_libs', include: ['*.aar', '*.jar'], exclude: []) implementation group: 'com.adups.iot', name: 'trace', version: '1.0.4' implementation group: 'com.adups.iot', name: 'mqtt_libs', version: '1.1.3' implementation group: 'com.adups.iot', name: 'iot_download_libs', version: '1.1.7' implementation group: 'com.adups.iot', name: 'http_libs', version: '1.0.8' } implementation 'no.nordicsemi.android:dfu:1.8.1' def room_version = "2.4.1" implementation "androidx.room:room-runtime:$room_version" annotationProcessor "androidx.room:room-compiler:$room_version" implementation "androidx.room:room-rxjava2:$room_version" implementation "androidx.room:room-guava:$room_version" testImplementation "androidx.room:room-testing:$room_version" def work_version = "2.7.0" implementation "androidx.work:work-runtime:$work_version" implementation 'com.google.android.gms:play-services-location:19.0.1' implementation 'com.google.android.gms:play-services-maps:18.0.2' coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.1" } def configureReactNativePom(def pom) { def packageJson = new groovy.json.JsonSlurper().parseText(file('../package.json').text) pom.project { name packageJson.title artifactId packageJson.name version = packageJson.version group = "com.reactlibrary" description packageJson.description url packageJson.repository.baseUrl licenses { license { name packageJson.license url packageJson.repository.baseUrl + '/blob/master/' + packageJson.licenseFilename distribution 'repo' } } developers { developer { id packageJson.author.username name packageJson.author.name } } } } afterEvaluate { project -> task androidJavadoc(type: Javadoc) { source = android.sourceSets.main.java.srcDirs classpath += files(android.bootClasspath) classpath += files(project.getConfigurations().getByName('customConfig').asList()) include '**/*.java' } task androidJavadocJar(type: Jar, dependsOn: androidJavadoc) { classifier = 'javadoc' from androidJavadoc.destinationDir } task androidSourcesJar(type: Jar) { classifier = 'sources' from android.sourceSets.main.java.srcDirs include '**/*.java' } android.libraryVariants.all { variant -> def name = variant.name.capitalize() def javaCompileTask = variant.javaCompileProvider.get() task "jar${name}"(type: Jar, dependsOn: javaCompileTask) { from javaCompileTask.destinationDir } // 关联Shadow任务与变体编译 javaCompileTask.dependsOn(shadowJar) } artifacts { archives androidSourcesJar archives androidJavadocJar } publishing { repositories { maven { url = uri("${rootProject.projectDir}/maven-repo") } } } }
验证执行
运行构建命令检查是否解决冲突:
./gradlew assembleRelease
内容的提问来源于stack exchange,提问作者Joao Victor Simonassi Farias
相关产品推荐
相关产品推荐

