React Native Android添加productFlavours后本地资源无法渲染
React Native Android添加productFlavours后assets本地资源无法加载问题
问题详情
- 克隆master分支后,Android端运行时
assets/目录下的本地图片、图标资源均无法加载,仅显示空白背景;iOS端无异常 - 问题始于添加多环境配置的
productFlavours之后 - 使用的运行命令:
npx react-native run-android --variant=DevDebug
提供的android/app/build.gradle内容
apply plugin: "com.android.application" import com.android.build.OutputFile project.ext.react = [ enableHermes: (findProperty('expo.jsEngine') ?: "jsc") == "hermes", cliPath: new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/cli.js", hermesCommand: new File(["node", "--print", "require.resolve('hermes-engine/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/%OS-BIN%/hermesc", composeSourceMapsPath: new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/scripts/compose-source-maps.js", ] apply from: new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), "../react.gradle") apply from: new File(["node", "--print", "require.resolve('@sentry/react-native/package.json')"].execute().text.trim(), "../sentry.gradle") android { compileSdkVersion rootProject.ext.compileSdkVersion defaultConfig { applicationId 'com.myapp' minSdkVersion rootProject.ext.minSdkVersion multiDexEnabled true targetSdkVersion rootProject.ext.targetSdkVersion versionCode 21 versionName "0.2.14" vectorDrawables.useSupportLibrary = true buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { externalNativeBuild { ndkBuild { arguments "APP_PLATFORM=android-21", "APP_STL=c++_shared", "NDK_TOOLCHAIN_VERSION=clang", "GENERATED_SRC_DIR=$buildDir/generated/source", "PROJECT_BUILD_DIR=$buildDir", "REACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid", "REACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build", "NODE_MODULES_DIR=$rootDir/../node_modules" cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1" cppFlags "-std=c++17" targets "myapp-app_appmodules" } } if (!enableSeparateBuildPerCPUArchitecture) { ndk { abiFilters (*reactNativeArchitectures()) } } } } if (isNewArchitectureEnabled()) { externalNativeBuild { ndkBuild { path "$projectDir/src/main/jni/Android.mk" } } def reactAndroidProjectDir = project(':ReactAndroid').projectDir def packageReactNdkDebugLibs = tasks.register("packageReactNdkDebugLibs", Copy) { dependsOn(":ReactAndroid:packageReactNdkDebugLibsForBuck") from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib") into("$buildDir/react-ndk/exported") } def packageReactNdkReleaseLibs = tasks.register("packageReactNdkReleaseLibs", Copy) { dependsOn(":ReactAndroid:packageReactNdkReleaseLibsForBuck") from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib") into("$buildDir/react-ndk/exported") } afterEvaluate { preDebugBuild.dependsOn(packageReactNdkDebugLibs) preReleaseBuild.dependsOn(packageReactNdkReleaseLibs) configureNdkBuildRelease.dependsOn(preReleaseBuild) configureNdkBuildDebug.dependsOn(preDebugBuild) reactNativeArchitectures().each { architecture -> tasks.findByName("configureNdkBuildDebug[${architecture}]")?.configure { dependsOn("preDebugBuild") } tasks.findByName("configureNdkBuildRelease[${architecture}]")?.configure { dependsOn("preReleaseBuild") } } } } splits { abi { reset() enable enableSeparateBuildPerCPUArchitecture universalApk false // If true, also generate a universal APK include (*reactNativeArchitectures()) } } signingConfigs { debug { storeFile file('debug.keystore') storePassword 'android' keyAlias 'androiddebugkey' keyPassword 'android' } } buildTypes { debug { signingConfig signingConfigs.debug } release { signingConfig signingConfigs.debug minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } flavorDimensions "env" productFlavors { production { dimension "env" applicationId 'com.myapp' } development { dimension "env" applicationId 'com.myapp' } staging { dimension "env" applicationId 'com.myapp' } } applicationVariants.all { variant -> variant.outputs.each { output -> def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] def abi = output.getFilter(OutputFile.ABI) if (abi != null) { output.versionCodeOverride = versionCodes.get(abi) * 1048576 + defaultConfig.versionCode } } } }
解决方案
1. 强制所有变体关联bundle打包任务
React Native的react.gradle默认可能未适配多flavor场景,导致特定变体未执行assets打包。在android代码块末尾添加以下配置:
afterEvaluate { // 确保所有mergeAssets任务依赖对应的bundle任务 def bundleTasks = tasks.findAll { task -> task.name.startsWith('bundle') } bundleTasks.each { bundleTask -> def targetVariant = bundleTask.name.split('bundle')[1].toLowerCase() tasks.findAll { task -> task.name.startsWith('merge') && task.name.endsWith('Assets') && task.name.toLowerCase().contains(targetVariant) }.each { mergeTask -> mergeTask.dependsOn(bundleTask) } } }
2. 明确每个flavor的assets目录
如果多flavor配置覆盖了默认资源目录继承规则,需在每个productFlavour中明确包含主assets目录:
productFlavors { production { dimension "env" applicationId 'com.myapp' sourceSets.production.assets.srcDirs += file("src/main/assets") } development { dimension "env" applicationId 'com.myapp' sourceSets.development.assets.srcDirs += file("src/main/assets") } staging { dimension "env" applicationId 'com.myapp' sourceSets.staging.assets.srcDirs += file("src/main/assets") } }
3. 清理缓存并手动重新打包assets
执行以下命令彻底清理构建缓存,手动生成bundle文件后重新运行项目:
# 清理Android构建缓存 cd android && ./gradlew clean && cd .. # 手动生成Android bundle和资源 npx react-native bundle --platform android --dev true --entry-file index.js \ --bundle-output android/app/src/main/assets/index.android.bundle \ --assets-dest android/app/src/main/res/ # 重新运行项目 npx react-native run-android --variant=DevDebug
4. 检查react.gradle的bundle配置
确认project.ext.react中未限制仅为特定变体打包,确保bundleInDebug、bundleInRelease等参数(如果存在)未被错误设置为false。
内容的提问来源于stack exchange,提问作者dev1ce
相关产品推荐
相关产品推荐

