Gradle dependency for specific architecture with ABI splits - android

Im facing this problem which seems im not able to solve. Here is scenario:
Im building apk which uses gradle dependency and this dependency is architecture specific so for apk for x86 i need different dependency and for arm different as well.
I solved it with product flavors:
productFlavors {
dev { ... }
develx86 { ... }
production { ... }
productionx86 { ... }
}
So then i defined dependency like this:
develCompile 'dependency_for_arm'
develx86Compile 'dependency_for_x86'
This works good. But recently i had to add to my application an usage of renderscript. I did it in this way:
renderscriptTargetApi 22
renderscriptSupportModeEnabled true
And after this when i uploaded apk on Google Play it says it's apk is suitable with arm, x86. I don't know how this is possible. As you can think it will crash on device with different CPU (if i generated apk for arm and user will execute it on x86 app will crash).
So i decited to use ABI splits:
splits {
abi {
enable true
reset()
include 'armeabi', 'x86'
universalApk false
}
}
//Ensures architecture specific APKs have a higher version code
//(otherwise an x86 build would end up using the arm build, which x86 devices can run)
ext.versionCodes = [armeabi:0, x86:1]
import com.android.build.OutputFile
android.applicationVariants.all { variant ->
// assign different version code for each output
variant.outputs.each { output ->
int abiVersionCode = project.ext.versionCodes.get(output.getFilter(OutputFile.ABI)) ?: 0
output.versionCodeOverride = android.defaultConfig.versionCode + abiVersionCode
}
But now when i see generated apk files, my dependency which is flavor-specific is not included into apk and apk will crash when i open section which uses API from this dependency.
Do someone know how to solve this issue? Or someone know why Google Play says that apk is for both architectures when i included renderscript? (Without it it works properly but i need renderscript).
Thank you for your time. I will appreciate any help.

If you look inside your APK, under lib folder, you should see that renderscript support mode added libs for other architectures than the one you're supporting.
You can keep your earlier configuration with ABI-specific flavors.
But in order to ensure that no libs for other architectures are included, try adding abiFilters to your flavors:
productFlavors {
dev { ... ndk.abiFilters 'armeabi-v7a' }
develx86 { ... ndk.abiFilters 'x86' }
production { ... ndk.abiFilters 'armeabi-v7a' }
productionx86 { ... ndk.abiFilters 'x86' }
}

Sorry I cannot comment inline yet.
What's in the apk, especially in res/raw/ and lib/?
Also, are you using gradle-plugin 2.1.0? (since you are using renderscriptTargetApi 22), have you tried Build-Tools 23.0.3?

Related

Nativescript: Add x86_64 libNativeScript.so for Android

I have Nativescript-vue project.
Because of Google play 64-bit requirement I am trying to add x86_64 native code.
All resources I found while researching say to do this:
In app/App_Resources/Android/app.gradle file:
android {
defaultConfig {
generatedDensities = []
applicationId = "com.foo.bar"
ndk.abiFilters 'armeabi-v7a','arm64-v8a','x86', 'x86_64'
}
aaptOptions {
additionalParameters "--no-version-vectors"
}
}
But 'x86_64' is ignored the output apk's lib folder contains only this platforms 'armeabi-v7a', 'arm64-v8a', 'x86'.
I found also this github issue , Nativescript team was saying that in the next release the 'x86_64' platform will be added, So i upgraded {N} , but there was no difference.
Also tried "ABI Split" config, that I found on the official {N} documentation & added 'x86_64' to be included:
android {
....
defaultConfig {
....
ndk {
abiFilters.clear()
}
}
splits {
abi {
enable true //enables the ABIs split mechanism
reset() //reset the list of ABIs to be included to an empty string
include 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
universalApk true
}
}
}
But also no difference.
Is there any way to achieve this manually?
Also any suggest, info, documentation will be helpful.
My config:
minSdkVersion="21"
targetSdkVersion="28"
Tried with "tns-android" version "5.3.1" & "6.0.0"
If you need anything else from my project/config... Tell me in the comments.
Android runtime v6.0.2 with support for 64bit is already out, the migrate command may not take you to the latest version of of tns-android always but a recent version.
You may manually update the version on package.json or removing and adding the platform back via CLI will take you to most latest version of the runtime.

ABI filters of extended Build Variants do not overrides its parents

In a project i need specific ABI filters per release and debug and some extneded build variants. It is ok and works fine with debug and release.
release {
.
.
.
ndk {
abiFilters 'armeabi'
}
}
debug {
.
.
.
ndk {
abiFilters 'x86', 'x86_64', 'armeabi'
}
}
When i extend new buildvariant that init each of these tow variants, abifilters is remained and do not change. For example i have debug_on_mainserver that inits debug. but i want to add another abiFilter. But it is still use debug abiFilters.
debug_on_mainserver {
initWith(buildTypes.debug)
.
.
.
ndk {
abiFilters 'armeabi'
}
}
I should say that may i can achive this with Flavor but i use 3 flavor for another reason (store type and handle store config and variables) and i do not want to add another flavor and mulitple my buildVariants variety. Beacuse it is logically should include in debug_on_mainserver.
How i can exclude or remove base abiFilters and add new one? Or is it another way to achive this?

Android Split ABI armeabi-v8a not working. i do not use ndk but have arm binary only work on armeabi-v8a

i have a arm 64bit binary that only work on armeabi-v8a. when i upload to google play other abi users get errors. i do not use ndk
i use this and works perfectly on armeabi-v8a. other people gave me bad reviews because google play showed my app to armeabi-v7a and other abi phones.
Process dd = Runtime.getRuntime().exec(s);
i want to know how to filter and give my app only to armeabi-v8a users. so i used abi splits it did not work always showed my app to other abi users. my gradle code is
splits {
abi {
enable true
reset()
include "armeabi-v8a"
universalApk false
}
}
The name of the ABI should be "arm64-v8a", not "armeabi-v8a".

barteksc/AndroidPdfViewer massive APK Size

We included this AndroidPdfViewer library to support viewing of PDF reports in the app. It lead to massive increase in APK size from 4.7Mb to 20.1Mb .
Is there a way to reduce this size. Let me know where and what to tinker around to help or solve this.
I am familiar with proguard and have it configure for my app with reasonable success.
Why resulting apk is so big?
As stated in the documentation by barteksc/AndroidPdfViewer
Android PdfViewer depends on PdfiumAndroid, which is set of native
libraries (almost 16 MB) for many architectures. Apk must contain all
this libraries to run on every device available on market.
Fortunately, Google Play allows us to upload multiple apks, e.g. one
per every architecture. There is good article on automatically
splitting your application into multiple apks, available here.
Most important section is Improving multiple APKs creation and
versionCode handling with APK Splits, but whole article is worth
reading. You only need to do this in your application, no need for
forking PdfiumAndroid or so.
API: https://github.com/barteksc/AndroidPdfViewer
You have to generate Multiple APKs for different devices, by doing this you can reduce the size of apk up to 10 MB less than previous. Add below code to build.gradle (Module:App)
android{
.....
splits {
abi {
enable true
reset()
include 'x86_64', 'x86', 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips'
universalApk false
}
}
.....
}
ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3, mips: 4, 'x86': 5, 'x86_64': 6]
import com.android.build.OutputFile
// For each APK output variant, override versionCode with a combination of
// ABI APK value * 1000 + defaultConfig.versionCode
android.applicationVariants.all { variant ->
// assign different version code for each output
variant.outputs.each { output ->
output.versionCodeOverride =
project.ext.versionCodes.get(output.getFilter(OutputFile.ABI)) * 1000 + android.defaultConfig.versionCode
}
}
Whatch video here https://youtu.be/bP05Vpp49hs for detail explanation on how to do it.
If anyone is looking for a lightweight pdf viewer for your app, then try this one
Use this library
It helped me to reduce the app size from 27MB to 10MB because of the barteksc-androidpdfviewer requires more space
I also faced the same problem, but this is very easy as of now to reduce the apk sizes by using android app bundles.
Firstly in build.gradle(Module: app) add these lines inside android { } brackets.
bundle {
abi {
enableSplit = true
}
}
This will handle apk splits on the basis of architecture.
Now, also remember to add this line in proguard-rules.pro
-keep class com.shockwave.**
If you will not add this line in proguard-rules.pro then your app will crash in release version.
Now, after this go to Build and then select, Generate Signed Bundle/apk. From here, generate a signed bundle. Bundles are generated in very same way, as the apk's are generated.
Then, upload your bundle(.aab file) on Google Play Console and you will see that every device gets different apks depending upon their architecture.
This is the most easiest way to reduce the app size.Multiple apk concept is more complicated.
So,I suggest you to use this way.

Android product flavors are not considered when using CPU ABI split in build.gradle

I want to make APK split based on CPU ABI according to http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits, however I want to split the APK only for a certain product flavor.
So my build.gradle file has the following product flavors plain and market. Actually I want the APK split to be performed when building market flavor.
android {
productFlavors {
plain {
}
market {
splits {
abi {
enable true
reset()
include 'armeabi', 'armeabi-v7a', 'x86', 'mips'
universalApk true
}
}
}
}
}
However, when I invoke gradle assemblePlainDebug and assembleMarketDebug, both of them produces the multiple APK. Is there something wrong with the configuration above?
I'm using com.android.tools.build:gradle:1.2.3.
I've been looking for a way to do this for a while and haven't found a solid solution. Something to do with the splits having to be run before resolving the buildTypes and productFlavors.
The Android Gradle - is use splits only for release possible? question had answer that I thought useful. It basically relies on a project property, passed in when building via the command line or continuous integration invironment, to set weather the split apk's option is enabled or not.
I used it like this:
splits {
abi {
enable project.hasProperty('splitApk')
reset()
include 'x86', 'armeabi-v7a', 'mips', 'armeabi'
universalApk true
}
}
and then depending on what falvour or build type you are building you can include:
./gradlew --project-prop splitApk assembleMarketDebug
This should then only enable the apk split when explicitly told too and should stay disabled for everything else.

Categories

Resources