Android Gradle exclude失效:RN项目play-services-location版本指定不生效
这问题我之前帮人排查过,核心原因是模块级别的依赖解析和你在app层的exclude/force配置没同步,具体来说:
为什么Gradle还在找16.1.0版本?
你的react-native-geolocation-service模块的build.gradle里,是直接读取根项目的googlePlayServicesVersion变量来确定play-services-location的版本:
def googlePlayServicesVersion = rootProject.hasProperty('googlePlayServicesVersion') ? rootProject.googlePlayServicesVersion : DEFAULT_GOOGLE_PLAY_SERVICES_VERSION implementation "com.google.android.gms:play-services-location:$googlePlayServicesVersion"
而你根build.gradle里明确设置了googlePlayServicesVersion = "16.1.0",所以这个模块在自身编译阶段(比如生成Debug R文件的步骤)会优先使用这个根变量指定的版本,和你在app模块里做的exclude、force配置没关系——因为app层的配置只影响app模块的依赖树,管不到其他模块自己的依赖解析逻辑。
可行的解决方案
方案一:修改根项目的版本变量(最简单直接)
直接把根build.gradle里的版本改成你需要的16.0.0:
buildscript { ext { ... googlePlayServicesVersion = "16.0.0" // 把这里改成16.0.0 } }
然后把app/build.gradle里的exclude和force配置删掉,只保留基础依赖:
dependencies { implementation(project(':react-native-geolocation-service')) }
这样react-native-geolocation-service会自动使用根项目指定的16.0.0版本,完美匹配你的需求。
方案二:通过根项目的resolutionStrategy统一强制版本(适合不想修改根变量的场景)
如果因为其他模块需要保留16.1.0的根变量,可以在根build.gradle的allprojects块里添加全局依赖解析策略,强制所有模块使用16.0.0版本的play-services-location:
allprojects { repositories { // 你的仓库配置(比如google()、mavenCentral()等) } configurations.all { resolutionStrategy { // 强制所有依赖使用指定版本的play-services-location force 'com.google.android.gms:play-services-location:16.0.0' } } }
同样,app层的exclude和force配置可以删掉,全局策略会自动接管所有模块的这个依赖版本。
方案三:修改第三方库的build.gradle(不推荐)
你可以手动修改node_modules/react-native-geolocation-service/android/build.gradle里的版本,直接写死16.0.0:
implementation "com.google.android.gms:play-services-location:16.0.0"
但这个方法有个致命问题:每次执行npm install或yarn install时,第三方库会被重新安装,你的修改会被覆盖。如果一定要用这个方法,建议配合patch-package工具给这个库打补丁,保留你的修改。
总结
优先推荐方案一或方案二,这两种方法都是从Gradle依赖解析的根源上解决问题,比在app层做exclude/force更可靠。
内容的提问来源于stack exchange,提问作者karansky

