diff options
author | Joe Fernandez <joefernandez@google.com> | 2014-11-01 14:10:43 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2014-11-01 14:10:43 +0000 |
commit | f16f6d9ed25ee2abfa09b6a9448772b90112f0b4 (patch) | |
tree | 1f9775497f9804023d4917541af2e53219633eb8 | |
parent | a1caad91c7b5d9a96fec68c014b4fdc6c0d56664 (diff) | |
parent | 84045506140d895aaf4fdc5a090e89d657add120 (diff) | |
download | frameworks_base-f16f6d9ed25ee2abfa09b6a9448772b90112f0b4.zip frameworks_base-f16f6d9ed25ee2abfa09b6a9448772b90112f0b4.tar.gz frameworks_base-f16f6d9ed25ee2abfa09b6a9448772b90112f0b4.tar.bz2 |
am 84045506: am 20207a83: am e8ad737d: docs: multidex - building apps with over 65K method references
* commit '84045506140d895aaf4fdc5a090e89d657add120':
docs: multidex - building apps with over 65K method references
-rw-r--r-- | docs/html/images/tools/studio-build-variant.png | bin | 0 -> 20405 bytes | |||
-rw-r--r-- | docs/html/tools/building/multidex.jd | 458 | ||||
-rw-r--r-- | docs/html/tools/support-library/features.jd | 29 | ||||
-rw-r--r-- | docs/html/tools/tools_toc.cs | 13 |
4 files changed, 497 insertions, 3 deletions
diff --git a/docs/html/images/tools/studio-build-variant.png b/docs/html/images/tools/studio-build-variant.png Binary files differnew file mode 100644 index 0000000..a400ad4 --- /dev/null +++ b/docs/html/images/tools/studio-build-variant.png diff --git a/docs/html/tools/building/multidex.jd b/docs/html/tools/building/multidex.jd new file mode 100644 index 0000000..49cde8c --- /dev/null +++ b/docs/html/tools/building/multidex.jd @@ -0,0 +1,458 @@ +page.title=Building Apps with Over 65K Methods +page.tags="65536","references","max","65k","dex","64k","multidex","multi-dex","methods"</p> + +@jd:body + +<div id="qv-wrapper"> + <div id="qv"> + <h2>In this document</h2> + <ol> + <li><a href="#about"> + About the 65K Reference Limit</a> + <ol> + <li><a href="#mdex-pre-l">Multidex support prior to Android 5.0</a></li> + <li><a href="#mdex-on-l">Multidex support for Android 5.0 and higher</a></li> + </ol> + </li> + <li><a href="#avoid"> + Avoiding the 65K Limit</a></li> + <li><a href="#mdex-gradle"> + Configuring Your App for Multidex with Gradle</a> + <ol> + <li><a href="#limitations"> + Limitations of the multidex support library</a></li> + </ol> + </li> + <li><a href="#dev-build"> + Optimizing Multidex Development Builds</a> + <ol> + <li><a href="#variants-studio"> + Using Build Variants in Android Studio</a></li> + </ol> + </li> + <li><a href="#testing"> + Testing Multidex Apps</a></li> + </ol> + + <h2>See Also</h2> + <ol> + <li><a href="{@docRoot}tools/help/proguard.html">ProGuard</a> + </li> + </ol> + </div> +</div> + + +<p> + As the Android platform has continued to grow, so has the size of Android apps. When your + application and the libraries it references reach a certain size, you encounter build errors that + indicate your app has reached a limit of the Android app build architecture. Earlier versions of + the build system report this error as follows: +</p> + +<pre> +Conversion to Dalvik format failed: +Unable to execute dex: method ID not in [0, 0xffff]: 65536 +</pre> + +<p> + More recent versions of the Android build system display a different error, which is an + indication of the same problem: +</p> + +<pre> +trouble writing output: +Too many field references: 131000; max is 65536. +You may try using --multi-dex option. +</pre> + +<p> + Both these error conditions display a common number: 65,536. This number is significant in that + it represents the total number of references that can be invoked by the code within a single + Dalvik Executable (dex) bytecode file. If you have built an Android app and received this error, + then congratulations, you have a lot of code! This document explains how to move past this + limitation and continue building your app. +</p> + +<p class="note"> + <strong>Note:</strong> The guidance provided in this document supersedes the guidance given in + the Android Developers blog post <a href= + "http://android-developers.blogspot.com/2011/07/custom-class-loading-in-dalvik.html">Custom Class + Loading in Dalvik</a>. +</p> + + +<h2 id="about">About the 65K Reference Limit</h2> + +<p> + Android application (APK) files contain executable bytecode files in the form of <a href= + "https://source.android.com/devices/tech/dalvik/">Dalvik</a> Executable (DEX) files, which + contain the compiled code used to run your app. The Dalvik Executable specification limits the + total number of methods that can be referenced within a single DEX file to 65,536, including + Android framework methods, library methods, and methods in your own code. Getting past this limit + requires that you configure your app build process to generate more than one DEX file, known as a + <em>multidex</em> configuration. +</p> + + +<h3 id="mdex-pre-l">Multidex support prior to Android 5.0</h3> + +<p> + Versions of the platform prior to Android 5.0 use the Dalvik runtime for executing app code. By + default, Dalvik limits apps to a single classes.dex bytecode file per APK. In order to get around + this limitation, you can use the <a href="{@docRoot}tools/support-library/features.html#multidex"> + multidex support library</a>, which becomes part of the primary DEX file of your app and then + manages access to the additional DEX files and the code they contain. +</p> + + +<h3 id="mdex-on-l">Multidex support for Android 5.0 and higher</h3> + +<p> + Android 5.0 and higher uses a runtime called ART which natively supports loading multiple dex + files from application APK files. ART performs pre-compilation at application install time which + scans for classes(..N).dex files and compiles them into a single .oat file for execution by the + Android device. For more information on the Android 5.0 runtime, see <a href= + "https://source.android.com/devices/tech/dalvik/art.html">Introducing ART</a>. +</p> + + +<h2 id="avoid">Avoiding the 65K Limit</h2> + +<p> + Before configuring your app to enable use of 65K 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: +</p> + +<ul> + <li> + <strong>Review your app's direct and transitive dependencies</strong> - 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. + </li> + <li> + <strong>Remove unused code with ProGuard</strong> - Configure the <a href= + "{@docRoot}tools/help/proguard.html">ProGuard</a> 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. + </li> +</ul> + + +<p> + Using these techniques can help you avoid the build configuration changes required to enable more + method references in your app. These steps can also decrease the size of your APKs, which is + particularly important for markets where bandwidth costs are high. +</p> + + +<h2 id="mdex-gradle">Configuring Your App for Multidex with Gradle</h2> + +<p> + The Android plugin for Gradle available in Android SDK Build Tools 21.1 and higher supports + multidex as part of your build configuration. Make sure you update the Android SDK Build Tools + tools and the Android Support Repository to the latest version using the <a href= + "{@docRoot}tools/help/sdk-manager.html">SDK Manager</a> before attempting to configure your app + for multidex. +</p> + +<p> + Setting up your app development project to use a multidex configuration requires that you make a + few modifications to your app development project. In particular you need to perform the + following steps: +</p> + +<ul> + <li>Change your Gradle build configuration to enable multidex</li> + <li>Modify your manifest to reference the {@link android.support.multidex.MultiDexApplication} + class</li> +</ul> + +<p> + Modify your app Gradle build file configuration to include the support library and enable + multidex output, as shown in the following Gradle build file snippet: +</p> + +<pre> +android { + compileSdkVersion 21 + buildToolsVersion "21.1.0" + + defaultConfig { + ... + minSdkVersion 14 + targetSdkVersion 21 + ... + + // Enabling multidex support. + multiDexEnabled true + } + ... +} + +dependencies { + compile 'com.android.support:multidex:1.0.0' +} +</pre> + +<p class="note"> + <strong>Note:</strong> You can specify the <code>multiDexEnabled</code> setting in the + <code>defaultConfig,</code> <code>buildType</code>, or <code>productFlavor</code> sections of + your Gradle build file. +</p> + + +<p> + In your manifest add the {@link android.support.multidex.MultiDexApplication} class from the + multidex support library to the application element. +</p> + +<pre> +<?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> +</pre> + +<p> + 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. +</p> + +<p class="note"> + <strong>Note:</strong> If your app uses extends the {@link android.app.Application} class, you + can override the attachBaseContext() method and call MultiDex.install(this) to enable multidex. + For more information, see the {@link android.support.multidex.MultiDexApplication} reference + documentation. +</p> + +<h3 id="limitations">Limitations of the multidex support library</h3> + +<p> + The multidex support library has some known limitations that you should be aware of and test for + when you incorporate it into your app build configuration: +</p> + +<ul> + <li>The installation of .dex files during startup onto a device's data partition is complex and + can result in Application Not Responding (ANR) errors if the secondary dex files are large. In + this case, you should apply code shrinking techniques with ProGuard to minimize the size of dex + files and remove unused portions of code. + </li> + + <li>Applications that use multidex may not start on devices that run versions of the platform + earlier than Android 4.0 (API level 14) due to a Dalvik linearAlloc bug (Issue <a href= + "http://b.android.com/22586">22586</a>). If you are targeting API levels earlier than 14, make + sure to perform testing with these versions of the platform as your application can have issues + at startup or when particular groups of classes are loaded. Code shrinking can reduce or possibly + eliminate these potential issues. + </li> + + <li>Applications using a multidex configuration that make very large memory allocation + requests may crash during run time due to a Dalvik linearAlloc limit (Issue <a href= + "http://b.android.com/78035">78035</a>). The allocation limit was increased in Android 4.0 (API + level 14), but apps may still run into this limit on Android versions prior to + Android 5.0 (API level 21). + </li> + + <li>There are complex requirements regarding what classes are needed in the primary dex file when + executing in the Dalvik runtime. The Android build tooling updates handle the Android + requirements, but it is possible that other included libraries have additional dependency + requirements including the use of introspection or invocation of Java methods from native code. + Some libraries may not be able to be used until the multidex build tools are updated to allow you + to specify classes that must be included in the primary dex file. + </li> +</ul> + + +<h2 id="dev-build">Optimizing Multidex Development Builds</h2> + +<p> + A multidex configuration requires significantly increased build processing time because the build + system must make complex decisions about what classes must be included in the primary DEX file + and what classes can be included in secondary DEX files. This means that routine builds performed + as part of the development process with multidex typically take longer and can potentially slow + your development process. +</p> + +<p> + In order to mitigate the typically longer build times for multidex output, you should create two + variations on your build output using the Android plugin for Gradle + <a href="http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Product-flavors"> + {@code productFlavors}</a>: a development flavor and a production flavor. +</p> + +<p> + For the development flavor, set a minimum SDK version of 21. This setting generates multidex + output much faster using the ART-supported format. For the release flavor, set a minimum SDK + version which matches your actual minimum support level. This setting generates a multidex APK + that is compatible with more devices, but takes longer to build. +</p> + +<p> + The following build configuration sample demonstrates the how to set up these flavors in a Gradle + build file: +</p> + +<pre> +android { + productFlavors { + // Define separate dev and prod product flavors. + dev { + // dev utilizes minSDKVersion = 21 to allow the Android gradle plugin + // to pre-dex each module and produce an APK that can be tested on + // Android Lollipop without time consuming dex merging processes. + minSdkVersion 21 + } + prod { + // The actual minSdkVersion for the application. + minSdkVersion 14 + } + } + ... + buildTypes { + release { + runProguard true + proguardFiles getDefaultProguardFile('proguard-android.txt'), + 'proguard-rules.pro' + } + } +} +dependencies { + compile 'com.android.support:multidex:1.0.0' +} +</pre> + +<p> + After you have completed this configuration change, you can use the <code>devDebug</code> variant + of your app, which combines the attributes of the <code>dev</code> productFlavor and the + <code>debug</code> buildType. Using this target creates a debug app with proguard disabled, + multidex enabled, and minSdkVersion set to Android API level 21. These settings cause the Android + gradle plugin to do the following: +</p> + +<ol> + <li>Build each module of the application (including dependencies) as separate dex files. This is + commonly referred to as pre-dexing. + </li> + + <li>Include each dex file in the APK without modification. + </li> + + <li>Most importantly, the module dex files will not be combined, and so the long-running + calculation to determine the contents of the primary dex file is avoided. + </li> +</ol> + +<p> + These settings result in fast, incremental builds, because only the dex files of modified modules + are recomputed and repackaged into the APK file. The APK that results from these builds can be + used to test on Android 5.0 devices only. However, by implementing the configuration as a flavor, + you preserve the ability to perform normal builds with the release-appropriate minimum SDK level + and proguard settings. +</p> + +<p> + You can also build the other variants, including a <code>prodDebug</code> variant + build, which takes longer to build, but can be used for testing outside of development. + Within the configuration shown, the <code>prodRelease</code> variant would be the final testing + and release version. If you are executing gradle tasks from the command line, you can use + standard commands with <code>DevDebug</code> appended to the end (such as <code>./gradlew + installDevDebug</code>). For more information about using flavors with Gradle tasks, see the + <a href="http://tools.android.com/tech-docs/new-build-system/user-guide">Gradle Plugin User + Guide</a>. +</p> + +<p> + <strong>Tip:</strong> You can also provide a custom manifest, or a custom application class for each + flavor, allowing you to use the support library MultiDexApplication class, or calling + MultiDex.install() only for the variants that need it. +</p> + + +<h3 id="variants-studio">Using Build Variants in Android Studio</h3> + +<p> + Build variants can be very useful for managing the build process when using multidex. Android + Studio allows you to select these build variants in the user interface. +</p> + +<p> + To have Android Studio build the "devDebug" variant of your app: +</p> + +<ol> + <li>Open the <em>Build Variants</em> window from the left-sidebar. The option is located next to + <em>Favorites</em>. + </li> + + <li>Click the name of the build variant to select a different variant, as shown in Figure 1. + </li> +</ol> + +<img src="{@docRoot}images/tools/studio-build-variant.png" alt="" height="XXX" id="figure1"> +<p class="img-caption"> + <strong>Figure 1.</strong> Screen shot of the Android Studio left panel showing a build variant. +</p> + +<p class="note"> + <strong>Note</strong>: The option to open this window is only available after you have + successfully synchronized Android Studio with your Gradle build file using the <strong>Tools > + Android > Sync Project with Gradle Files</strong> command. +</p> + + +<h2 id="testing">Testing Multidex Apps</h2> + +<p> + Testing apps that use multidex configuration require some additional steps and configuration. + Since the location of code for classes is not within a single DEX file, instrumentation tests do + not run properly unless configured for multidex. +</p> + +<p> + When testing a multidex app with instrumentation tests, use + <a href="{@docRoot}reference/com/android/test/runner/MultiDexTestRunner.html"> + MultiDexTestRunner</a> from the multidex testing support library. The following sample + {@code build.gradle} file, demonstrates how to configure your build to use this test runner: +</p> + +<pre> +android { + defaultConfig { + ... + testInstrumentationRunner "android.support.multidex.MultiDexTestRunner" + } +} + +dependencies { + androidTestCompile 'com.android.support:multidex-instrumentation:1.0.0' +} +</pre> + +<p> + You may use the instrumentation test runner class directly or extend it to fit your testing + needs. Alternatively, you can override onCreate in existing instrumentations like this: +</p> + +<pre> +public void onCreate(Bundle arguments) { + MultiDex.install(getTargetContext()); + super.onCreate(arguments); + ... +} +</pre> + +<p class="note"> + <strong>Note:</strong> Use of multidex for creating a test APK is not currently supported. +</p>
\ No newline at end of file diff --git a/docs/html/tools/support-library/features.jd b/docs/html/tools/support-library/features.jd index 44c5045..3ebfc89 100644 --- a/docs/html/tools/support-library/features.jd +++ b/docs/html/tools/support-library/features.jd @@ -8,6 +8,7 @@ page.title=Support Library Features <h2>In this document</h2> <ol> <li><a href="#v4">v4 Support Library</a></li> + <li><a href="#multidex">Multidex Support Library</a></li> <li><a href="#v7">v7 Support Libraries</a> <ol> <li><a href="#v7-appcompat">v7 appcompat library</a></li> @@ -145,6 +146,34 @@ com.android.support:support-v4:21.0.+ <p>This dependency notation specifies the release version 21.0.0 or higher.</p> +<h2 id="multidex">Multidex Support Library</h2> + +<p> + This library provides support for building apps with multiple Dalvik Executable (DEX) files. + Apps that reference more than 65536 methods are required to use multidex configurations. For + more information about using multidex, see <a href="{@docRoot}tools/building/multidex.html"> + Building Apps with Over 65K Methods</a>. +</p> + +<p> + This library is located in the {@code <sdk>/extras/android/support/multidex/} directory + after you download the Android Support Libraries. The library does not contain user interface + resources. To include it in your application project, follow the instructions for <a href= + "{@docRoot}tools/support-library/setup.html#libs-without-res">Adding libraries without + resources</a>. +</p> + +<p> + The Gradle build script dependency identifier for this library is as follows: +</p> + +<pre> +com.android.support:multidex:1.0.+ +</pre> + +<p>This dependency notation specifies the release version 1.0.0 or higher.</p> + + <h2 id="v7">v7 Support Libraries</h2> <p>There are several libraries designed to be used with Android 2.1 (API level 7) and higher. diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs index 8eb9cbf..ac33185 100644 --- a/docs/html/tools/tools_toc.cs +++ b/docs/html/tools/tools_toc.cs @@ -66,10 +66,17 @@ <li class="nav-section"> - <div class="nav-section-header"><a href="<?cs var:toroot ?>tools/building/index.html"><span class="en">Building and Running</span></a></div> + <div class="nav-section-header"> + <a href="<?cs var:toroot ?>tools/building/index.html"> + <span class="en">Building and Running</span></a> + </div> <ul> - <li><a href="<?cs var:toroot ?>tools/building/building-eclipse.html"><span class="en">From Eclipse with ADT</span></a></li> - <li><a href="<?cs var:toroot ?>tools/building/building-cmdline.html"><span class="en">From the Command Line</span></a></li> + <li><a href="<?cs var:toroot ?>tools/building/building-eclipse.html"> + <span class="en">From Eclipse with ADT</span></a></li> + <li><a href="<?cs var:toroot ?>tools/building/building-cmdline.html"> + <span class="en">From the Command Line</span></a></li> + <li><a href="<?cs var:toroot ?>tools/building/multidex.html"> + <span class="en">Apps Over 65K Methods</span></a></li> </ul> </li> |