React-native Android 捆绑包版本无法在某些设备上运行

Emr*_*cer 5 64-bit android build react-native android-app-bundle

我正在开发一个移动应用程序并使用react-native进行开发。我可以通过以下方式在我的模拟器上成功运行该项目

\n\n
react-native run-android \n
Run Code Online (Sandbox Code Playgroud)\n\n

我可以使用命令成功发布捆绑包

\n\n
./gradlew bundleRelease\n
Run Code Online (Sandbox Code Playgroud)\n\n

我什至可以成功地将我的应用上传到 Google Play 商店。\n问题是某些设备无法安装该应用。它会失败。

\n\n

在互联网上搜索后,我发现问题是不同设备上的各种不同的 cpu 架构(据我所知)。我的模拟器使用 32 位 cpu (x86),并且构建在我的模拟器上成功运行。

\n\n

我没有 Android 设备,因此我发现调试错误的最佳方法是使用 Firebase 的“测试实验室”并观察输出。

\n\n

我相信除了CPU架构之外还有另一个问题,那就是Hermes。我在app/build.gradle中禁用了hermes,但是当我发布一个包并在Firebase测试实验室上测试它时,应用程序将失败并给我这个输出;

\n\n
java.lang.UnsatisfiedLinkError: couldn\'t find DSO to load: libhermes.so\n     FATAL EXCEPTION: create_react_context\nProcess: com.lockerapp, PID: 18180\njava.lang.UnsatisfiedLinkError: couldn\'t find DSO to load: libhermes.so\n    at com.facebook.soloader.SoLoader.doLoadLibraryBySoName(SoLoader.java:738)\n    at com.facebook.soloader.SoLoader.loadLibraryBySoName(SoLoader.java:591)\n    at com.facebook.soloader.SoLoader.loadLibrary(SoLoader.java:529)\n    at com.facebook.soloader.SoLoader.loadLibrary(SoLoader.java:484)\n    at com.facebook.hermes.reactexecutor.HermesExecutor.<clinit>(HermesExecutor.java:20)\n    at com.facebook.hermes.reactexecutor.HermesExecutorFactory.create(HermesExecutorFactory.java:27)\n    at com.facebook.react.ReactInstanceManager$5.run(ReactInstanceManager.java:949)\n    at java.lang.Thread.run(Thread.java:764)\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我的环境;

\n\n
System:\n    OS: macOS 10.14.4\n    CPU: (4) x64 Intel(R) Core(TM) i5-4278U CPU @ 2.60GHz\n    Memory: 242.76 MB / 8.00 GB\n    Shell: 3.2.57 - /bin/bash\n  Binaries:\n    Node: 12.9.0 - /usr/local/bin/node\n    Yarn: 1.17.3 - /usr/local/bin/yarn\n    npm: 6.10.3 - /usr/local/bin/npm\n    Watchman: 4.9.0 - /usr/local/bin/watchman\n  SDKs:\n    iOS SDK:\n      Platforms: iOS 12.4, macOS 10.14, tvOS 12.4, watchOS 5.3\n    Android SDK:\n      API Levels: 25, 26, 27, 28, 29\n      Build Tools: 26.0.2, 27.0.3, 28.0.3, 29.0.2\n      System Images: android-28 | Intel x86 Atom_64, android-28 | Google Play Intel x86 Atom\n  IDEs:\n    Android Studio: 3.4 AI-183.6156.11.34.5692245\n    Xcode: 10.3/10G8 - /usr/bin/xcodebuild\n  npmPackages:\n    react: 16.8.6 => 16.8.6 \n    react-native: 0.60.5 => 0.60.5 \n  npmGlobalPackages:\n    create-react-native-app: 2.0.2\n    react-native-cli: 2.0.1\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我的 app/build.gralde;

\n\n
apply plugin: "com.android.application"\n\nimport com.android.build.OutputFile\n\nproject.ext.react = [\n    entryFile: "index.js",\n    enableHermes: false,  // clean and rebuild if changing\n]\n\napply from: "../../node_modules/react-native/react.gradle"\n\n\ndef enableHermes = project.ext.react.get("enableHermes", false);\n\nandroid {\n    compileSdkVersion rootProject.ext.compileSdkVersion\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n\n    defaultConfig {\n        applicationId "com.lockerapp"\n        minSdkVersion rootProject.ext.minSdkVersion\n        targetSdkVersion rootProject.ext.targetSdkVersion\n        versionCode 11\n        versionName "1.1.5"\n    }\n    splits {\n        abi {\n            reset()\n            enable enableSeparateBuildPerCPUArchitecture\n            universalApk false  // If true, also generate a universal APK\n            include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"\n        }\n    }\n    signingConfigs {\n        debug {\n            storeFile file(\'debug.keystore\')\n            storePassword \'android\'\n            keyAlias \'androiddebugkey\'\n            keyPassword \'android\'\n        }\n    release {\n            if (project.hasProperty(\'MYAPP_UPLOAD_STORE_FILE\')) {\n                storeFile file(MYAPP_UPLOAD_STORE_FILE)\n                storePassword MYAPP_UPLOAD_STORE_PASSWORD\n                keyAlias MYAPP_UPLOAD_KEY_ALIAS\n                keyPassword MYAPP_UPLOAD_KEY_PASSWORD\n            }\n        }\n    }\n    buildTypes {\n        debug {\n            signingConfig signingConfigs.debug\n        }\n        release {\n            // Caution! In production, you need to generate your own keystore file.\n            // see https://facebook.github.io/react-native/docs/signed-apk-android.\n            signingConfig signingConfigs.release\n        minifyEnabled enableProguardInReleaseBuilds\n            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"\n        }\n    }\n    // applicationVariants are e.g. debug, release\n    applicationVariants.all { variant ->\n        variant.outputs.each { output ->\n            // For each separate APK per architecture, set a unique version code as described here:\n            // https://developer.android.com/studio/build/configure-apk-splits.html\n            def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]\n            def abi = output.getFilter(OutputFile.ABI)\n            if (abi != null) {  // null for the universal-debug, universal-release variants\n                output.versionCodeOverride =\n                        versionCodes.get(abi) * 1048576 + defaultConfig.versionCode\n            }\n\n        }\n    }\n\n    packagingOptions {\n        pickFirst \'**/armeabi-v7a/libc++_shared.so\'\n        pickFirst \'**/x86/libc++_shared.so\'\n        pickFirst \'**/arm64-v8a/libc++_shared.so\'\n        pickFirst \'**/x86_64/libc++_shared.so\'\n        pickFirst \'**/x86/libjsc.so\'\n        pickFirst \'**/armeabi-v7a/libjsc.so\'\n    }\n}\n\ndependencies {\n    implementation fileTree(dir: "libs", include: ["*.jar"])\n    implementation "com.facebook.react:react-native:+"  // From node_modules\n\n    if (enableHermes) {\n      def hermesPath = "../../node_modules/hermesvm/android/";\n      debug\xc4\xb0mplementation files(hermesPath + "hermes-debug.aar")\n      release\xc4\xb0mplementation files(hermesPath + "hermes-release.aar")\n    } else {\n      implementation jscFlavor\n    }\n}\n\n// Run this once to be able to run the application with BUCK\n// puts all compile dependencies into folder libs for BUCK to use\ntask copyDownloadableDepsToLibs(type: Copy) {\n    from configurations.compile\n    into \'libs\'\n}\n\napply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)\n\n
Run Code Online (Sandbox Code Playgroud)\n\n

我正在努力为尽可能多的设备发布捆绑包并发布到 Google Play 商店。只要我的构建成功并在所有可能的设备上运行,我并不真正关心是否使用 Hermes。

\n\n

是否有一个已知的指南,我可能错过了发布所有 CPU 架构的捆绑包并避免 Hermes 的错误?\n任何答案都值得赞赏,谢谢。

\n\n

更新:

\n\n

经过大量研究后,我仍然找不到解决方案,但是我找到了解决该问题的方法,而不是使用以下命令创建 .aab 文件

\n\n
./gradlew bundleRelase \n
Run Code Online (Sandbox Code Playgroud)\n\n

我正在使用以下命令创建一个通用 APK 文件;

\n\n
./gradlew assembleRelease\n
Run Code Online (Sandbox Code Playgroud)\n\n

生成的 .apk 文件被 Google Play 商店接受,我已经通过了 Firebase 测试实验室的测试,也适用于 32 位和 64 位本地 Android 模拟器,缺点当然是我的下载大小增加了(从大约 8mb 到 15mb),但是这仍然是一段时间内的解决方案。

\n

Bla*_*dow 3

我能够启用hermes并创建捆绑包并通过此修复提交到 Playstore

if (getGradle().getStartParameter().getTaskRequests().toString().toLowerCase().contains("bundle")) {
    packagingOptions {
        exclude '**/libhermes-inspector.so'
        exclude '**/libhermes-executor-debug.so'
        exclude '**/libjscexecutor.so'
    }
}
Run Code Online (Sandbox Code Playgroud)

https://github.com/facebook/react-native/issues/25927#issuecomment-535695869

如果您想测试最终bundle文件,我建议您执行以下操作:

  1. 下载 android 捆绑工具 ( BundleTool GitHub )
  2. 从一台 Android 设备创建配置文件

    java -jar bundletool.jar get-device-spec --output=device-spec.json

  3. 为该特定配置文件生成 apk

    java -jar bundletool.jar build-apks --device-spec=device-spec.json --bundle=app-release.aab --output=device.apks

  4. 将生成的APK安装到设备中

    java -jar bundletool.jar install-apks --apks=device.apks

  5. 另外,您可以使用 android apk 分析器并查看这些 APK 并确保hermes二进制文件存在,而 libjs 相关的二进制文件不存在。