You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 04:06:14