I have some libraries that use native components, the libraries are built with NDK for 32 bit Arm architectures.
now we have 64-bit processors on modern devices, so I'm wondering if the libraries will work. In my situation, I don't have the source code files of the native library, just the SO files, I can't build them for 64-bits.
So will the 32-bits libraries run on 64-bits processors? or I have to re-build them?
**
EDIT
**
In my scenario I have the following:
1- I distribute the APK manually, didn't publish to Google Play yet.
2- The project has two native libraries, one with 64 & 32-bits support and the other with 32-bits only.
Is there a way to make the application work on 64-bits devices without having to publish to Google Play for now? can I remove the 64-bits libs to enforce the package manger to load the 32-bits ones?
The 32 bits libraries will work just fine on 64 bits processors.
As long as the libraries get installed the right/official way (i.e., not manually downloaded or extracted from some nonstandard part in the APK, but packaged properly in the APK), the package manager will detect that the process uses 32 bit libraries, and the process should be started in 32 bit mode. If not, the process will be started in 64 bit mode, and later will be unable to load 32 bit libraries. (If your APK would contain some .so files, but not all, in 64 bit mode, it would only install them, and the process would be launched in 64 bit mode. So unless all .so files are available for a specific ABI, don't include any of them).
So if you have a 64 bit version of one of the native libraries, just remove that and only ship the 32 bit version, until you have 64 bit versions of all of them.
Related
I have upgraded my react-native project to 0.59.x so that it may provide a 64 bit version.
I now need to check whether each library I use provides a 64 bit version, such as react-native-firebase or various other popular libraries.
I've already decompressed the APK and observed that x86_64 contains files with the same names as in the x86 directory. My concern is that because my upgrade path was so complex and fraught with issues/hacks, and I'm using very old libraries which seem less likely to have 64bit versions, that perhaps some of those libraries within x86_64 directory might actually be 32 bit.
I feel like there must be some way, such as inspecting the .so files within the directory some way.
NOTE:
I understand that only libraries which provide native code will need to provide 64 bit version.
I assume React Native 0.59.x does not somehow guarantee my libraries are compiled to 64 bit also. I assume it's up to me to find a version of each library which also provides 64 bit version. If this is not true, and simply upgrading to 0.59.x does somehow guarantee my libraries are compiled to 64 bit, then tell me that and my entire question itself is solved. This seems extremely unlikely though.
My paranoia stems from using OLD react native libraries and then using this hack to bypass version mismatch issues during build.
Check out this issue, read the discussions, according to this if your any library is not 64 bit compatible it won't be compiled into 64 bit. And build won't be happening! If you have that kind of problem. Then you can detect which library is compatible or not!
In another way, you can do the split by ABI setting true def enableSeparateBuildPerCPUArchitecture = true
Produce the 64-bit version apks and check it out on 64 -bit version phone or emulator.
Can I use "adb install" command to install an app intended for 32bit systems on my x86_64 Marshmallow system?
The app has opencv implementation only for x86 (because it uses opencv 2.4) which means that the libopencv_java.so libraries files is only in the 'lib\x86' directory inside the .apk file (There are other subdirectories of 'lib' directory without library files inside).
I'm not too good with Android system, so the question may seem credulous to some of you, but please help me if you can - I really need to install this app on my smartphone.
The 64b Android can run the 32b applications in compatibility mode (at least the ARM for sure, but I think x86 too, otherwise many of old legacy applets in market would be not working on 64b OS).
To make sure the 32b .apk works in emulated 32b mode, it has to contain ONLY 32b libs variants. If you have multiple native libraries from different vendors, some with 32b support only, and some with 64b support included, delete the 64b variants everywhere (but make sure those libs do have 32b variant, although that would be again a bit insane, to release anything for 64-only).
The true 32b OS will not mind 64b libraries, so rather validate manually by checking the zip (apk) content. Only 64b OS will be confused if some libraries are 64b and others are not.
Such .apk with valid set of libraries should work both when installed from GooglePlay market, or by adb install some.apk from PC.
Why didn't you simply try to install it? Or does it fail and how? If it fails and you think the 32b libs are the problem, verify the 64b libs folders are non-empty, so some other library triggers 64b mode. If they are empty, the app should work, and any other problem is probably unrelated to 32b opencv.
I have an Android app that uses some JNI code. Long story short (pun intended), it is nearly impossible to convert the JNI libraries to 64-bit as it would require a lot of changes. The code (both Java and JNI) works nicely on armeabi-v7a architecture.
The libraries are being loaded using loadLibrary. When I attempt to run my app on a Nexus 6, the app loads fine. As soon as loadLibrary is executed, the app crashes with the error described here.
The problem, as I understand it, is that when executing on Nexus 6, the app builds as arm64-8a. But the libraries are not built for arm64-8a (as the 64-bit version has issues I mentioned at start of the question).
My question is, can I force arm64-8a devices to also run armeabi-v7a code? How do I force my app apk to be armeabi-v7a so it is only 32-bit regardless of device?
Yes, arm64-v8a devices can also run armeabi-v7a code.
When the APK is installed, the installer checks if the package contains libraries in the official directories, and marks the activity as 32 or 64 bit depending on the outcome.
If it finds libraries in lib/arm64-v8a within the APK (normally taken from the directory libs/arm64-v8a in the build directory), it will be marked as 64 bit, and will ignore all other directories. If it finds libraries in lib/armeabi-v7a or lib/armeabi in the APK, the process is marked as 32 bit. If there's no native libraries in any of these, the installer assumes that the application doesn't use native code at all and is free to run it in either mode, in practice in 64 bit mode.
Now if you do ship some, but not all, libraries in 64 bit mode, the process will be launched in 64 bit mode and will be unable to load the 32 bit libraries (which won't even be installed). In this case, you must avoid bundling any 64 bit libraries unless all of them are available.
Or you don't use the official libs directory but install your libraries some other way (e.g. by downloading them at runtime or keeping them in e.g. assets), the system has no idea that your process wants to run libraries in 32 bit mode (at which point it is too late to switch to the other mode). In these cases, make sure to include at least some dummy library in the normal/official way, in order to flag the application as 32 bit.
See https://stackoverflow.com/a/33919454/3115956, https://stackoverflow.com/a/27713998/3115956 and https://stackoverflow.com/a/35450911/3115956 for answers to similar issues.
I have been distributing my app with armeabi and armeabi-v7 versions of native binary but recently started to get a lot of UnsatisfiedLinkError errors where "somehow" one of the native binaries (app has few) isn't extracted/copied on install. I can't reproduce it but it looks like this is due to size of the app being near to 8 MB.
I want to stop including armeabi-v7 in the app to save near enough 2 MB and done some tests on 3 devices I have. Everything seems to be working. I also noticed (for example) Dropbox only distributes armeabi.
Would you advise against it? And yes, native binary does some number crunching and encoding but there is no optimization in build script?
8 MB should not be a problem. However, you can safely drop armeabi-v7a if you verify that it is not performance bottleneck.
Alternatively, you can use the multi-APK approach to make user downloads smaller. The official site recommends: You should generally use multiple APKs to support different device configurations only when your APK is too large (greater than 50MB). You should carefully follow the version code guidelines if you choose this route.
I've compiled ffmpeg library for usage in my Android apps, so now I have *.so files and I want to use them in other Android projects.
But I've compiled them in Linux and now I am going to work in Windows. Can I just put these compiled files to my project in Windows link them in mk file and use? Does difference between 32 and 64 bit OS play role?
Thanks!
As long as your target android platform is the same, it should work.
The .so file generated by Android NDK compiler is native code of the target android platform.
It is just packed into the APK intact, so the OS you use to pack the APK doesn't affect the outcome.
EDIT:
As a commenter suggested, by target platform I meant CPU architectures like ARM, x86 or MIPS
As to the API level, neither targetSdkVersion nor minSdkVersion doesn't directly affect the native code.
Rather, your code may fail at runtime, if you use higher level API than is available on the actual Android device.
To avoid this safely, you need to set your minSdkVersion according to the NDK API level which was assumed when compiling your .so file.
In other words, files under "<your-ndk-dir>/platforms/android-<NDK-API-level>/arch-<CPU type>/usr/..." should have been looked up by the NDK compiler when you compiled your native code. Identify which level was used, and make sure you have equal or greater number as minSdkVersion.
If you have NDK installed, it's documented in "<your-ndk-dir>/docs/STABLE-APIS.html".