I do not use Android Studio but I do everything from the command line. I am building different APKs for different architectures so my build.gradle looks like this:
...
splits {
// Configures multiple APKs based on ABI.
abi {
// Enables building multiple APKs per ABI.
enable true
// By default all ABIs are included, so use reset() and include to specify that we only
// want APKs for x86, armeabi-v7a, and mips.
// Resets the list of ABIs that Gradle should create APKs for to none.
reset()
// Specifies a list of ABIs that Gradle should create APKs for.
include "armeabi", "armeabi-v7a", "arm64-v8a"
// Specifies that we do not want to also generate a universal APK that includes all ABIs.
universalApk false
}
}
I then use the method described here to assign different version codes to the individual APKs.
This all works fine except that when I say
./gradlew tasks
there is only one task named installRelease. Running this task will then automatically choose an appropriate APK and install it.
However, I'd like to test the individual APKs separately, i.e. on my 64-bit Android device I'd first like to test armeabi, then armeabi-v7a, and finally arm64-v8a. When running installRelease, however, gradle will always automatically install arm64-v8a. So how can I force gradle to install a specific architecture?
Previously, I was using this code in build.gradle instead of the splits code shown above:
productFlavors {
arm7 {
// in the future, ndk.abiFilter might also work
ndk {
abiFilter 'armeabi-v7a'
}
}
arm8 {
ndk {
abiFilters 'arm64-v8a'
}
}
arm {
ndk {
abiFilter 'armeabi'
}
}
}
When using this code, gradle offered individual tasks named installArmRelease, installArm7Release, and installArm8Release which was exactly what I was looking for but I had to drop this code because I didn't find a way to use it alongside the code that generates different version codes for the individual APKs as described here.
Related
I am trying to reduce my Android app. It has a differenct packages, a client package which depenend of bunch of other packages. I am analyzing the APK and saw there are so files for different paltforms namely x86 and armeabi-v7a. I dont want x86 currently. I am using splits to restrict the so files for x86 platform with following code in my build.gradle file.
splits {
abi {
enable false
// By default all ABIs are included, so use reset() and include to specify that we only
// want APKs for x86 and x86_64.
// Resets the list of ABIs that Gradle should create APKs for to none.
reset()
// Specifies a list of ABIs that Gradle should create APKs for.
include "armeabi-v7a"
// Specifies that we do not want to also generate a universal APK that includes all ABIs.
universalApk false
}
}
But still I could see the x86 files. Can someone help me in what I am doing wrong?
Use abiFilters from NdkOptions to include the native libraries only of certain ABIs.
Example:
android {
// Similar to other properties in the defaultConfig block, you can override
// these properties for each product flavor in your build configuration.
defaultConfig {
ndk {
// Tells Gradle to build outputs for the following ABIs and package
// them into your APK.
abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a'
}
}
}
I know that there was an option to exclude ABIs when generating splits in Gradle which looked like this:
android {
splits {
// Configures multiple APKs based on ABI.
abi {
// Enables building multiple APKs per ABI.
enable true
// By default all ABIs are included, so use reset() and include to specify that we only
// want APKs for x86 and x86_64.
// Resets the list of ABIs that Gradle should create APKs for to none.
reset()
// Specifies a list of ABIs that Gradle should create APKs for.
include "x86", "x86_64"
}
}
}
And here is the official reference to splits configuration
Now it is recommended to use App Bundles when publishing your App to Play Store and I don't see any option to exclude ABIs from this bundle either by using Gradle or Play Store publishing console.
The only clue I found so far is that you can enable/disable a particular split variant. For example here is how to disable ABI bundle splitting completely according to documentation:
android {
// When building Android App Bundles, the splits block is ignored.
splits {...}
// Instead, use the bundle block to control which types of configuration APKs
// you want your app bundle to support.
bundle {
abi {
// This property is set to true by default.
enableSplit = true
}
}
}
But there no mention on how to disable/enable a specific ABI set.
I already have abiFilters specified to exclude not supported NDKs, but it looks like it has no influence on App Bundle.
Update: I assumed that abiFilters are specifying ABIs to exclude from the App Bundle but it was exactly opposite and their porpose is to list ABIs to be included. After this clarification, everything seems to be working correctly.
abiFilters is the way to go. Specify the list of ABIs you want to include, and the other ones will be excluded.
You don't need the "splits" block for Android App Bundles: it's ignored.
If this doesn't work for you, then could you please provide the Gradle config with the abiFilters set, and say how you determine the ABIs present in the App Bundle?
Here is my problem. I am working on an already quite large Android application, and am adding a native library.
I would like to build only for armeabi-v7a while I am testing, for various reasons. My test phone has this abi, and I have issues building some third party libraries with some ABIs at the moment.
Now, I already googled / SEed for how to filter ABIs.
I have added in my app build.gradle the following :
splits {
abi {
enable true
reset()
include 'armeabi-v7a'
}
}
defaultConfig {
externalNativeBuild {
cmake {
abiFilters "armeabi-v7a"
}
}
}
To be safe, I duplicated this config in my modules build.gradle.
However, running a build results in CMake errors, saying it cannot find some tools for ABIs mips and x86_64. (I actually don't have them)
It would really help if someone could suggest why gradle would ignore the abi configuration entries, and how I could solve this.
In my app I'm using "de.mrmaffen:vlc-android-sdk:2.0.6" library and it's taking much storage but I can't find a smaller alternative.
So I decided as CommonsWare mentioned to use splits or product flavors but I can't get it to work.
I tried to follow the docs with no luck.
Any help appreciated.
Building the LibVLC Android SDK yourself
If you are using "de.mrmaffen:vlc-android-sdk:2.0.6", buid the LibVLC Android SDK yourself
As explained here, afterwards simply run this Gradle command: ./gradlew buildLibVlc
Building a specific version of the LibVLC Android SDK
cd vlc-android // if this folder doesn't exist yet, simply run ./gradlew cloneVlcAndroid
git tag // to list all release versions
git checkout {tag-name} // to checkout the git repo at the given tag
cd ..
./gradlew buildLibVlc // build it
Make sure you followed the Android compile instructions in terms of dependencies and check this:
git clone repo.
open up a command prompt in this repo. "cd" or change directory into
it.
git clone .
change directory into the vlc-android directory.
git tag
git checkout <tag_version>. In this case, 2.1.2.
cd ..
comment out both the compile/build of the build.gradle script that
you don't need.
./gradlew buildLibVlc
you should have a successful build with both the Java sources and
shared object (*.so) files in the jniLibs folder.
create a libs folder right next to the jniLibs folder if you
updated the gradle version.
Get it via Maven CentralJCenter
Just add this dependency to your project and you're good to go.
dependencies {
implementation 'de.mrmaffen:libvlc-android:2.1.12#aar'
}
I'm using this version. Remember to add JCenter to your project's build.gradle file:
allprojects {
repositories {
jcenter()
}
}
VLC Android SDK via JCenter supports the next ABIs: armeabi-v7a, arm64-v8a, x86 and x86_64.
You can filter specific ABIs in your app's build.gradle file (x86_64 and arm64-v8a are excluded):
android {
ndk {
abiFilters "armeabi-v7a", "x86"
}
}
It's possible to check included files in mrmaffen's repository and via recent Android Studio versions:
Configure multiple APKs for ABIs
Add an abi block inside
your splits block. In your abi block, provide a list of desired ABIs. Source
android {
...
splits {
// Configures multiple APKs based on ABI.
abi {
// Enables building multiple APKs per ABI.
enable true
// By default all ABIs are included, so use reset() and include to specify that we only
// want APKs for x86 and armeabi-v7a.
// Resets the list of ABIs that Gradle should create APKs for to none.
reset()
// Specifies a list of ABIs that Gradle should create APKs for.
include "x86", "armeabi-v7a"
// Specifies that we do not want to also generate a universal APK that includes all ABIs.
universalApk false
}
}
}
Build multiple APKs
Click Build > Build APK to build all APKs for the currently selected
module in the Project pane.
Gradle creates the APKs for each ABI
into the project's build/outputs/apk/ directory.
Configure Build Variants
This page builds on the Configure Your Build Overview to show you how you can configure build variants to create different versions of your app.
Combine abi filters and build variants
Exclude abi from apk
android {
productFlavors {
x86 {
ndk {
abiFilter "x86"
}
}
arm {
ndk {
abiFilters "armeabi-v7a", "armeabi"
}
}
}
}
Multi-APK through ABI and density splits
How to reduce the number of APKs with ABI splits
Here’s
a code snippet that you can use to set version codes for ABI splits.
Give the x86_64 and x86 higher version numbers than ARM, as many x86
devices can run ARM code through an emulation layer, although with
lower performance.
If you don’t wish to manage too many APKs, target the most popular
ones (usually ARM and maybe x86) with a split APK and serve a
universal APK to everyone else.
It’s vital that you publish the universal APK on the Play Store with a lower
version number than all other ABI-specific packages.
If you need more flexibility for your Multi-APK setup, check out
Multi-APK through product
flavors.
Recommended Medium post to choose supported ABIs
In this
post
we will understand what is ABI, problems with the ABI split, and
alternative way to avoid those problems... For instance, Android supports the following ABIs :
mips, mips64, X86, X86–64, arm64-v8a, armeabi, armeabi-v7a
So you have to take a call on supporting 64-bit libraries based on
size vs performance criteria but mips, mips-64, and armeabi should be
removed without any hesitation.
Solve UnsatisfiedLinkError Problem on some devices
As explained here, 64-bit processors generate and check arm64 folder to load native libraries.
If your project does not have arm64 folder. Here is the solution:
build.gradle
defaultConfig {
...
ndk {
abiFilters "armeabi-v7a", "x86"
}
}
You need to add this filters(abiFilters) to your app module’s
build.gradle files. So when your device try to run your app, it will
check gradle file and understands that it should not generate any
folder and use existing native library resources. Boom. Almost solved.
But still there is one more thing. Add this line to your gradle.properties to use deprecated Ndk.
gradle.properties
android.useDeprecatedNdk=true
You can use app bundle so you don't need to handle multiple apks. Google Play will handle it for you automatically. Plus this approach can provide additional benefits. For more details: https://developer.android.com/guide/app-bundle
I am using arcgis in my app and it bundles native dependencies that are large in size. I don't want to include the x86 dependency if it means reducing the size of the apk. How do I tell gradle to automatically exclude the x86 native library.
I tried removing it manually during the build. but it shows up again after rebuild.
how do I tell gradle to automatically exclude the x86 native library
Use splits:
android {
// other good stuff here
splits {
abi {
enable true
reset()
include 'armeabi-v7a'
universalApk false
}
}
}
This tells Android to build only an ARMv7 version of your APK. You would need to adjust the include line to list what APKs you want.
However, you may be better served using splits to just build a separate x86 APK file (have include 'x86', 'armeabi-v7a') and ship both, so you better support x86 but still have smaller files.