I am working on a mobile application and developing it using react-native.I can successfully run the project on my emulator via
react-native run-android
and i can successfully have a bundle release with the command
./gradlew bundleRelease
And i can even successfully upload my app to the Google Play Store. The problem is that some devices won't be able to install the app.It will fail.
After searching on the internet i figured out that the problem was variety of different cpu architectures on different devices (as far as i understood).And my emulator is using a 32 bit cpu (x86) and the build runs successfully on my emulator.
I don't own an Android device so the best way i have found to debug the error was to use Firebase's "Test Lab" and observe the output.
I believe there is another problem other than cpu architecture, which is the Hermes.I am disabling the hermes in my app/build.gradle however when i release a bundle and test it on Firebase Test Lab the application will fail and give me this output;
java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libhermes.so
FATAL EXCEPTION: create_react_context
Process: com.lockerapp, PID: 18180
java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libhermes.so
at com.facebook.soloader.SoLoader.doLoadLibraryBySoName(SoLoader.java:738)
at com.facebook.soloader.SoLoader.loadLibraryBySoName(SoLoader.java:591)
at com.facebook.soloader.SoLoader.loadLibrary(SoLoader.java:529)
at com.facebook.soloader.SoLoader.loadLibrary(SoLoader.java:484)
at com.facebook.hermes.reactexecutor.HermesExecutor.<clinit>(HermesExecutor.java:20)
at com.facebook.hermes.reactexecutor.HermesExecutorFactory.create(HermesExecutorFactory.java:27)
at com.facebook.react.ReactInstanceManager$5.run(ReactInstanceManager.java:949)
at java.lang.Thread.run(Thread.java:764)
Here is my environment;
System:
OS: macOS 10.14.4
CPU: (4) x64 Intel(R) Core(TM) i5-4278U CPU @ 2.60GHz
Memory: 242.76 MB / 8.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 12.9.0 - /usr/local/bin/node
Yarn: 1.17.3 - /usr/local/bin/yarn
npm: 6.10.3 - /usr/local/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 12.4, macOS 10.14, tvOS 12.4, watchOS 5.3
Android SDK:
API Levels: 25, 26, 27, 28, 29
Build Tools: 26.0.2, 27.0.3, 28.0.3, 29.0.2
System Images: android-28 | Intel x86 Atom_64, android-28 | Google Play Intel x86 Atom
IDEs:
Android Studio: 3.4 AI-183.6156.11.34.5692245
Xcode: 10.3/10G8 - /usr/bin/xcodebuild
npmPackages:
react: 16.8.6 => 16.8.6
react-native: 0.60.5 => 0.60.5
npmGlobalPackages:
create-react-native-app: 2.0.2
react-native-cli: 2.0.1
And here is my app/build.gralde;
apply plugin: "com.android.application"
import com.android.build.OutputFile
project.ext.react = [
entryFile: "index.js",
enableHermes: false, // clean and rebuild if changing
]
apply from: "../../node_modules/react-native/react.gradle"
def enableHermes = project.ext.react.get("enableHermes", false);
android {
compileSdkVersion rootProject.ext.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId "com.lockerapp"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 11
versionName "1.1.5"
}
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}
}
signingConfigs {
debug {
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
release {
if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
storeFile file(MYAPP_UPLOAD_STORE_FILE)
storePassword MYAPP_UPLOAD_STORE_PASSWORD
keyAlias MYAPP_UPLOAD_KEY_ALIAS
keyPassword MYAPP_UPLOAD_KEY_PASSWORD
}
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://facebook.github.io/react-native/docs/signed-apk-android.
signingConfig signingConfigs.release
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// https://developer.android.com/studio/build/configure-apk-splits.html
def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
}
}
}
packagingOptions {
pickFirst '**/armeabi-v7a/libc++_shared.so'
pickFirst '**/x86/libc++_shared.so'
pickFirst '**/arm64-v8a/libc++_shared.so'
pickFirst '**/x86_64/libc++_shared.so'
pickFirst '**/x86/libjsc.so'
pickFirst '**/armeabi-v7a/libjsc.so'
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "com.facebook.react:react-native:+" // From node_modules
if (enableHermes) {
def hermesPath = "../../node_modules/hermesvm/android/";
debugİmplementation files(hermesPath + "hermes-debug.aar")
releaseİmplementation files(hermesPath + "hermes-release.aar")
} else {
implementation jscFlavor
}
}
// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
from configurations.compile
into 'libs'
}
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
I am struggling with releasing a bundle for as many devices as possible and publishing to the Google Play Store.I don't really care about using hermes or not as far as my build succeeds and runs on all possible devices.
Is there a known guide that i might have missed to release a bundle for all cpu architectures and avoids the errors with hermes? Any answer is appreciated, thanks.
UPDATE:
After a lot of research i still couldn't find a solution for this, however i found a work around for the problem, instead of creating an .aab file with
./gradlew bundleRelase
i am creating a universal APK file with the command;
./gradlew assembleRelease
The generated .apk file is accepted by google play store and i have passed the tests on Firebase Test Lab, also works on 32bit and 64bit local android emulators, the down side is of course my download size increased (from around 8mb to 15mb) but still it is a solution for a while.