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.
Related
I am working with Xamarin Forms and I published the Android app ad-hoc to disc.
What I would like to do is to give the apk to some people to test by uploading it to a web site I have so they can download it. Here's what was created:
com.xx.xx-arm64-v8a.apk
com.xx.xx-armeabi-v7.apk
com.xx.xx-x86_64.apk
com.xx.xx-x86.apk
com.xx.xx.apk
My question is twofold. Why does it create four apps and which of those should I give to the person? I assume it's okay to give the last in the list but if that's the case then why are the others created?
I also heard something about a new feature with Android that would allow smaller builds and just let a person download the build that is needed for their device. Can someone tell me if I could use that with these apks and if so how I would do it.
Thanks
Here are the list of options that I have selected:
Please open your Android Options, If you enable the Generate one package (.apk) per selected ABI selection, you will get serveral .apk file. If you want to generate one .apk file, just unselect it like following screenshot.
If you want to enable the Generate one package (.apk) per selected ABIselection. you can give the .apk file by Users' device(CPU Architectures).
Xamarin.Android supports the following architectures:
armeabi – ARM-based CPUs that support at least the ARMv5TE instruction set. Note that armeabi is not thread-safe and should not be used on multi-CPU devices.
Note
As of Xamarin.Android 9.2, armeabi is no longer supported.
armeabi-v7a – ARM-based CPUs with hardware floating-point operations and multiple CPU (SMP) devices. Note that armeabi-v7a machine code will not run on ARMv5 devices.
arm64-v8a – CPUs based on the 64-bit ARMv8 architecture.
x86 – CPUs that support the x86 (or IA-32) instruction set. This instruction set is equivalent to that of the Pentium Pro, including MMX, SSE, SSE2, and SSE3 instructions.
x86_64 CPUs that support the 64-bit x86 (also referred as x64 and AMD64) instruction set.
If you want to know more details about CPU Architectures, you can refer to this thread.
https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/cpu-architectures?tabs=windows
while you are creating an apk Please make sure your Architecture should be armeabi-7a and armeabi-v8a in Project Properties - > Android Options -> Advanced.
after that Clean Solution.
than Please go for .apk Archive it will create simple Signed Apk which you can distribute.
Hope it helps.
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 a few native libraries that are fairly big and bloating the application binary size. I looked into APK splitting but maintaining and QAing multiple APKs is not something I want to do.
So I'd like to exclude unused architectures in my release build flavour using the ndk.abiFilters Gradle property. (The debug builds I want to leave alone so that I can run the HAXM-accelerated emulator on x86).
I was thinking of just having armeabi-v7a and arm64-v8a in my release flavour, but I'm not sure whether it is worth worrying about the market share of the other architectures I'm dropping. After a lot of looking around I cannot find any reference to market share of ARMv6 (armeabi), MIPS, x86 or x86_64. My intuition tells me that the latter three are almost non-existent, but I'm not sure about ARMv6.
I found this link on a forum that has a list of phones that use various architectures. Is there something more reliable somewhere? Maybe with % of users similar to the Android version dashboard?
Anything else I may miss if I just build my native libs for armeabi-v7a and arm64-v8a (or armeabi, armeabi-v7a and arm64-v8a)?
First off, if you're worring about binary size, you don't really need arm64-v8a, all those devices can run the armeabi-v7a binaries just fine. Only if you really need to cram the last extra performance out of it, it might be worthwhile.
As for armeabi and ARMv6; Android itself doesn't officially support it any longer, since Android 4.4 (October 2013) - and since Android 4.0 it should be much less common (from that version, AOSP source requires modifications to still build for ARMv6). So in practice, if you aren't supporting versions below 4.4, you can drop that one without any significant loss.
Also, for x86; many of those devices ship with surprisingly decent emulation of arm binaries, so those can manage with the armeabi-v7a version just fine as well.
EDIT: The above was written in 2015; these days Play Store requires that apps include support for arm64-v8a. But these days the next question is more about whether you need to include armeabi-v7a at all, or if the market share of 32 bit devices is small enough to drop support for.
Including additional architectures will no longer have any impact on the binary size when using app bundles, as in that case Google Play will serve each device only the binaries that apply to that particular device. Not only that, but also application updates will be way smaller and faster.
Leaving the previous information for projects still not using app bundles:
Unfortunately, the Android Dashboard, as useful as it is, does not provide architecture information, nor does Google Analytics.
The Unity statistics used to provide statistics per architecture and CPU features. Note, however, that these are not general statistics, but only cover users of Unity applications/games. The information doesn't seem to be available in a public link anymore, so I have replaced the direct links with the latest snapshots in archive.org.
I was stuck with this problem when using Mapbox, then later found this article which was very useful.
Based on the below picture you just need armeabi-v7a and x86. Then based on Jose Gómez answer, I only added armeabi-v7a and didn't have any problem at all.
So add this line to your app.gradle
android {
defaultConfig {
//other configs
ndk {
abiFilters "armeabi-v7a"
}
}
}
If you're still worried about 2% - 3% of those who use x86 architecture, like ASUS ZenFone and lenovo phones then use this config instead in app.gradle
ndk {
abiFilters "armeabi-v7a", "x86"
}
Also for genymotion emulators you should use x86 architecture
UPDATE
If you get this error while publishing the apk in play store
Then use this
ndk {
abiFilters "armeabi-v7a", "arm64-v8a"
}
And finally, I suggest you use app bundle for releasing the APK
When I read #mstorsjo answer I was a little bit confused how to really use only one (or two) native libs, even though it's quite simple and straightforward. Therefore, I will give here an example and some more explanation (based on my further research).
For each supported architecture we have to create a specific folder in the jniLibs folder and drop the .so file there. As an example, for supporting armeabi-v7a (32bit) and arm64-v8a (64bit):
|--app
|--|--src
|--|--|--main
|--|--|--|--jniLibs
|--|--|--|--|--armeabi-v7a
|--|--|--|--|--|--.so Files
|--|--|--|--|--arm64-v8a
|--|--|--|--|--|--.so Files
With armeabi-v7a you support more than 90% of the available devices, but since it is 32bit architecture, running it on 64bit devices will result in an loss of performance (20-30%) {1}. For each specific case it can be quite handy to check the actual amount of supported devices, which can be done within the Google Play Console in the Release management > Device catalog section, by specifying ABI as filter.
Attention
When you don't add binaries for all architectures you have to be aware of the following:
If your app contains any other native libraries, you'll have to make sure you only have the same versions of them as well. That is due to Android demanding that all loaded native libraries be built for the same architecture. For example, if the first native library loaded is armeabi-v7a, Android will look ONLY for armeabi-v7a libraries on all System.loadLibrary() calls after that. If it doesn't find that exact architecture, it'll throw the java.lang.UnsatisfiedLinkError exception. {1}
I ran into this problem because some of my dependencies used native libraries, whereby armeabi-v7a couldn't be loaded anymore.
When I install my app on a genymotion simulater device,it can not be installed well,on console I got "INSTALL_FAILED_CPU_ABI_INCOMPATIBLE"
I trid another app,it installed fine.I do not know why.
The application (certainly a game) must be ARM only.
Genymotion is a x86 platform, so compile the application to target x86.
You may be able to install ARM support manually :
http://forum.xda-developers.com/showthread.php?t=2528952
If you are using IntelliJ it may be related to the project's default configuration. IntelliJ will assume, unless otherwise specified, that Native libraries will be stored in the Libs folder. This is usually where developer store their JAR libraries. IntelliJ build process will package up the JAR file into the Native file folder in the APK.
If you experiencing this problem, you can find a good How-to:
INSTALL_FAILED_CPU_ABI_INCOMPATIBLE Intellj
This helped to resolve the issue I had.
You might want to check out my answer here:
INSTALL_FAILED_CPU_ABI_INCOMPATIBLE on device using intellij
I know it's written for IntelliJ, but you could be running into a similar issue with Eclipse where it thinks that some normal Java files or jar libraries are native code and including it in the compiled APK. A quick way to find out is to open up the final APK (it's just a jar file, so most utilities should be able to decompress it) and make sure that the only things you see are META-INF, res, AndroidManifest.xml, classes.dex, and resources.arsc. It's possible that there are other valid files in a normal Java Android application, but in general if you see anything else in there, particularly a libs folder, it's probably the result of the compilation process thinking that those other things are native libraries (compiled C/C++ code using the JNI).
If this is the case, you'll need to configure Eclipse to not interpret the Java libraries you're using as native code. Now, I don't personally use Eclipse so I don't know where the proper settings would be, but based off of this answer, it looks like Eclipse automatically assumes that the libs folder in the root of your project contains native libraries. The easiest solution may be to move any Java libraries you are using into a different folder (such as libraries).
http://blog.iteedee.com/2014/02/android-install_failed_cpu_abi_incompatible-intellj/
The INSTALL_FAILED_CPU_ABI_INCOMPATIBLE error is generated when you attempt to install an android application on a device with an unsupported CPU architecture. This error is usually related to the native libraries that are not packaged up for the device’s CPU architecture (ie: x86, ARMv6, ARMv7, etc).
Now, if you have an application that doesn’t use any native libraries or *.so file you might be scratching your head on this one. If you use IntelliJ IDEA IDE for your android development it might be packaging all of your related .JAR file in to the Native Library file location in your APK.
The cause of the same problem was different in my case.
I had added some dependency jars in /libs directory of my Android app project. One of these jars had exported library in jar format; i.e. a jar within a jar file. I've noticed that the apk created using jars with such structure are incompatible with x86 based devices (don't know why).
I have an Android application that only runs on ARM CPUs. This is due to the fact that I have included an ARM executable in the APK. However, after quite a bit of searching, I have been unable to find any way to indicate (in a manifest file or something similar) that the application will not run on other architectures.
Normally, applications that want to include native code include a shared library. In this case, the app only shows up in the Play Store for users with a compatible CPU. However, using a shared library is not an option for my app.
Is there some place in the project's manifest file or somewhere else that I can explicitly indicate the CPU architectures the app supports?
However, using a shared library is not an option for my app.
In theory, it should be. Create a do-nothing little JNI-compatible library with the NDK, and only build it for architectures that your packaged-in binary supports (e.g., ARMv5 and ARMv7). You probably don't even have to use the library (though I'd set up a Java class that references it to be safe, at least during initial testing). That should be enough to trigger Play Store filters, even if you never actually invoke the code at runtime.
IOW, use the NDK stuff just for filtering.
Personally, I'd rewrite your command-line binary to be a NDK-built JNI-compatible library, for performance reasons, but that's just me.
This is may be what you are looking for
TextView tv_showArch_View = (TextView)findViewById(R.id.ShowCPUArch);
String CPU_ABI = Build.CPU_ABI;
tv_showArch_View.setText(CPU_ABI);
It returned to me
ARMeabi for Emulator running on ARM processor
and
X86 for Emulator running on Intel processor
For More detailed information you can go thru Google's Official Documentation