I am integrating a third party API into an Android application and must include their NDK libraries. I am using Android Studio w/gradle and putting all native libraries under:
src/main/jniLibs/
My question is this: they have provided '.so' libraries under the subdirectories:
armeabi/ mips/ x86/
Do I need to include all of these directories under jniLibs in my app?
The implementation instructions specified only 'armeabi', but then I am not sure why the other architectures are provided. The mips directory is about 3.2 MB and the x86 directory is about 6MB, so I do not want to package these in my app if not necessary. Not sure what they are for.
MIPS-powered devices take a relatively small market share these days, and this is the low-end (primarily in terms of retail price) segment of the market. Your app may be exactly fit for this niche, or you may not be interested to pursue this opportunity (note that marketing approach and even technical challenges are significantly different for the top-end and low-end targets).
On the other end, all Intel-based devices I saw, have decent ARM emulation built-in, exactly for the purpose to compensate for poor coverage of this platform by developers of native apps. So, if you are not concerned with the performance, you can painlessly drop the x86 support.
Actually, it might be more important to provide armv7-a version of your native libs, because use of advanced instruction set (especially with NEON) may boost performance of your app for a vast majority of users (most of the modern tablets and phone these days come with one of the chipsets that support these).
Furthermore, in less than a month, new ABIs will enter the market: 64-bit Intel and ARM devices, e.g. Nexus 6, running Android 5.0 Lollipop.
But ultimately, your primary concern probably is that the size of APK file that millions of your users will be downloading from the Play Store will be unnecessarily huge. To resolve this, there is a different technique, which allows you to split your APK and upload to Play Store separate versions, one for each ABI. The trick is that the version numbers should be managed carefully, to allow smooth upgrades for users of each platform. Here yours truly proposed (and Ashwin S Ashok improved) a version numbering scheme that helps manage this task.
Related
I've generated a release apk of my Android project in order to do some internal testing via the Developer Console.
Upon generating it, I clicked to analyze the APK file. From the picture I see most of my APk allocations go to libraries and assets.
I'm focusing on the architectures of ARM X86 and X64. I believe they are processor speeds on phones and
upon the APK being installed on a phone the Play Store will determine the phones processor and architectures and then download my APK based on that scenario.
My question is that with Android migrating to 64 bit architecture apps can't I get rid of the ARM architectures that aren't 64 bit based.
I'm unsure of what do do and would like to get rid of these extra architectures if possible to reduce APK size.
Please see the picture provided
Today, the vast majority of Android devices today are arm. The Device Catalog on the Play Console reports 98% of devices supported by Play are running on ARM. Although this number does not take into account devices not supported by Play or the number of users on each device, it still gives you an idea of the proportions.
That being said, regardless of the architectures you choose to support, when publishing to Play, you should always add support for 64 bits of that architecture. For example, if you want to support arm, you must have the libraries for arm64-v8a and if you want to support x86, you must have the libraries for x86_64.
However, to reduce APK size, there is now a better way: publishing an Android App Bundle. Play introduced this new publishing format to solve that exact problem: you publish a single App Bundle to Play, and Play takes care of generating the APKs optimized for each device, containing only the files needed for their device architecture, screen density and language (customizable).
All it takes is to enroll in Play App Signing in the Play Console (so that Play can sign the APKs it generates on your behalf), and select "Build Android App Bundle" in Studio instead of "Build APKs". -- If you use Gradle, gradlew bundleRelease instead of gradlew assembleRelease.
Hope that helps,
The reason I ask is related to Google's recent communication https://developer.android.com/distribute/best-practices/develop/64-bit regarding apps needing to support 64-bit devices. I am pretty confident my app supports 64-bit devices based on the suggestions mentioned in the article. When I install it from Google Play, it works exactly as expected, however when I test the APK locally using the ADB command on 64-bit hardware (as Google suggested in this section 'Test your app on 64-bit hardware'), my app has UI issues. I'm not sure why it's behaving inconsistently.
Is it possible that somehow the 32-bit version is being installed when using Google Play and therefore works fine? I'm concerned my app may actually have problems when truly installed as 64-bit, so any clarification on the inconsistencies described above would be appreciated.
The device I'm testing with is a 'Moto X Pure Edition' running Android 7.0. It has a Snapdragon 808 CPU which uses ARM architecture. On the other hand, we don't see any '/lib' folder as the Google article suggests to check. Our app is hybrid, built with Ionic v3.
There is no such thing as "installing as 32 bit" or "installing as 64 bit". I'll try to explain. This gets a little complicated, and you don't provide many details about your app. There are a few possibilities for how you have chosen to build your app.
You have no native code in your app (no .so libraries). It was written entirely in Java or Kotlin, and none-of the third party libraries you use use native code either. In this case the lib/ subdirectory of your APK you'd expect to be empty.
You do have native code in your app, but you have .so files (libraries) for all ABIs. In this case in your APK you'd expect to see multiple subdirectories under lib/ in your APK, with names like x86, armeabi-v7a, etc
You have native code in your app, but you are relying on ABI compatibility to work. That is your lib/ directory contains just armeabi-v7a as a subdirectory. x86, x86-64 and 64 bit ARM all emulate 32 bit ARM.
You have made more than one APK for each release of your app, one for each ABI. The is usually called multi-APK. So there is one for 64 bit ARM, one for 32 bit ARM, one for X86, one for X86 64 bit, etc.
You use the Android App Bundle, and let Google Play choose how to deliver your app.
By the way, I'd strongly recommend 5 as an option, it makes it much more likely the right thing will happen.
In the case of 1, 32 bit or 64bit doesn't matter. Any UI issues are caused by something else. Maybe the 64 bit phone allocates a bit more memory and your app doesn't perform well in low memory. Maybe the 64 bit phone is a bit faster and you've written your code with race conditions. Whatever it is, 64 vs 32 bit isn't the root cause.
In the case of 2, Google Play installs the same APK to every phone. But the device itself chooses which library (.so file) to load based on the processor. If one of your libraries was buggy on 64 bit that could be the issue.
In the case of 3, this is what Google's latest blog post is trying to stop. This won't be allowed to be published for new APKs. You need to properly support 64 bit devices by adding 64 bit native libraries. If this was the case, you could get bad UI performance by having the device emulate 32 bit arm on a 64 bit (possibly X86) device. You should switch to some other option, I'd recommend 5. This might not be you by the way, it might be some 3rd party library you depend on.
In the case of 4, Google Play does install different APKs to different devices based on processor type. Each different APK has a different version code. The device with a 64 bit processor will get the APK with the 64 bit libraries. If you are testing by putting the 32 bit version code on the 64 bit device using adb, you could indeed get bugs. However, if you were building and publishing different APKs for different APIs you would know it. Just install the right version code with adb.
In the case of 5, Google will install different APKs (in fact multiple different APK splits) to different devices. To test it, I'd recommend using a Google Play internal test track to verify to check exactly the right parts are installed which match Google Play.
I am building my Xamarin.Android project and I have selected AOT compilation which has bloated my .apk to 165mb.
To get my .apk size down I am looking at the target architectures, currently I target:
armeabi, armeabi-v7, x86, arm64-v8a
But I have no idea how these architectures correspond to modern devices.
I have read Android CPU Architectures and it says:
Xamarin.Android defaults to armeabi-v7a for Release builds. This
setting provides significantly better performance than armeabi. If you
are targeting a 64-bit ARM platform (such as the Nexus 9), select
arm64-v8a. If you are deploying your app to an x86 device, select x86.
If the target x86 device uses a 64-bit CPU architecture, select
x86_64.
Therefore do I need to target armeabi and armeabi-v7?
what archetectures should I target for a modern Android tablet and phone?
armeabi is for older devices as most newer devices run armeabi-v7. Secondly, 64 bit devices can fallback to other ABIs. If you're concerned about the size, then your best choice is to create multiple apks:
https://developer.xamarin.com/guides/android/application_fundamentals/cpu_architectures/#Targeting_Multiple_Platforms
Although Google recommends a single APK, this is not always the case:
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. To help you publish your application for as many devices as possible, Google Play allows you to publish multiple APKs under the same application listing. Google Play then supplies each APK to the appropriate devices based on configuration support you've declared in the manifest file of each APK.
https://developer.android.com/google/play/publishing/multiple-apks.html
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'm new to using Qt5 and I'm wondering how many compilers are needed to support the majority of Android devices? Which compilers cover the most devices.
In addition when submitting to Google Play do I have to specify a different build for every single device? Or do they have a method that lets you map APK files to compiler version?
Any advice for the process of going from Qt Creator to having an APK or multiple APKs that support the majority of devices.
You'll need to download additional API packages.
http://developer.android.com/sdk/installing/adding-packages.html
It depends on how many different API versions you want to support. As a first cut you can look at the Google Play Dashboard
http://developer.android.com/about/dashboards/index.html
which should give you an idea of the population of devices running which version of Android.
Given that Qt 5.x for Android supports API level 10 (Gingerbread), you should start there.
http://doc.qt.io/qt-5/android-support.html