Getting MultiDex Error, even after setting Min SDK 21 - android

The project i am working on has around 180k Methods. I have read blogs, and articles where its written that if you set your Min SDK to 21, then you don't need MultiDex. But if i remove MultiDex from here it gives me the 65k MultiDex error message. Following is my gradle file. I don't know whether i failed to understand the concept or something else. Kindly guide me.
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
applicationId 'com.myapp.app'
minSdkVersion 21
targetSdkVersion 23
versionCode 59
versionName "1.0.1"
multiDexEnabled true
ndk {
abiFilters "armeabi", "armeabi-v7a", "x86"
}
}
dexOptions {
javaMaxHeapSize "4g" //specify the heap size for the dex process
}
lintOptions {
abortOnError false
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
}

if you set your Min SDK to 21, then you don't need MultiDex
As per the "Multidex support for Android 5.0 and higher" instructions in the MultiDex guide, even if you minSdk 21 then you still need compile with multiDexEnabled true. What you don't need to do is include the MultiDex support library via:
compile 'com.android.support:multidex:1.0.0'
or call MultiDex.install(Context) in your Application class.
The 64K method problem is a limitation of the DEX file format and not of the Android Platform itself. The difference between the two versions is that Android 5.0+ knows how to automatically load multiple DEX files into a single OAT file and load classes from it while Android versions prior to 5.0 require the support library in order to load classes from secondary DEX files (e.g. classes2.dex, classes3.dex, etc).

Related

How to choose different minSdkVersion for different android ABI?

I have Android app which builds armeabi-v7a and arm64-v8a. Here is the build.gradle:
apply plugin: 'com.android.library'
allprojects {
repositories {
jcenter()
google()
}
}
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
externalNativeBuild {
cmake {
// Linker flags and Visibility options keeps the size of the library small
cppFlags "-std=c++11"
arguments "-DANDROID_STL=gnustl_static",
"-DANDROID_CPP_FEATURES=rtti exceptions",
"-DANDROID_TOOLCHAIN=gcc"
}
}
}
buildTypes {
release {
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
externalNativeBuild {
cmake {
cppFlags "-Wl,--exclude-libs=ALL -Wl,--gc-sections -fvisibility=hidden -fvisibility-inlines-hidden -ffunction-sections"
}
}
}
debug {
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
}
}
externalNativeBuild {
cmake {
path 'CMakeLists.txt'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
I am using the minSdkVersion = 21 to support arm64. I would like to change the minSdkVersion based on the abiFilters i.e., use 16 for v7 and use 21 for arm64.
You don't need to do anything mentioned in the selected answer. Just set minSdkVersion 16 and the 64-bit ABIs will automatically use minSdkVersion 21 because that's the lowest available API for 64-bit.
For how the minSdkVersion property works, see below quotes from official documentation:
If there exists a platform version for the ABI equal to minSdkVersion, CMake uses that version.
Otherwise,
if there exists platform versions lower than minSdkVersion for the ABI, CMake uses the highest of those platform versions. This is a reasonable choice because a missing platform version typically means that there were no changes to the native platform APIs since the previous available version.
Otherwise, CMake uses the next available platform version higher than minSdkVersion.
And it has ever been mentioned in may answer to your another question: Android Studio CMake/Ninja Not Used for Building an NDK project.
I am using the minSdkVersion = 21 to support arm64. I would like to change the minSdkVersion based on the abiFilters i.e., use 16 for v7 and use 21 for arm64.
My understanding is that you are trying to support older (api level lower than 21) 32-bit devices without 64-bit native binaries. I would like to say "productFlavor" is the right direction to go. E.g. you can have your gradle configuration like below to achieve what you expect:
android {
...
flavorDimensions "api", "mode"
productFlavors {
minApi16 {
dimension "api"
minSdkVersion 16
versionCode android.defaultConfig.versionCode
versionNameSuffix "-minApi16"
ndk {
abiFilters 'armeabi-v7a'
}
}
minApi21 {
dimension "api"
minSdkVersion 21
versionCode android.defaultConfig.versionCode
versionNameSuffix "-minApi21"
ndk {
abiFilters 'arm64-v8a'
}
}
}
...
}
The minSdkVersion 16 and minSdkVersion 21 will help you choose the best suitable NDK version.
Edit #1
How to choose different minSdkVersion for different android ABI?
minSdkVersion is the property telling the minimum Android version that your app can install on. For one single APK, this is an unconditional characteristic. So:
If you want to have one single APK to support all the devices starting from api 16, then you have to set your minSdkVersion to 16.
If you want to have one single APK to support both 32-bit devices and 64-bit devices, you have to provide a complete set of ALL the shared libraries both 32-bit and 64-bit.
Or else, you have to provide different APKs split by ABIs and minSdkVersion.

No Class defined error on release builds?

I seem to be running into an issue where only release builds crash with the error java.lang.NoClassDefFoundError: Failed resolution of: Lretrofit2/Retrofit$Builder; The class is irrelevant because it has not resolved other classes too in the release build. However, this does not appear on Debug builds which makes no sense at all. I have found that when I include these two dependencies:
implementation 'com.google.android.gms:play-services-ads:12.0.0'
implementation 'com.google.ads.interactivemedia.v3:interactivemedia:3.8.5'
the app crashes. However, when I exclude one of them, then the release builds work. Has anyone encountered this before?
The build config looks like this:
compileSdkVersion 26
buildToolsVersion 26.0.1
defaultConfig {
applicationId "xxxx"
minSdkVersion 21
targetSdkVersion 27
versionName project.rootProject.version.toString()
multiDexEnabled true
vectorDrawables.useSupportLibrary = true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig xxxx
}
}
Update your gradle
targetSdkVersion 27,
compileSdkVersion 27, and
buildtoolsVersion to 27.0.1 or remove it (leave it as default. gradle will always look for the latest within this version 27)
The above solved my problem too. Although, i don't use multiDexEnabled true as i see no reason why when i have google play service library included.
Try removing multiDexEnabled true and re-build gradle.
Unless your are class extending Application class.Then you can use multiDexEnable true
#Override
protected void attachBaseContext(Context context) {
super.attachBaseContext(context);
MultiDex.install(this);
}
check this question for possible solution

Flutter project exceeds .dex Method Reference Count limit

Why does a Flutter project exceed 64K method reference in its .dex file?
I am wondering what the cause of this could be:
In a rather small Flutter project I use 13 plugins. Without Multidex, the Android build fails because it vastly exceeds the method reference limit.
Is there any trick (e.g. Gradle related) that would allow to shrink the method reference count because I think that such a project should not exceed the limit?
(if you want further information on why I think that this is odd, please take a look at older revisions of this question)
I had the same problem and the fix for me was increasing the minSdkVersion in the app/build.bradle like this
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
minSdkVersion 21 // change this to 21
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
If you are using minSdkVersion less than 21, you can do the following to enable multidex.
In your app level build.gradle change as follows:
Add multiDexEnabled true to defaultConfig
defaultConfig {
minSdkVersion 15
targetSdkVersion 28
...
multiDexEnabled true
}
Add multidex dependency
dependencies {
...
implementation 'androidx.multidex:multidex:2.0.1'
}
You can refer this for more information.
in your android/app/build file increase the minsdkversion from 16 to 21 under defautConfig.
Some have even increased it to 28 but it worked for me at 21.
Here is the link to the issue on git
Edit: multiDexEnabled: true also works for some under the same defautConfig.
in the build.gradle under the defaultConfig add the multiDexEnabled true
minSdkVersion 16
targetSdkVersion 30
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true
}
Use ProGuard to eliminate unused classes at compile time. This will reduce your method count by a considerable amount.
You will need to adjust the ProGuard rules to work with Flutter like the Flutter documentation explains here.
I successfully migrated the app to androidx using the below link and the second step:
1) Flutter Projects & Android X Migration Issues
2) In your android/app/build file increase the minsdkversion from 16 to 21 under defaultConfig. Some have even increased it to 28 but it worked for me at 21.
There is another solution without multidex or increasing min SDK. But it's need R8, just enable minify on App level build.gradle
buildTypes {
release {
minifyEnabled true
}
debug {
minifyEnabled true
}
}
from github comment
or to run debug without minify github comment
buildTypes {
release {
minifyEnabled true
}
debug {
defaultConfig.minSdkVersion 21
}
}
Option 1: use the multidex Library.
Option 2: increase your min SDK to 21 or higher
Detailed explanation on using Multidex Library:
Versions of the platform prior to Android 5.0 (API level 21) use the Dalvik runtime for executing app code. By default, Dalvik limits apps to single classes.dex bytecode file per APK. In order to get around this limitation, you can add the multidex library to the module-level build.gradle file:
Steps to fixing it: set multiDex enabled to true
defaultConfig {
minSdkVersion 15
targetSdkVersion 28
...
multiDexEnabled true
}
Add multidex dependency:
dependencies {
implementation "androidx.multidex:multidex:2.0.1" }
Detailed explanation on why increasing your min SDK to 21 in your android/app/build.gradle works is:
Android 5.0 (API level 21) and higher uses a runtime called ART which natively supports loading multiple DEX files from APK files. ART performs pre-compilation at app install time which scans for classesN.dex files and compiles them into a single .oat file for execution by the Android device. Therefore if you have your min SDK set to 21 or higher, you do not need the multidex Library.
Here is a more detailed write up about the issue:
https://developer.android.com/studio/build/multidex

My build is ok but d APK It fails.over 64k, I tried google's site to fix the 2 errors although I just get more errors

Hello I get the 2 errors when trying to generate a signed APK. Although when I build the project it has O errors.
I have gone to the links tried to make the modifications but it comes up with more errors
Error:The number of method references in a .dex file cannot exceed 64K.
Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html
Error:Execution failed for task ':app:transformClassesWithDexForRelease'.
com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: java.lang.UnsupportedOperationException
Configure your app for multidex
Setting up your app project to use a multidex configuration requires that you make the following modifications to your app project, depending on the minimum Android version your app supports.
If your minSdkVersion is set to 21 or higher, all you need to do is set multiDexEnabled to true in your module-level build.gradle file, as shown here:
android {
defaultConfig {
...
minSdkVersion 21
targetSdkVersion 25
multiDexEnabled true
}
...
}
However, if your minSdkVersion is set to 20 or lower, then you must use the multidex support library as follows:
Modify the module-level build.gradle file to enable multidex and add the multidex library as a dependency, as shown here:
android {
defaultConfig {
...
minSdkVersion 15
targetSdkVersion 25
multiDexEnabled true
}
...
}
dependencies {
compile 'com.android.support:multidex:1.0.1'
}
This is the point I though I should put it in my code. I looked around and tried a couple more locations although I keep getting errors.
android {
compileSdkVersion 25
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "com.adventure.game"
minSdkVersion 10
targetSdkVersion 25
versionName '1'
versionNameSuffix '1.0'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
productFlavors {
}
}
If anyone can help, that would be great.
Thanks in advance.
I had the 64k error in one of my apps, and the solution was not to use the multidex.
My problem was that I was importing all the google services with this line in my dependencies: compile 'com.google.android.gms:play-services:10.0.1'. Google brought 64k classes to my app, so I removed this compile line and imported only the services I needed (the location service).
You can find the complete list here.
And this worked for me.
I hope this will help you.

Cannot filter assets for multiple densities using SDK build tools 21 or later

Due to an issue building my application in release mode with the gradle plugin 1.3.0, I have switched to 1.4.0 (beta 2), which fixes said build issue.
However, whereas some flavors build perfectly, others have their build aborted with the following error message:
Cannot filter assets for multiple densities using SDK build tools 21 or later. Consider using apk splits instead.
I haven't found any reference to the sentence above, what should I do with the resources of these flavors, or even why this error only appears in a couple of flavors and not in all of them.
Edit: build.gradle
apply plugin: 'com.android.application'
android {
signingConfigs {
config {
}
}
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "com.example.appname"
minSdkVersion 8
targetSdkVersion 23
versionCode 1
versionName '0.0.1'
}
buildTypes {
release {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
minifyEnabled true
zipAlignEnabled true
signingConfig signingConfigs.config
}
debug {
applicationIdSuffix 'debug'
versionNameSuffix '_debug'
}
}
flavorDimensions "googleplay"
productFlavors {
noplay {
dimension "googleplay"
versionCode Integer.parseInt(defaultConfig.versionCode + "0")
buildConfigField "boolean", "HAS_GOOGLE_PLAY", "false"
resConfigs "ldpi", "mdpi"
// so far we are using the noplay flavor only for old devices, which do not have hidpi
}
play {
dimension "googleplay"
versionCode Integer.parseInt(defaultConfig.versionCode + "1")
buildConfigField "boolean", "HAS_GOOGLE_PLAY", "true"
minSdkVersion 9
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
// Google Play services (analytics)
playCompile 'com.google.android.gms:play-services-analytics:8.1.0'
// ActionBar and support libraries
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.android.support:support-v4:23.0.1'
}
resConfigs is replaced by APK splits for densities and architectures. Note the following sentence:
When using build tools older than 21 you could also add resConfigs
"nodpi", "hdpi" to also limit the density folders that are packaged.
Instead, use apk splits to provide different apks to devices with
different densities.
There is a bug report for this issue.
The offending resConfigs have to be removed, and apk splits can be used in their instead.
Alternatively, switching to build-tool 20.0.0 seems work around this problem.

Categories

Resources