Genereting Android density splits for 560dpi and 420dpi devices - android

While generating density Gradle splits are working fine for the named densities (like xxxhdpi). I am yet to find a way to create a density split for some different densities like 560dpi or 420dpi (e.g., for Google Pixel 3XL).
Here is how I am generating ABI + density splits
// ABI Splits related code
splits {
// Configures multiple APKs based on Application Binary Interfaces (ABI)
abi {
enable true // enables the ABIs split mechanism
reset() // Clears the default list from all ABIs to no ABIs
include 'arm64-v8a', 'armeabi-v7a', 'x86', "x86_64" // Spcifies a list of ABIs Gradle should createa APKs for.
universalApk false // false to skip generting the universal APK
}
// Configures multiple APKs based on screen density.
density {
enable true
reset() // Clears the default list from all densities to no denstities
include "mdpi", "hdpi", "ldpi", "xhdpi", "xxhdpi", "xxxhdpi" // Specifies a list of screen densities Gradle should create multiple APKs for.
compatibleScreens 'small', 'normal', 'large', 'xlarge' // Specifies a list of compatible screen size settings for the manifest.
}
}
And then, I am generating different versions for the generated APKs.
project.ext.abiCodes = ['armeabi-v7a': 1, 'arm64-v8a': 2, 'x86': 3, "x86_64": 4].withDefault{0}
project.ext.densityCodes = ["mdpi": 10, 'hdpi': 20, 'xhdpi': 30, "xxhdpi": 40, "xxxhdpi": 50, "ldpi": 60].withDefault{0}
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
def baseAbiVersionCode = project.ext.abiCodes.get(output.getFilter("ABI"), 0)
def baseDensityVersionCode = project.ext.densityCodes.get(output.getFilter("DENSITY"), 0)
if (baseAbiVersionCode != null) {
output.versionCodeOverride = ((baseDensityVersionCode + baseAbiVersionCode) * 100000) + variant.versionCode
}
}
}
However, with the above, some newer devices that are using densities like 560dpi are marked as not supported. The universal APK is a no go for me as I am hitting the maximum APK size (and I can't use extension files).
Any ideas on how to generate density split for those unnamed densities?

Related

Gradle - Android - APK Split Version Error - Ambiguous method overloading for method java.lang.Integer#plus

I was trying to split the apk based on architecture. It was working on another app. But not this one. This error gets happen each time trying to build the gradle.
Any ideas to solve this. I've tried some casting. but nothing happens.
Here's the full split code
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'
universalApk true
}
}
// map for the version code
project.ext.versionCodes = ['armeabi':1, 'armeabi-v7a':2, 'arm64-v8a':3, 'mips':5, 'mips64':6, 'x86':8, 'x86_64':9]
android.applicationVariants.all { variant ->
// assign different version code for each output
variant.outputs.each { output ->
output.versionCodeOverride = project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1000000 + android.defaultConfig.versionCode
}
}

How to reduce apk size if more than 60% of accumolate lib folder after apk anlysis?

I have seen bellow report from my .apk using android build->analysis apk.
I have used progrud bellow like
buildTypes {
release {
shrinkResources true
minifyEnabled true
zipAlignEnabled true
//Other parameters
debuggable false
jniDebuggable false
renderscriptDebuggable false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
But My debug apk size is 26.9 MB. When I want to build for release apk then its size become 23.5 MB. It is big in size.
Please help me for reduce my apk or reduce at least 60%. Thanks Enamul
Splitting apk is a good solution. But here is once more trick.
If you just include armeabi-v7a in your apk, that will be fine unless you support < 4.4 android versions.
ARMv6 is no longer supported by Android since android 4.4 (Oct 13)
See this Unity Statics, You just need to include ARMv7 & Intelx86 to make support your app 100% devices.
Now what you have to do is just include ARMv7 & x86 in your app. See abiFilter.
Add this to your app level build.gradle
buildTypes {
release {
ndk {
abiFilters "x86", "armeabi-v7a"
}
}
Press Sync
Build and check size
The only way it is to build apk for each abi
Here is short example:
android {
splits {
abi {
enable true
reset()
include "mips", "x86", "x86_64", "armeabi-v7a", "armeabi-v7a", "arm64-v8a"
}
}
}
You will get apk's for different architectures with single JNI lib in it.
But you also need to implement special versioning process for it, so there will be no problem to upload apk in Google Play.
Like this:
android {
def abiCodes = ['mips':1, 'x86':2, 'x86_64':3, 'armeabi':4, 'armeabi-v7a':5, 'arm64-v8a':6]
android.applicationVariants.all { variant ->
variant.outputs.each {
output ->
def abiName = output.getFilter(OutputFile.ABI)
output.versionCodeOverride = abiCodes.get(abiName, 0) * 100000 + variant.versionCode
}
}
}
Use lint and remove unwanted resources from your code.
This is link
Remove all unused resources from an android project
It may help you.

after split APK which one should I choose?

I split my apk application and I got multiple apk
now which one I will choose to import to my play store ?
You add all of them, Play Store chooses the right one for the user, depending on their device. Just be sure to use different version codes for every apk.
See official documentation for more information.
you can let gradle auto configure your version code, then upload ALL of the apps to the play store.
google's example below will auto append 001, 002 or 003 depending on the variant ('armeabi-v7a':1, x86:2, x86_64:3).
do note that you will have to upload the play store from the smallest number to the biggest number.
see https://developer.android.com/studio/build/configure-apk-splits.html#configure-APK-versions
android {
...
defaultConfig {
...
versionCode 4
}
splits {
...
}
}
// Map for the version code that gives each ABI a value.
ext.abiCodes = ['armeabi-v7a':1, x86:2, x86_64:3]
// For per-density APKs, create a similar map like this:
// ext.densityCodes = ['mdpi': 1, 'hdpi': 2, 'xhdpi': 3]
import com.android.build.OutputFile
// For each APK output variant, override versionCode with a combination of
// ext.abiCodes * 1000 + variant.versionCode. In this example, variant.versionCode
// is equal to defaultConfig.versionCode. If you configure product flavors that
// define their own versionCode, variant.versionCode uses that value instead.
android.applicationVariants.all { variant ->
// Assigns a different version code for each output APK
// other than the universal APK.
variant.outputs.each { output ->
// Stores the value of ext.abiCodes that is associated with the ABI for this variant.
def baseAbiVersionCode =
// Determines the ABI for this variant and returns the mapped value.
project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))
// Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes,
// the following code does not override the version code for universal APKs.
// However, because we want universal APKs to have the lowest version code,
// this outcome is desirable.
if (baseAbiVersionCode != null) {
// Assigns the new version code to versionCodeOverride, which changes the version code
// for only the output APK, not for the variant itself. Skipping this step simply
// causes Gradle to use the value of variant.versionCode for the APK.
output.versionCodeOverride =
baseAbiVersionCode * 1000 + variant.versionCode
}
}
}
For more examples of alternate version code schemes, see Assigning version codes (https://developer.android.com/google/play/publishing/multiple-apks.html#VersionCodes)
Yeah, It depends on which device you want to target. For more information Below - stackoverflow and developer's official links are also be helpful to you:
Publish Multiple APKs to Google Play Store
https://developer.android.com/studio/build/configure-apk-splits.html#build-apks
Depends on which device you want to target. Play store will tell you how much device you have left out after uploading an apk. Make sure you have version code different for each flavor if you want to upload multiple ones. For example,I have XXXn where n is the code for cpu architecture.
I can't publish multiple release
the problem is the release code or version
ext.abiCodes = ['x86_64':1,'x86':2,'armeabi':3,'armeabi-v7a':4,'arm64-v8a':5,'mips':6]
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.book.walid.resumephilosophie"
minSdkVersion 15
resConfigs "ar"
targetSdkVersion 27
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
splits {
abi{
enable true
reset()
include 'x86_64','x86','armeabi','armeabi-v7a','arm64-v8a','mips'
universalApk false
}
}
android.applicationVariants.all { variant ->
def baseAbiVersionCode =
project.ext.abiCodes.get(com.android.build.OutputFile.ABI)
if (baseAbiVersionCode != null) {
output.versionCodeOverride =
baseAbiVersionCode * 1000 + variant.versionCode
}
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

Android Studio split APK over Density

splits {
// Configures multiple APKs based on screen density.
density {
// Configures multiple APKs based on screen density.
enable true
reset()
// Specifies a list of screen densities Gradle should create multiple APKs for.
include 'ldpi', 'mdpi', 'hdpi', 'xhdpi', 'xxhdpi', 'xxxhdpi'
// Specifies a list of compatible screen size settings for the manifest.
//compatibleScreens 'small', 'normal', 'large', 'xlarge'
}
// Configures multiple APKs based on ABI.
abi {
// Enables building multiple APKs per ABI.
enable false
// 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-v7a', 'arm64-v8a', 'x86', 'x86_64'
// Specifies that we do want to also generate a universal APK that includes all ABIs.
universalApk true //generate an additional APK that contains all the ABIs
//'armeabi' - Not surported by Realm since v2.0.0
}
}
I'm trying to split my APKs by Desity in order to reduce APK size, using the above Gradle it splits the APKs into densities but the drawable resources for each APK are identical.
Should the result of this not be that the xhdpi APK only contains only drawable-ldrtl-xhdpi-v17, drawable-xhdpi-v4 and mipmap-xhdpi-v4?
Example of density apk split in gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 19
buildToolsVersion = rootProject.ext.buildToolsVersion
defaultConfig {
versionCode 12
minSdkVersion 16
targetSdkVersion 20
buildConfigField "String", "FOO", "\"bar\""
}
splits {
density {
enable true
exclude "ldpi", "tvdpi", "xxxhdpi", "400dpi", "560dpi"
compatibleScreens 'small', 'normal', 'large', 'xlarge'
}
}
}
// map for the version code
ext.versionCodes = [all:1, mdpi:2, hdpi:3, xhdpi:4, xxhdpi:5]
android.applicationVariants.all { variant ->
// assign different version code for each output
variant.outputs.each { output ->
def key = output.getFilter(OutputFile.DENSITY) == null ? "all" : output.getFilter(OutputFile.DENSITY)
output.versionCodeOverride = project.ext.versionCodes.get(key) * 100 + android.defaultConfig.versionCode
}
}

Robolectric 3 support of Gradle splits

I have in build.gradle Android splits:
splits {
abi {
enable true
reset()
include 'x86', 'mips', 'armeabi-v7a', 'armeabi'
universalApk false
}
}
android.applicationVariants.all { variant ->
// assign different version code for each output
variant.outputs.each { output ->
output.versionCodeOverride =
versionCodes.get(output.getFilter(OutputFile.ABI), 0) * 1000000 + android.defaultConfig.versionCode
}
}
After update of Robolectric to 3.0 I become path error:
build/intermediates/manifests/full/debug/AndroidManifest.xml not found or not a file; it should point to your project's AndroidManifest.xml
because I in build/intermediates/manifests/full/ have 4 splits folders
armeabi/ armeabi-v7a/ mips/ x86/
How can i set in Robolectric config or in gradle configuration, that I have splits?
Thank you
UPDATE:
In all my classes I have following configuration:
#RunWith(RobolectricGradleTestRunner.class)
#Config(sdk = 21, manifest = "../application/AndroidManifest.xml", constants = BuildConfig.class)
I think the easiest way will just be to point it to your x86/AndroidManifest.xml
You can specify this using the manifest key in your #Config, e.g.
#Config(manifest="path-here")
Since you will need this for every test, you might also consider creating a properties file. For more details on this, the docs are here

Categories

Resources