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.
Related
Note - I am relatively new to Android and AOSP...
Where can I find the Android SDK in the AOSP? As we know, we build apk files in the android studio using the separately installed SDK. But for some reason, I wish to use the SDK in the AOSP if it is available. I see the source code of SDK in the AOSP; do we need to build it?
Why/How I have arrived at the above question:
I had created an .apk in the AOSP which had JNI files and dependency on some existing Broadcom libs (so). It is a system app. What I noticed is the .apk package does not contain the JNI libs but rather is copied to /system/lib folder separately. Hence I had a doubt how the .apk upgrade will work? Is it possible?
I assumed the .apk upgrade won't work that way and the .apk should be packaged including the JNI libs. Hence I planned to build the .apk in the studio and use the .apk as prebuilt and just sign it in the AOSP (we have the keys). Then I also wanted to allow the developers to build the .apk in AOSP itself by running the Gradle in the command line. I did so by adding the command to the Android.mk. But the point here is, it is still using the SDK installed in /home//Android/Sdk. But there may be build machines which may not have the SDK installed. So I am putting this question - Do we (where?) have the SDK in AOSP? Can I use that instead?
I tried to explain the problem.. in case it's not clear please let me know... Will try to give more details...
OTA update will work. Update with Package Manager - won't. This is normal for system apps with native libraries.
In AOSP applications are built differently depending on their location in build tree. Apps placed in ~/packages/apps and ~/device/some_vendor are system apps and they are handled differently by the system. One of differences is that during build process they are stripped of their native libraries and those libraries are simply copied to the /system/ partition.
Including pre-built apk is a good solution.
Yes you can build sdk yourself from sources. Yes, it's there. But I don't understand why you need that. Are there any changes to the API?
There are other options. For example, you can mangle your build scripts. Say, you can add a global FLAG that would disable lib stripping for system apps.
I have this native library that only works on certain devices (armeabi, armeabi-v7a). It provides support for a custom HW module.
I detect and enable this library in java code based on the device that actually supports it. There are no issues on arm devices that do not provide this custom HW.
However, if I try to install my apk to an x86 device (or emulator), installation will fail with INSTALL_FAILED_NO_MATCHING_ABIS.
How can I link the library into the app that would avoid the reported error? I don't care if it's an ugly hack, as long as the app installs and starts.
The device checks the content of libs directory in the APK which is (in default Gradle configuration) copied from src/main/jniLibs. If there are subdirectories and none of them is x86, it will report this error. The easy solution here is to create subdirectory x86 with some dummy file.
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 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.
As a follow up to an earlier question (Android ioctl - root permissions and usage), is it possible to create a separate native executable and package it in an APK?
The app needs root access and isn't going into the Android marketplace, but I'd like to be able to install it without using a script that pushes an extra executable onto the device.
There is an easy way to package an executable into an APK, and let the system installer take care of unpacking this executable, see How to package native commandline application in apk?.
The trick (tested up to Jelly Bean 4.3) is to name the file "libmyexecutable.so" and put it into libs/armeabi of your Android project (I assume an ADT or ant build). The Package Manager will unpack the file to /data/data/your.package.full.name/lib (it's a symbolic link, for backwards compatibility reasons, so maybe in some future version of Android this will not work anymore) on the device, with executable permissions.
Note that the file has all read-and-execute permissions, so you can use Runtime.getRuntime().exec() or system() from other apps, too.
Update:
These days, you should use libs/armeabi-v7a for 32 -bit ARM executables, and you probably need to prepare 64-bit ARM version of the same executables, too.
You can put it into assets and copy it to the app's private directory on first run. After you set the executable bit, you should be able to run it.