Getting started with AndroidLayoutsGradle for AndroidRecyclerView onClickListenersNavigationViewIntentJSON in Android with org.jsonAndroid StudioResourcesData Binding LibraryExceptionsGetting Calculated View DimensionsAsyncTaskSharedPreferencesEmulatorMaterial DesignLint WarningsServiceStoring Files in Internal & External StorageWebViewProject SDK versionsRecyclerViewGoogle Maps API v2 for AndroidPorterDuff Mode9-Patch ImagesAndroid NDKRecyclerView DecorationsCamera 2 APIViewPagerCardViewHttpURLConnectionSQLiteADB (Android Debug Bridge)ButterKnifeSupporting Screens With Different Resolutions, SizesGlideRetrofit2DialogACRAGreenDAOFormatting StringsNotificationsAlarmManagerFragmentsHandlerCreating Custom ViewsBroadcastReceiverActivitySnackbarRuntime Permissions in API-23 +Logging and using LogcatVectorDrawable and AnimatedVectorDrawableTools AttributesToastInterfacesAnimatorsLocationTheme, Style, AttributeThe Manifest FileParcelableMediaPlayerMultidex and the Dex Method LimitData Synchronization with Sync AdapterMenuInstant Run in Android StudioPicassoBluetooth and Bluetooth LE APIRoboGuiceMemory LeaksUniversal Image LoaderVolleyWidgetsDate and Time PickersIntegrate Google Sign InIn-app BillingFloatingActionButtonContentProviderDagger 2RealmUnit testing in Android with JUnitAndroid VersionsWi-Fi ConnectionsSensorManagerLocalization with resources in AndroidProgressBarCustom FontsVibrationGoogle Awareness APIsText to Speech(TTS)UI LifecycleSpinnerData Encryption/DecryptionTesting UI with EspressoWriting UI tests - AndroidGreenRobot EventBusOkHttpEnhancing Android Performance Using Icon FontsHandling Deep LinksCanvas drawing using SurfaceViewFirebaseCrash Reporting ToolsCheck Internet ConnectivityFacebook SDK for AndroidUnzip File in AndroidAndroid Places APICreating your own libraries for Android applicationsGsonDevice Display MetricsTextViewListViewBuilding Backwards Compatible AppsLoaderProGuard - Obfuscating and Shrinking your codeDetect Shake Event in AndroidTypedef Annotations: @IntDef, @StringDefCapturing ScreenshotsMVP ArchitectureOrientation ChangesXposedSecurityPackageManagerImageViewGesture DetectionDoze ModeAndroid Sound and MediaSearchViewCamera and GalleryCallback URLTwitter APIsDrawablesColorsConstraintLayoutRenderScriptFrescoSwipe to RefreshAutoCompleteTextViewInstalling apps with ADBIntentServiceAdMobImplicit IntentsPublish to Play StoreFirebase Realtime DataBaseImage CompressionEmail ValidationKeyboardButtonTextInputLayoutBottom SheetsCoordinatorLayout and BehaviorsEditTextAndroid Paypal Gateway IntegrationFirebase App IndexingFirebase Crash ReportingDisplaying Google AdsAndroid Vk SdkLocalized Date/Time in AndroidCount Down TimerBarcode and QR code readingOtto Event BusTransitionDrawablePort Mapping using Cling library in AndroidCreating Overlay (always-on-top) WindowsExoPlayerInter-app UI testing with UIAutomatorMediaSessionSpeech to Text ConversionFileProviderPublish .aar file to Apache Archiva with GradleXMPP register login and chat simple exampleAndroid AuthenticatorRecyclerView and LayoutManagersAudioManagerJob SchedulingAccounts and AccountManagerIntegrate OpenCV into Android StudioSplit Screen / Multi-Screen ActivitiesThreadMediaStoreTime UtilsTouch EventsFingerprint API in androidMVVM (Architecture)BottomNavigationViewORMLite in androidYoutube-APITabLayoutRetrofit2 with RxJavaDayNight Theme (AppCompat v23.2 / API 14+)ShortcutManagerLruCacheJenkins CI setup for Android ProjectsZip file in androidVector DrawablesfastlaneDefine step value (increment) for custom RangeSeekBarGetting started with OpenGL ES 2.0+Check Data ConnectionAndroid Java Native Interface (JNI)FileIO with AndroidPerformance OptimizationRobolectricMoshiStrict Mode Policy : A tool to catch the bug in the Compile Time.Internationalization and localization (I18N and L10N)Fast way to setup Retrolambda on an android project.How to use SparseArrayFirebase Cloud MessagingShared Element TransitionsAndroid ThingsVideoViewViewFlipperLibrary Dagger 2: Dependency Injection in ApplicationsFormatting phone numbers with pattern.How to store passwords securelyAndroid Kernel OptimizationPaintAudioTrackWhat is ProGuard? What is use in Android?Create Android Custom ROMsJava on AndroidPagination in RecyclerViewGenymotion for androidHandling touch and motion eventsCreating Splash screenConstraintSetCleverTapPublish a library to Maven Repositoriesadb shellPing ICMPAIDLAndroid programming with KotlinAutosizing TextViewsSign your Android App for ReleaseContextActivity RecognitionSecure SharedPreferencesSecure SharedPreferencesBitmap CacheAndroid-x86 in VirtualBoxJCodecDesign PatternsOkioGoogle signin integration on androidTensorFlowAndroid game developmentNotification Channel Android OBluetooth Low EnergyLeakcanaryAdding a FuseView to an Android ProjectAccessing SQLite databases using the ContentValues classEnhancing Alert DialogsHardware Button Events/Intents (PTT, LWP, etc.)SpannableStringLooperOptimized VideoViewGoogle Drive APIAnimated AlertDialog BoxAnnotation ProcessorSyncAdapter with periodically do sync of dataCreate Singleton Class for Toast MessageFastjsonAndroid Architecture ComponentsJacksonGoogle Play StoreLoading Bitmaps EffectivelyGetting system font names and using the fontsSmartcardConvert vietnamese string to english string Android

Multidex and the Dex Method Limit

Other topics

Remarks:

What is dex?

Dex is the name of the file format and encoding to which Android Java code is compiled. Early versions of Android would load and execute dex binaries directly in a virtual machine named Dalvik. More recent versions of Android use the Android Runtime (ART), which treats dex files as an intermediate representation and performs further compilations on it prior to running the application.

Dex is a very old file format, in terms of the lifespan of smartphones, and was designed for devices whose main memory was measured in tens of megabytes. The design limitations of those days have remained with us to this day.

The problem:

The dex file format encodes a limit to the number of methods that can be referenced in a single binary. Because the portion of the file format that stores the number of references is two bytes long, the maximum number of method references is 0xFFFF, or 65535. If an application contains more than that number of method references, it will fail to compile.

What to do about it:

Google has provided a way around this problem, called Multidex. It has compile-time and run-time components. As its name implies, at compile-time it will divide code between one or more dex files. At runtime, it will teach the default ClassLoader how to look up classes from these files.

This approach works well on newer devices, but has some substantial drawbacks. It can increase application startup time dramatically, and on older devices can cause Application Not Responding failures.

Multidex, while effective, should be avoided if possible.

How to avoid the limit:

Before configuring your app to enable use of 64K or more method references, you should take steps to reduce the total number of references called by your app code, including methods defined by your app code or included libraries. The following strategies can help you avoid hitting the dex reference limit:

  • Review your app's direct and transitive dependencies - Ensure any large library dependency you include in your app is used in a manner that outweighs the amount of code being added to the application. A common anti-pattern is to include a very large library because a few utility methods were useful. Reducing your app code dependencies can often help you avoid the dex reference limit.
  • Remove unused code with ProGuard - Configure the ProGuard settings for your app to run ProGuard and ensure you have shrinking enabled for release builds. Enabling shrinking ensures you are not shipping unused code with your APKs.

The first point requires diligence and discipline on the part of the developer. When incorporating third-party libraries, one must consider the size of the library. For example, two popular JSON libraries are Jackson and Gson. Functionally they are quite similar, but Gson tends to see greater use in Android. One reason is that Jackson weighs in around 9,000 methods, whereas Gson contributes 1,900.

There are several tools available to help developers keep track of the size of their application:

  • dexcount-gradle-plugin reports the number of method references in your APK or AAR on each build
  • dex-method-counts is a commandline tool that counts the number of method references in an APK
  • www.methodscount.com is a web service which will count the method references in any APK that you upload.

Enabling Multidex

In order to enable a multidex configuration you need:

  • to change your Gradle build configuration
  • to use a MultiDexApplication or enable the MultiDex in your Application class

Gradle configuration

In app/build.gradle add these parts:

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.1"

    defaultConfig {
        ...
        minSdkVersion 14
        targetSdkVersion 24
        ...

        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.1'
}

Enable MultiDex in your Application

Then proceed with one of three options:

When these configuration settings are added to an app, the Android build tools construct a primary dex (classes.dex) and supporting (classes2.dex, classes3.dex) as needed.
The build system will then package them into an APK file for distribution.

Multidex by using MultiDexApplication directly

Use this option if you don't need an Application subclass.

This is the simplest option, but this way you can't provide your own Application subclass. If an Application subclass is needed, you will have to switch to one of the other options to do so.

For this option, simply specify the fully-qualified class name android.support.multidex.MultiDexApplication for the android:name property of the application tag in the AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.multidex.myapplication">
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
</manifest>

Multidex by extending Application

Use this option if your project requires an Application subclass.

Specify this Application subclass using the android:name property in the manifest file inside the application tag.

In the Application subclass, add the attachBaseContext() method override, and in that method call MultiDex.install():

package com.example;

import android.app.Application;
import android.content.Context;

/**
 * Extended application that support multidex 
 */
public class MyApplication extends Application {

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }
}

Ensure that the Application subclass is specified in the application tag of your AndroidManifest.xml:

<application
    android:name="com.example.MyApplication"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name">
</application>

Counting Method References On Every Build (Dexcount Gradle Plugin)

The dexcount plugin counts methods and class resource count after a successful build.

Add the plugin in the app/build.gradle:

apply plugin: 'com.android.application'

buildscript {
    repositories {
        mavenCentral() // or jcenter()
    }

    dependencies {
        classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.5.5'
    }
}

Apply the plugin in the app/build.gradle file:

apply plugin: 'com.getkeepsafe.dexcount'

Look for the output data generated by the plugin in:

../app/build/outputs/dexcount

Especially useful is the .html chart in:

../app/build/outputs/dexcount/debugChart/index.html

Multidex by extending MultiDexApplication

This is very similar to using an Application subclass and overriding the attachBaseContext() method.

However, using this method, you don't need to override attachBaseContext() as this is already done in the MultiDexApplication superclass.

Extend MultiDexApplication instead of Application:

package com.example;

import android.support.multidex.MultiDexApplication;
import android.content.Context;

/**
 * Extended MultiDexApplication 
 */
public class MyApplication extends MultiDexApplication {

     // No need to override attachBaseContext()

     //..........
}

Add this class to your AndroidManifest.xml exactly as if you were extending Application:

<application
    android:name="com.example.MyApplication"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name">
</application>

Contributors

Topic Id: 1887

Example Ids: 6155,6002,6003,6156,18691

This site is not affiliated with any of the contributors.