I am attempting to build all ABIs for my project but would only like to package a subset of them into my app. For example, I would like to build "x86", "x86_64", "armeabi-v7a" and "arm64-v8a" but only package "x86" (for example).
Reading this document (https://developer.android.com/studio/projects/gradle-external-native-builds.html#jniLibs) under section "Specify ABIs", it seems very possible using the snippet they provided as an example. However, this does not seem to be working for me.
My code snippet is as follows.
android {
defaultConfig {
ndk {
abiFilters 'armeabi-v7a'
}
externalNativeBuild {
cmake {
abiFilters 'armeabi-v7a', 'x86'
}
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
In the snippet above, from my understanding of the document, it should build both armeabi-v7a and x86, but only package armeabi-v7a in my APK. This is not working though.
I am using Android plugin 3.1.0 and NDK 16.1.4479499
what you are looking for, is controlled by splits.
splits {
abi {
enable true
reset()
include 'armeabi-v7a'
universalApk false //don't generate an additional APK that contains all the ABIs
}
}
Related
I need to have a separate CMakeLists.txt for each Android ABI. I tried to use product flavor to set the path for CMakeLists.txt. But I am getting following error on running ./gradlew assembleDebug or any other gradle command from command line.
Could not find method path() for arguments [CMakeLists.txt] on object
of type
com.android.build.gradle.internal.dsl.ExternalNativeCmakeOptions.
Here is how I have set product flavor in build.gradle.
productFlavors {
arm64_v8a {
ndk {
abiFilters "arm64-v8a"
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
x86_64 {
ndk {
abiFilters "x86_64"
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
}
NOTE - I had initially named the files as "CMakeLists_arm64-v8a.txt" and "CMakeLists_x86_64.txt". But that was failing so tried same name.
How to fix this or is there a workaround for this?
No, you cannot have CMakeLists.txt paths different for different flavors and/or ABIs, but you can use the arguments to add conditionals in your cmake script, for example like this:
flavorDimensions "abi"
productFlavors {
arm64_v8a {
dimension "abi"
ndk {
abiFilters "arm64-v8a"
}
externalNativeBuild {
cmake {
arguments "-DFLAVOR=ARM"
}
}
}
x86_64 {
dimension "abi"
ndk {
abiFilters "x86_64"
}
externalNativeBuild {
cmake {
arguments "-DFLAVOR=x86"
}
}
}
}
Now you can check this in your CMakeLists.txt:
if (FLAVOR STREQUAL 'ARM')
include(arm.cmake)
endif()
But in your case, you can rely on the argument that is defined by Android Studio, and don't need your own parameter:
if (ANDROID_ABI STREQUAL 'arm64-v8a')
include(arm.cmake)
endif()
Actually, you probably don't need separate productFlavors at all, but rather use splits to produce thin APKs for each ABI.
I would like to have multiple android builds, but it isn't building the way I would like.
I am using Android Studio to make my app and build it with the following productFlavors in the gradle file:
android {
productFlavors {
armv7 {
ndk {
abiFilters "armeabi-v7a", "x86"
}
}
}
}
When I have Android Studio build the application, it only builds the x86 version. If I remove the x86 from the flavors, it builds armeabi-v7a. How can I get it to build both versions?
You should probably do this to get both:
android {
productFlavors {
armv7 {
ndk {
abiFilters "armeabi-v7a"
}
}
x86 {
ndk {
abiFilters "x86"
}
}
}
}
I want to add ndk.abiFilters property in gradle.properties file. Now I've this property inside build.gradle.
Here is part of my build.gradle
buildTypes {
debug {
ndk {
abiFilters "x86", "armeabi-v7a", "armeabi"
//abiFilters ABI_FILTERS
}
}
}
Here's part of my gradle.properties file
ABI_FILTERS = "x86", "armeabi-v7a", "armeabi"
Problem is that String from gradle.properties is not correctly converted for use with abiFilters. I tried many variants but with no luck. What is the correct way how to do this correctly? Thank you for help.
In gradle.properties you can have for example:
ABI_FILTERS=armeabi-v7a;x86 //delimiter can be anything (change below)
Then in build.gradle there is (for example in debug buildType section):
ndk {
abiFilters = []
abiFilters.addAll(ABI_FILTERS.split(';').collect{it as String})
}
Now each developer can choose independetly abi for his current testing device (gradle.properties is in .gitignore).
Thanks Igor Ganapolsky for starting hint.
Following works with Gradle 2.3:
abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a'
gradle.properties file
ABI_FILTERS = ["armeabi", "x86"]
build.gradle file
ndk {
abiFilters = []
abiFilters.addAll(ABI_FILTERS)
}
Use this:
flavorDimensions "abi"
productFlavors {
arm7 {
dimension "abi"
ndk.abiFilters 'armeabi-v7a'
}
x86 {
dimension "abi"
ndk.abiFilters 'x86'
}
}
You can see an example of this setting in the Google samples for NDK: https://github.com/android/ndk-samples/blob/8132651aba8db36b14e0d0461c7cb46d3778f99c/other-builds/ndkbuild/hello-neon/app/build.gradle
This can also be done for flutter.
Add:
android{
buildTypes{
debug {
ndk {
abiFilters 'arm64-v8a'
}
}
}
}
to android\app\build.gradle. That works to remove the x86 libflutter.so libraries from the debug builds and shortens installation time. Works for gradle 7.2
In my application I use renderscript which has native code for x86, armeabi-v7a and mips (~2.7Mb each). Also I read that the mips architecture has just a few devices. So I'd like to bundle my application in two APKs: universal (eg. x86 and armeabi-v7a) and mips. I found that split section helps to create apk for mips, but universal apk still contains mips architecture. So my question is how to exclude abi from result apk?
Thanks
You can try setting up another flavor that contains everything but MIPS. In the build.gradle file from one of the test projects that are part of the Android Gradle plugin sources, I found this:
apply from: "../commonHeader.gradle"
buildscript { apply from: "../commonBuildScript.gradle", to: buildscript }
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion = rootProject.ext.buildToolsVersion
productFlavors {
x86 {
ndk {
abiFilter "x86"
}
}
arm {
ndk {
abiFilters "armeabi-v7a", "armeabi"
}
}
mips {
ndk {
abiFilter "mips"
}
}
}
}
It looks like their arm flavor basically includes the two common ARM ABIs. You could probably define an "universal" flavor containing x86 and armeabi-v7a.
They have another test project, whose build.gradle contains:
splits {
abi {
enable true
reset()
include 'x86', 'armeabi-v7a', 'mips'
}
}
You might be able to use something similar, and drop the mips from there.
I have an android APK that use a native library (snappydb).
The native libraries takes a lot of spaces, so I want to keep only the snappydb for armeabi-v7a architectures?
I know it's not 100% safe to remove snappydb for other architectures, so my question is: how unsafe it is? (how many devices/users will I lost?)
Just for reference, the minimal sdk version that my app support is 16 (JELLY_BEAN).
I suggest using Gradle's productFlavors to produce different APKs per ABI, as some ABI may include some assembly code optimization (SSE4, SSE5, Arm Neon etc,)
android {
...
flavorDimensions "abi", "version"
productFlavors {
freeapp {
flavorDimension "version"
...
}
x86 {
flavorDimension "abi"
...
}
}
}
Or if you're using the experimental Gradle plugin
'com.android.tools.build:gradle-experimental:0.1.0'
android.productFlavors {
create ("arm7") {
ndk.abiFilters += "armeabi-v7a"
}
create ("arm8") {
ndk.abiFilters += "arm64-v8a"
}
create ("x86-32") {
ndk.abiFilters += "x86"
}
// for detailed abiFilter descriptions, refer to "Supported ABIs" #
// https://developer.android.com/ndk/guides/abis.html#sa
// build one including all productFlavors
create("fat")
}
You will probably not gain too much from arm-v7a optimization, and currently there is no compelling reason to include 64-bit build. But MIPS and X86 owners will thank you if you keep their devices covered.