I am developing an application that must be compatible with all Android device architectures. Also, some of these devices may have UHF reader capabilities that I want to exploit.
For these special devices, I have a shared library for the armeabi architecture. In devices with this architecture, the application works fine (whether they have UHF reader or not). However, for devices with other architectures, the application is not even installed, with an INSTALL_FAILED_NO_MATCHING_ABIS error.
I want to know if there is any way to make the library optional, so that devices of other architectures simply ignore it.
It would be ok if I could explicitly load the library (or not, depending on the architecture) using
System.loadLibrary("DeviceAPI");
but I don't know how to fix the installation problem. I want to avoid generating more than one APK.
Ok, this is surely not the best way to go, but it seems to work. I simply created a dummy shared library for every missing platform and renamed the .so files with the same name as my armeabi library file. The app installs now in every platform and I only have to catch the proper exceptions at initialization or check the device architecture.
Related
How could it be possible to build an AOSP app from source (using mma to build so there would only be the needed modules instead of a full system image) and have access to shared libraries?
I'm building LatinIME with some modifications.
As I wanted to easily install and debug, I changed the package name. Now I can easily install the app as user app but it can't access the .so files in system partition. If I try to install the app with original package name, it can't because of the old app installed.
library "/system/lib64/libjni_latinimegoogle.so" ("/system/lib64/libjni_latinimegoogle.so") needed or dlopened by "/system/lib64/libnativeloader.so" is not accessible for the namespace
The other way I could think of is to keep the package name as original but either create a flashable zip or copy the apk each time to system partition.
Is it possible to allow access to this file (or include it in the apk) or do I need to do this the hard way?
The easiest path is to have a copy of all needed non-public system native libraries in your APK, under lib/arm64-v8a or the other relevant ABI. libjni_latinimegoogle.so may depend on other libraries, and you must pack them with your APK, too. Make sure you use the correct versions of these libs. You can pull them from your system/lib64 via adb.
But replacing the APK in the system partition is a cleaner way to handle the situation. This does involve reboot each time, but I would probably choose this track, to avoid any possible behavioral differences between the system app and the user app.
I have written one c file native code for an Android application but when I build the apk and when I want to release that apk, it only supports four CPU's architecture.
Please tell me how to resolve that problem? I want to make the apk which supports all types of CPU architectures.
This should be happening automatically if you're using the canonical build process (i.e. Android Studio with externalNativeBuild). If it isn't, update your NDK/SDK/gradle plugin.
If that still doesn't do it, you can try explicitly listing all the ABIs you want to support: Add abiFilters to gradle properties
Also note that you really don't want a single APK with libraries for all ABIs, as that would be a very large APK with mostly unused stuff in it. What you really want are app bundles which will automatically include only the libraries for the device the user is installing the app too.
I am using OpenFL to build an Android app to distribute on Google Play. I want to target only armv7 devices, and I believe OpenFL does armv7-only builds by default.
However when building the OpenFL build system creates and populates the libs/armeabi folder instead of a libs/armeabi-v7a folder. The problem with this is that this makes Google Play believe that the resulting apk supports armv5/armv6/armv7 when in reality it only supports armv7. This means my apps get some 1-star reviews from people with the older/incompatible devices.
On this Github issue, Joshua Granick (jgranick) explains why the build tools do this:
Oh and BTW, originally we tried only armeabi-v7, but it failed to run on certain devices. This is why there's the current behavior or using armeabi, and adding armeabi-v7 only if there is an armv5/6 version too
I would like to know what the issue he mentions is, and what devices/Android versions it would affect. Depending on what it is, it may be possible to still just do an armv7 build and manually blacklist the buggy devices.
A final option is to simply support the armv5/armv6 devices by doing a "fat" build, or by only building for armv5 which I assume is compatible everywhere. This is quite easy using the <architecture> tag in the project.xml file. It's a tradeoff I may take if there is no way to work around the problem Joshua mentioned.
Also using the Google Play developer dashboard I could also blacklist armv5/armv6 devices manually, but it would be very time consuming to do this for every app/apk.
So my question is: how can I make armv7-only Android builds using OpenFL and get Google Play to only allow compatible devices, without running into problems like the one I quoted above? If that isn't possible, then what is my best option?
For reference here are the relevant Google Play apk details I get when I build armv7-only:
Thanks!
I got an answer on this GitHub issue. Some armv7 devices or the versions of Android on them cause apps to crash when there is no libs/armeabi folder in the apk. Joshua explained how this led to lime-tools (as of version 1.5.7) setup:
in my Samsung Galaxy S (perhaps other devices) the applications would not run unless there was a "libs/armeabi" folder
If there are both folders, it prefers the armeabi-v7a directory, but otherwise failed to work. So that's why the tools use only a single folder if you target only armv7, and use both folders if you include armv5 and armv7 both.
I'm not sure of a good solution for this, I think the key point of friction here is the Google Play submission process, which should allow us to account for that.
Given this, the solution that works for me was to simply do fat builds of my apps and also support armv5/armv6 devices.
I need to distribute an application (a player), which depends on a native library built for a given ARM version and extension (Tegra, Neon). This native library is quite large so I can’t distribute all its versions in one universal package. So I decided to split the application into one small universal .apk and more specialized .apks – plug-ins without any activities.
How can I access a specialized native shared library in the plug-in app from the main host application? Is it possible to use simply
System.loadLibrary("path_to_library");
If so, how can I get the path to that library?
How to solve this problem in case it is not possible?
System.loadLibrary() takes a library name and maps it to a full path somehow.
foo => libfoo.so
The system normally checks the apk itself and then usually /system/lib/
If you have a full path, use System.load()
In any case it will be a hassle to manage the location of your lib unless it's either in the apk or with all the system libs.
I'd just pack the specific lib with the apk.
Eight years later, the major concerns of the TS have been addressed: there are splits that can produce smaller APK for each ABI, there are app bundles that allow easier packaging, there are extensions that even allow to delay download of a native library until it is really needed by the app…
Still, the same technique to System.load("/data/data/{app-package}/lib/lib{library-name}.so") still works, and may be useful in some scenarios.
We have a manufacturer that wants to pre-install our application on their Android device. We sent them the APK and even though it installs fine when used by a user, it appears to not get installed correctly when included in the manufacturer's build image. FYI, our application uses the JNI layer and some libraries built with NDK. The exception we're seeing seems to indicate that the class loader cannot find the library and is unable to load it. They have verified that the library files are indeed present in the APK.
Since we dont make devices, its unclear why they are seeing this exception and what needs to be done differently when including a package as part of the Android build image.
Any Android folks here care to comment?
I have worked with pre-installed Android apps, that also uses library files, in my case jar files. I am assuming that you have added the appropriate lines to AndroidManifest.xml like <uses-library android:name..... I am also assuming that you have provided instruction on how to install your library files on handset, with instructions like adb push ... on the command prompt. If you havent, do provide them the instructions.
Another issue may be permissions, we had to get the library jar AND the permissions xml file installed, that may be the issue.
Also ensure that you are using the correct version of Android for testing. And if everything fails, ask them to send one of the handsets that is not working to you and you can then compare with the one in office and debug this. Good Luck, as all this can be pretty frustrating.
Besides moving the apk file into /system/app, you should ask the manufacturer to move the native libraries created by NDK (.so files) to /system/lib or the path specified by LD_LIBRARY_PATH.
Please refer to https://groups.google.com/d/topic/android-porting/r_Ao7_PWgKQ for more details.