Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support third-party 64-bit libraries on Android #2814

Closed
corbt opened this issue Sep 17, 2015 · 130 comments
Closed

Support third-party 64-bit libraries on Android #2814

corbt opened this issue Sep 17, 2015 · 130 comments

Comments

@corbt
Copy link
Contributor

@corbt corbt commented Sep 17, 2015

Excerpt from the Android Developers Blog article, Get your apps ready for the 64-bit requirement:
[added by @hramos]

The 64-bit requirement: what it means for developers

Starting August 1, 2019:

  • All new apps and app updates that include native code are required to provide 64-bit versions in addition to 32-bit versions when publishing to Google Play.
  • Extension: Google Play will continue to accept 32-bit only updates to existing games that use Unity 5.6 or older until August 2021.

Starting August 1, 2021:

  • Google Play will stop serving apps without 64-bit versions on 64-bit capable devices, meaning they will no longer be available in the Play Store on those devices.
  • This will include games built with Unity 5.6 or older.

The requirement does not apply to:

  • APKs or app bundles explicitly targeting Wear OS or Android TV, which are form factors that do not currently support 64-bit code.
  • APKs or app bundles that are not distributed to devices running Android 9 Pie or later.

Original Issue

Hey, it appears that React Native on Android doesn't provide a 64-bit version of the libreactnativejni.so native library, which can cause compatibility issues on 64-bit devices. I ran into this while attempting to integrate React Native with a large existing application I'm developing.

Steps to reproduce:

  1. Create a new application with react-native init.
  2. In the "android/app/build.gradle" file, add compile 'io.realm:realm-android:0.82.2' to the end of the dependencies {} block. (Note that I don't think this is an issue specifically caused by Realm, it's just an example dependency with a 64-bit native library).
  3. Attempt to run on a Nexus 9.

Stack trace:

E/AndroidRuntime(32171): FATAL EXCEPTION: main
E/AndroidRuntime(32171): Process: com.androidemberall, PID: 32171
E/AndroidRuntime(32171): java.lang.UnsatisfiedLinkError: could find DSO to load: libreactnativejni.so
E/AndroidRuntime(32171):    at com.facebook.soloader.SoLoader.loadLibraryBySoName(SoLoader.java:213)
E/AndroidRuntime(32171):    at com.facebook.soloader.SoLoader.loadLibrary(SoLoader.java:178)
E/AndroidRuntime(32171):    at com.facebook.react.bridge.JSCJavaScriptExecutor.<clinit>(JSCJavaScriptExecutor.java:19)
...

I believe this to be caused by the shared library loading logic explained in this answer on StackOverflow. Since Realm includes a 64-bit native binary, the system no longer automatically falls back to the 32-bit version of libreactnativejni.so provided by React.

This bug is blocking me from integrating React Native into my existing application, which I'm really excited to try!

@mkonicek
Copy link
Contributor

@mkonicek mkonicek commented Sep 17, 2015

Thanks for reporting! Yes we don't provide 64-bit version of the native code and the system should always fall back to 32-bit. I believe @kmagiera has context on why we don't provide 64-bit version.

@corbt
Copy link
Contributor Author

@corbt corbt commented Sep 17, 2015

Like the stackoverflow answer says, the fallback doesn't work if there are other 64-bit native libraries. Most Android projects use a number of 3rd-party libraries, and any that include native 64-bit code will cause React Native to fail.

I think that Android's policy on this is strange (the way one library is loaded shouldn't affect another that doesn't depend on it), but as you can see if you follow my steps to reproduce, it does in fact fail. As more libraries switch to native 64-bit support and React Native gets used in more heterogeneous projects this will become more of an issue.

@ide ide changed the title React Native for Android fails on nexus 9 with 3rd-party libraries [Android] React Native for Android is incompatible with 3rd-party 64-bit libraries Sep 17, 2015
@kmagiera
Copy link
Contributor

@kmagiera kmagiera commented Sep 18, 2015

It definitely matters as all native libs share address space.

Workaround would be to follow build.grade from our examples and add the following block to defaultConfig:

ndk {
  abiFilters "armeabi-v7a", "x86"
}

see: https://github.com/facebook/react-native/blob/master/Examples/SampleApp/android/app/build.gradle

@corbt
Copy link
Contributor Author

@corbt corbt commented Sep 18, 2015

Yeah, I tested with that ndk block as well (it actually is included in the default project config generated by react-native init) and the issue still stands.

@corbt
Copy link
Contributor Author

@corbt corbt commented Sep 18, 2015

I've uploaded an example failing project here, in case it helps with debugging.

The only changes to the default React-Native-generated project are the addition of the README and the addition of the realm-android dependency.

@corbt
Copy link
Contributor Author

@corbt corbt commented Sep 18, 2015

Furthermore, I can confirm that installing the apk in 32-bit mode works on the nexus 9, as found in this SO answer (adb install --abi armeabi-v7a app-debug.apk)

@corbt
Copy link
Contributor Author

@corbt corbt commented Sep 18, 2015

I figured out a workaround in the short term (disabling all ARM64 binaries) and wrote it up in a blog. However, the right solution definitely needs to be proper ARM64 support, because that's the way the device ecosystem is moving).

If it isn't included because of concerns over binary size, maybe switching to the packaged V8 interpreter would help? Any ARM64 devices should come with it included, and perhaps falling back to the vendored JSC for devices where V8 isn't available could work.

@ide
Copy link
Contributor

@ide ide commented Sep 18, 2015

The fragmentation of running on different JS VMs is worth avoiding. It already kind of sucks that iOS 7/8/9 support different features, and the JS VM should be only a couple MB anyway.

Can ABI splits be used to address concerns about APK size? The idea is that you generate three APKs for 32bit, 64bit, simulator, and distribute them separately.

@corbt
Copy link
Contributor Author

@corbt corbt commented Sep 18, 2015

@ide yes, splits can be used to keep size down, although Google doesn't recommend it: "Although we encourage you to develop and publish a single APK that supports as many device configurations as possible, doing so is sometimes not possible" (emphasis theirs).

I think a reasonable solution would be to generate a monolithic APK by default with x86/arm/arm64 support, and allow individual developers to go through the hassle of producing multiple APKs if their app requires it. I don't think that just ignoring ARM64 will be a good long-term compromise -- it will become harder and harder to use 3rd-party libraries with React Native as more include ARM64 support and more 64-bit devices come to market.

@ide
Copy link
Contributor

@ide ide commented Sep 18, 2015

I kind of understand Google's solution though that's how Apple operated for almost a decade and they're moving to architecture-/device-specific binaries (but doing it all for you with their bitcode compiler).

allow individual developers to go through the hassle of producing multiple APKs if their app requires it

I like this solution as a starting point.

Things to track for 64-bit support are:

All of these are up-for-grabs. @kmagiera can you tell us if 64-bit is something that Facebook is actively interested in, or should people just start working on these items?

@kmagiera
Copy link
Contributor

@kmagiera kmagiera commented Sep 20, 2015

@ide I don't think we have anyone focusing on this at the moment. What are the specific things that doesn't compile for armv8? Except from JSC we build all the first-party and third-party libs RN depends on with BUCK for arm64 so it shouldn't take much to make android makefiles build them as well.

Speaking of split builds I don't think Google's recommendation apply in the case when 80% of the APK size comes from native libs. Don't have exact values with me at the moment but from what I remember JSC lib is around 2.3M for armv7 and 2.5M for x86 (uncompressed) which adds around 1.3M to the APK size. Considering the fact that arm64 are quite rare and all of them can run armv7 binaries (JSC with JIT enabled doesn't work with libhoudini if I recall correctly from our experiments, so I consider x86 android devices incapable of running armv7 in this case) I don't think we should default to armv7+arm64+x86 builds. My suggestion would be still to default to x86+armv7 but provide config for split builds for arm64 once it's supported

@ide
Copy link
Contributor

@ide ide commented Sep 20, 2015

@kmagiera - OK. So if people are interested in 64-bit support they should contribute.

I hit an issue with Google's double-conversion library but I could have specified the wrong compiler options. I didn't spend much time looking into it.

@kmagiera
Copy link
Contributor

@kmagiera kmagiera commented Sep 20, 2015

@ide feel free to send PR, I'll update here once we start working on this but I don't expect this to happen within the next couple of weeks.

@LegNeato
Copy link

@LegNeato LegNeato commented Oct 1, 2015

FWIW Facebook does ABI apk splitting (and others). Whenever we ship we ship ~14 apks to the store. Out of that 14 we had a fallback that supported everything (no splitting) but virtually no device ever installed it because the others were sufficient.

@Matthew-C
Copy link

@Matthew-C Matthew-C commented Oct 27, 2015

Hi,
any plan to solve this issue in the near future? It simply blocks us using react-native on Nexus 9.

@ide
Copy link
Contributor

@ide ide commented Oct 28, 2015

@Matthew-C I haven't heard any updates. If you need this feature, please help out!

@mkonicek
Copy link
Contributor

@mkonicek mkonicek commented Oct 28, 2015

@Matthew-C This workaround might unblock you (see the discussion above): https://corbt.com/posts/2015/09/18/mixing-32-and-64bit-dependencies-in-android.html

@ajwhite
Copy link
Contributor

@ajwhite ajwhite commented Nov 6, 2015

+1 on this, our product has some 64bit dependencies as well

@lklots
Copy link
Contributor

@lklots lklots commented Dec 1, 2015

@mkonicek
Copy link
Contributor

@mkonicek mkonicek commented Apr 10, 2016

Hi there! This issue is being closed because it has been inactive for a while.

But don't worry, it will live on with ProductPains! Check out its new home: https://productpains.com/post/react-native/android-react-native-for-android-is-incompatible-with-3rd-party-64-bit-libraries

ProductPains helps the community prioritize the most important issues thanks to its voting feature.
It is easy to use - just login with GitHub.

Also, if this issue is a bug, please consider sending a PR with a fix.
We're a small team and rely on the community for bug fixes of issues that don't affect fb apps.

@mkonicek mkonicek added the Icebox label Apr 10, 2016
@mkonicek mkonicek closed this Apr 10, 2016
@afilp
Copy link

@afilp afilp commented Mar 27, 2019

Isn't react-native 0.60 solving the problem?

@joshfriend
Copy link

@joshfriend joshfriend commented Mar 27, 2019

@jgreen210
Copy link

@jgreen210 jgreen210 commented Mar 28, 2019

The latest release is currently 0.59.2. There is not yet a 0.60.

@afilp
Copy link

@afilp afilp commented Mar 28, 2019

Indeed, I meant to say "0.59 solving the problem", sorry for the confusion.

rozele pushed a commit to microsoft/react-native-windows that referenced this issue Apr 14, 2019
Summary:
add arm64 support, related issue : facebook/react-native#2814.
If we are okay with binary aar android-jsc, then the pr can be directly merged. Otherwise merge facebookarchive/android-jsc#30 first and do a new release.

RNTester all variant works. You can also test the apk from here: https://github.com/gengjiawen/react-native/releases/tag/v0.56beta.

facebookarchive/android-jsc#30.

 [ANDROID] [ENHANCEMENT] [ABI] - add x86_64 arm64-v8a support.

Differential Revision: D9491481

Pulled By: hramos

fbshipit-source-id: d6ec6992768eb0c0866a0317273e09fae5b8935e
@ggsrivas
Copy link

@ggsrivas ggsrivas commented May 2, 2019

Does this means that all the react native apps will have to upgrade their RN version to 0.0.59 or higher for pushing any update to play store starting August 1st, 2019?

@AdamZaczek
Copy link

@AdamZaczek AdamZaczek commented May 3, 2019

I'm getting the following warning:
This release is not compliant with the Google Play 64-bit requirement.
I'm very confused, react native 0.59 is supposed to support 64-bit. Do you know why did I get this message?

@react-native-bot react-native-bot added the Bug label May 4, 2019
@awidiyadew
Copy link

@awidiyadew awidiyadew commented May 6, 2019

@AdamZaczek after upgrade to RN 0.59 try to add x64 build config on /android/app/build.gradle following android official docs.
https://developer.android.com/distribute/best-practices/develop/64-bit

// Your app's build.gradle
apply plugin: 'com.android.app'

android {
   compileSdkVersion 27
   defaultConfig {
       appId "com.google.example.64bit"
       minSdkVersion 15
       targetSdkVersion 28
       versionCode 1
       versionName "1.0"
       ndk.abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
// ...

To make sure there's no missing library try to decompress apk, and open libs, U will find directory arm64-v8a and x86_64. Make sure that total files in 32 bit (x86 and armeabi-v7a) and x64 bit are same.

@antoinerousseau
Copy link
Contributor

@antoinerousseau antoinerousseau commented May 6, 2019

You can use this tool to know what changed in the project files that are not dependencies thus not automatically updated when updating RN, e.g.:
https://github.com/react-native-community/rn-diff-purge/compare/release/0.58.6..release/0.59.5#diff-b5a6cecd7ee362715d6306d583e73612

@prrenish
Copy link

@prrenish prrenish commented May 20, 2019

 defaultConfig {

ndk{
    abiFilters "armeabi-v7a","x86"
}
packagingOptions {
    exclude "lib/arm64-v8a/libimagepipeline.so"
}
}

this worked for me

@nunobasto
Copy link

@nunobasto nunobasto commented May 24, 2019

I have several Apps with RN 0.54.2. Is there no way I can get a 64bit version without upgrading to 0.59?

I've tried a couple times to upgrade with rn-diff-purge or react-native upgrade but I spend a lot of time solving conflicts and in the end the project doesn't work correctly.

@saadsaleem187
Copy link

@saadsaleem187 saadsaleem187 commented May 24, 2019

My react native version is 0.59 but my app is not working on android 9 after downloading from play store. I followed the @prrenish way but id didn't worked for me. Also i generated Android App Bundle of my app and uploaded to google play console but app still on working on android 9.

@Dror-Bar
Copy link

@Dror-Bar Dror-Bar commented May 26, 2019

So what are the exact steps required after upgrading an app to RN 0.59 so that it will be both 32bit and 64 compliant? I've seen several different suggestions so far such as this, this and this.

@HarshitMadhav
Copy link

@HarshitMadhav HarshitMadhav commented May 30, 2019

Anyone please update on the question of @Dror-Bar ? I also have the same question.

@Dror-Bar
Copy link

@Dror-Bar Dror-Bar commented Jun 2, 2019

By the way, I needed to update from version 0.55.4 to 0.59.8.
As mentioned here by kelset, in order do that I need to use rn-diff-purge to manually change all the necessary files. This ended up being a very tedious process. At the end, I managed to get Android version to work, but on IOS I had a generic linker error that was hard to debug and I couldn't solve.

So, I finally decided to just initialise a new project with the latest version, then simply copy my src folder, make the necessary package updates from there, then run Android Studio and Xcode and see that it compiles successfully . Surprisingly, while I still had to update a few 3rd party packages, this ended up being a much cleaner and easier solution.

t-nanava pushed a commit to microsoft/react-native-macos that referenced this issue Jun 17, 2019
Summary:
add arm64 support, related issue : facebook#2814.
If we are okay with binary aar android-jsc, then the pr can be directly merged. Otherwise merge facebookarchive/android-jsc#30 first and do a new release.

RNTester all variant works. You can also test the apk from here: https://github.com/gengjiawen/react-native/releases/tag/v0.56beta.

facebookarchive/android-jsc#30.

 [ANDROID] [ENHANCEMENT] [ABI] - add x86_64 arm64-v8a support.

Differential Revision: D9491481

Pulled By: hramos

fbshipit-source-id: d6ec6992768eb0c0866a0317273e09fae5b8935e
@zmefz
Copy link

@zmefz zmefz commented Jun 21, 2019

So what are the exact steps required after upgrading an app to RN 0.59 so that it will be both 32bit and 64 compliant? I've seen several different suggestions so far such as this, this and this.

Add line from this answer:

ndk.abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'

Alternatively it can be (the same):

ndk {
    abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
}

Then create your build using this command:

(cd android && ./gradlew bundleRelease)

It will create Android App Bundle file, located at:

android/app/build/outputs/bundle/release/app.aab

Upload app.aab file to the Play Market.

This steps solved my issue. Hope it will help someone.

@antoinerousseau
Copy link
Contributor

@antoinerousseau antoinerousseau commented Jun 21, 2019

@shoopi12
Copy link

@shoopi12 shoopi12 commented Jun 21, 2019

@zmefz
Hey, I might have missed some documentation... I usually use a release APK file located at android/app/build/outputs/apk/release/app-release.apk.
What is the difference between release APK file and app.aab bundle exactly?

@Dror-Bar
Copy link

@Dror-Bar Dror-Bar commented Jun 23, 2019

@shoopi12 it's covered here and here.

@iagormoraes
Copy link

@iagormoraes iagormoraes commented Jul 18, 2019

@shoopi12 it's covered here and here.

Is this required, to generate an app ABB instead of APK for 1st august compliance.

@Dror-Bar
Copy link

@Dror-Bar Dror-Bar commented Jul 21, 2019

@iagorm I think it has to do with React Native 0.59+ which supports 64 bit (you can see it supports arm64-v8a and x86_64 in addition to armeabi-v7a and x86 in android/app/build.gradle).

I believe ABB is only to reduce overall APK size by creating a bundle that Goole Play later chooses just the necessary libraries to install on the device.

@saadsaleem187
Copy link

@saadsaleem187 saadsaleem187 commented Dec 11, 2019

I solved this issue by changing my Rest API URL from "http" to "https". If your API URL type is "http" it will not work on android 9. By changing to "https" my app is working fine now.

@pencilcheck
Copy link

@pencilcheck pencilcheck commented Dec 16, 2019

This article seems to work for me, esp the part about "Better solution"
https://badoo.com/techblog/blog/2017/06/30/integration-react-native-in-an-existing-application/

@facebook facebook locked as resolved and limited conversation to collaborators Feb 1, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
You can’t perform that action at this time.