Building Apps with Over 65K Methods(解决APP引用方法总数超过65536)
本文翻译自http://developer.android.com/intl/zh-cn/tools/building/multidex.html#about。主要介绍当我们Android App中函数超过65536时构建失败的原因及解决办法!
-------------------------分割线--------------------------------------------------
随着android platform的持续增长,android apps的大小也在增长。当你的应用程序包括其所引用的库达到一定的规模,你将遇到构建错误,这表明你的程序已经达到到了android 应用框架的限制。在早期的构建系统会报告如下错误信息:
Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536
最近版本的构建系统会显示不同的错误,这是同一个问题的提示信息:
trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.
这两种错误情况显示了一个共同的数字:65536。这个数字代表的是单个Dalvik可执行的(DEX)字节码文件的可以调用方法总数。如果你已经创建了android应用,并且收到了这个错误,那么恭喜你,你的代码太多了!本文档将介绍如何突破这个限制,继续构建你的app。
About the 65K Reference Limit
APK文件包含用于运行你的应用程序编译代码形式的可执行字节码文件(Dalvik Executable DEX)。Dalvik可执行的规范限制了在一个单一的DEX文件中引用到包括Android框架方法,库方法等方法的总数为65,536。想要突破此限制,您需要配置您的应用程序的构建过程,生成多个DEX文件,被称为multidex配置。
Multidex support prior to Android 5.0
Android5.0之前的版本使用的Dalvik运行时执行应用程序代码。默认情况下,Dalvik的限制的应用程序,每APK一个classes.dex字节码文件。为了解决这个限制,可以使用multidex support library,成为您的应用程序的主DEX文件的一部分,然后设法获得了额外的DEX文件和它们所包含的代码。
Multidex support for Android 5.0 and higher
Android5.0以及更高版本使用的是ART runtime,可以支持原生从APK文件中加载多个dex文件。ART进行预编译的应用程序安装时它会扫描类(.. N).dex文件,并通过Android设备编译成一个单一的.oat文件执行。对于在Android5.0运行时的详细信息,请参考 Introducing ART。
Avoiding the 65K Limit
在配置您的应用程序能够使用65K+方法个数之前,您应该采取措施来减少您的应用程序代码调用引用的总数,包括您的应用程序代码中的方法和库定义的方法。以下策略可以帮助您避免超过DEX参考限值:
看您的应用程序的直接和间接性依赖:确保在你的app中包含的library的用途要和其代码量匹配。一个比较常见的反例就是包含巨大的代码量,用途却很小。减少你的app的library依赖往往可以帮你避免dex reference限制。
删除未使用的代码混淆(code with ProGuard):配置可以运行你的app的ProGuard并确保可以在正式构建程序的时候为你的程序瘦身。
使用这些技术可以帮助你避免更改程序构建配置时需要启用更多的方法引用。对于宽带成本很高的市场来说,这些步骤很重要。
Configuring Your App for Multidex with Gradle
Android插件Gradle 可Android SDK Build Tools 21.1和更高版本中支持multidex作为构建配置的一部分。在为你app配置multidex之前,请先使用SDK Manager将Android SDKBuild Tools 和Android Support Repository更新到最新版本。
在你的app中使用multidex配置之前,需要对你的程序开发做一些相应修改。你需要执行以下步骤:
1.修改你的 Gradle构建配置以启用multidex
2.修改你的AndroidManifest 去引用MultiDexApplication class。
修改build.gradle配置去引用support library和启用multidex输出,如以下所示build.gradle片段
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'
}
Note:你可以在build.gradle文件的defaultConfig,buildType,或者productFlavor中设置multiDexEnable。
在你的AndroidManifest的application元素中添加MultiDexApplication class:
<?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>
当这些配置添加到一个应用程序中,Android构建工具会构建一个dex(classes.dex),根据需要会继续构建(classes2.dex, classes3.dex)。然后构建系统将他们打包进同一个apk中。
Note: 如果你的app使用了自己定义的Application class,你可以重写attachBaseContext()方法并在其中调用MultiDex.install(this)去实现multidex。更多信息请参考MultiDexApplication
Limitations of the multidex support library
你应该意识到multidex support library有一些已知的限制,所以当你在将他合并到你的应用程序中时需要测试一下:
1..dex文件的安装在启动设备的数据分区很复杂,如果二级dex文件太大可能导致程序没有响应(ANR)。在这种情况下,您应与混淆器(ProGuard)应用代码缩减技术,减少.dex文件的大小和删除未使用的部分代码。
2.程序不能在在早已Android4.0(API level 14)之前的版本上使用multidex由于a Dalvik linearAlloc bug(Issue 22586)(http://b.android.com/22586)如果你使用API Level 14之前的版本,确保执行您的应用程序在启动时或者装载特定的类时,测试你的程序是否会出现问题。代码缩减可以消除这些潜在问题。
3.应用程序使用multidex配置会发出非常大的内存分配请求,这可能会导致运行时崩溃,由于a Dalvik linearAlloc bug(Issue 78035)(http://b.android.com/78035)。
4.Dalvik runtime执行时the primary dex文件可能需要复杂的请求。Android build tooling 更新处理Android需求,但是其他included libraries可能有额外的依赖需要,包括调用本地的java代码。一些library可能无法使用,直到multidex build tools更新后允许您指定必须包含在主dex文件的类。
Optimizing Multidex Development Builds
multidex配置需要显著增加构建处理时间,因为构建系统必须做出复杂决定,来确定哪些类必须包含在主dex文件以及哪些类可以包含在第二级dex文件中。这意味着常规构建执行与multidex作为开发过程的一部分,通常需要更长的时间,这可能减缓你的程序开发进度。
为了减少multidex输出构建时间,你应该创建两个变量来使用Android构建输出插件Gradle productFlavors: a development flavor and a production flavor。
a development flavor,设定一个最低21的SDK版本。这个设置生成multidex输出比使用ART-supported格式要快得多。the release flavor,设定一个最低SDK版本匹配你的项目最低支持版本。这个设置生成一个multidex APK,与更多的设备兼容,但需要更长的时间来构建。
以下构建配置示例演示了如何在Gradle构建文件设置这些 flavors :
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'
}
完成了这个配置更改后,您可以使用与app的devDebug变量相结合的属性dev productFlavor和debug buildType。利用这个去创建一个minSdkVersion为Android API Level 21不使用proguard,启用multidex的debug app 。这些设置使Android gradle插件执行以下操作:
1.构建应用程序的每个模块(包括依赖库)作为单独的dex文件。这通常被称为pre-dexing。
2.包括每个dex文件没有修改APK文件
3.最重要的是,dex的模块文件不会被结合,所以可以避免来确定主dex文件内容的长时间运行的计算。
这些设置导致快速、增量构建,因为只有dex文件修改模块的会重新计算,重新包装成APK文件。这些设置构建APK只能用于测试Android 5.0及以上设备。然而,通过实现配置的flavors,你能够执行正常构建release-appropriate最低SDK和proguard设置
还可以建立其他变量,包括构建prodDebug变量,这需要更长的时间来构建,但可以用于测试外的开发。如果你从命令行执行gradle任务,您可以使用标准命令在结束的位置附加DevDebug(如./ gradlew installDevDebug)。
关于使用flavors与Gradle任务的更多信息,参考Gradle Plugin User Guide(http://tools.android.com/tech-docs/new-build-system/user-guide)
Tip:您也可以提供一个自定义清单,或者为每个flavor自定义一个应用程序类,允许你在变量需要的时候使用MultiDexApplication应用程序类库或者调用 MultiDex.install()。
Using Build Variants in Android Studio
Build variants对管理multidex构建过程是非常有用的,Android Studio可以使用可视化操作来选择这些变量。
1.打开位于 left-sidebar的Build Variants 窗口(一般是在Android studio的左下)
2.点击Build Variants的名称来选择不同的变量,,如图1所示
Testing Multidex Apps
当multidex应用程序中使用instrumentation tests时,需要进行额外的配置。因为代码在multidex应用程序中不是位于单一DEX文件。所以instrumentation tests不能正常运行,除非程序为multidex配置。
为了使用instrumentation tests测试multidex app,需要配置MultiDexTestRunner。
下面build.gradle文件演示了如何配置来使用这个测试运行器:
android {
defaultConfig {
...
testInstrumentationRunner "com.android.test.runner.MultiDexTestRunner"
}
}
Note: With Android Plugin for Gradle versions lower than 1.1, you need to add the following dependency for multidex-instrumentation:
dependencies {
androidTestCompile('com.android.support:multidex-instrumentation:1.0.1') {
exclude group: 'com.android.support', module: 'multidex'
}
}
你可以用instrumentation tests runner class直接或扩展它来适应您的测试需求。或者,您可以在现有的instrumentation中覆盖onCreate:
public void onCreate(Bundle arguments) {
MultiDex.install(getTargetContext());
super.onCreate(arguments);
...
}
Note: Use of multidex for creating a test APK is not currently supported.
Building Apps with Over 65K Methods(解决APP引用方法总数超过65536)的更多相关文章
- 解决DATASNAP远程方法参数超过32个的问题
群里有位同仁提出他有一个DATASNAP远程方法超过了32个参数,然后DELPHI编译通不过,提示方法参数不能超过32个,问怎么办?于是群内同仁纷纷出主意,我说用OLEVARINAT数组,有人说用RE ...
- 解决Android单个dex文件不能超过65536个方法问题
当我们的项目代码过大时,编译运行时会报Unable to execute dex: method ID not in[0, 0xffff]: 65536)错误.当出现这个错误时说明你本身自己的工程代码 ...
- Android开发训练之第五章——Building Apps with Connectivity & the Cloud
Building Apps with Connectivity & the Cloud These classes teach you how to connect your app to t ...
- android wear开发之:建立可穿戴设备的应用 - Building Apps for Wearables
注:本文内容来自:https://developer.android.com/training/building-wearables.html 翻译水平有限,如有疏漏,欢迎批评指教. 译:山人 建立可 ...
- Android Studio2.3.3卡在Building 'xxx' Gradle project info的解决方法
Android Studio版本:V2.3.3 操作系统环境:Ubuntu14.04 64bit 新安装好Android Studio后,在创建新的项目时或者在导入他人的项目代码时,Android ...
- SQLServer查看和解决死锁的方法
http://luohonghong.blog.163.com/blog/static/78312058201142411533316/ SQLServer查看和解决死锁的方法 2011-05-24 ...
- django中跨app引用model
可能是自己水平的原因,总感觉跨django中app引用有点怪怪的,所以在自己没有达到另一个级别之前就先把正确的解决 方案记一下吧. 一.django中跨app引用model,以app02中的model ...
- Flask-分开Models解决循环引用
Flask-分开Models解决循环引用 在之前我们测试中,所有语句都在同一个文件中,但随着项目越来越大,管理起来有所不便,所以将Models分离.基本的文件结构如下 \—–app.py\—–mode ...
- 深入研究Block用weakSelf、strongSelf、@weakify、@strongify解决循环引用(上)
深入研究Block捕获外部变量和__block实现原理 前言 在上篇中,仔细分析了一下Block的实现原理以及__block捕获外部变量的原理.然而实际使用Block过程中,还是会遇到一些问题,比如R ...
随机推荐
- 连接远程LINUX服务器
远程登陆linux服务器需要下载一个软件,非常好用,名字是SecureCRT5,百度搜索有很多,如果下载不到可以联系我 运行安装包,一路下一步就可以了 安装好后,运行该软件 点击左上角第二 ...
- jQuery 遍历同胞(siblings)
同胞拥有相同的父元素. 通过 jQuery,您能够在 DOM 树中遍历元素的同胞元素. 在 DOM 树中水平遍历 有许多有用的方法让我们在 DOM 树进行水平遍历: siblings() next() ...
- ArcGIS JS Demo
最近在用 ArcGIS 写了一个Demo 效果如下: 1. 引用 ArcGIS JS API arcgis_js_api/init.js 2. 引用 样式 arcgis_js_api/js/esri/ ...
- Java中报错No enclosing instance of type caiquan is accessible. Must qualify the allocation with an enclosing instance of type caiquan (e.g. x.new A() where x is an instance of caiquan).
package test;import java.util.Scanner;import java.util.Random;public class caiquan { public static v ...
- vertical-align的深入学习
W3C官方对vertical-align属性的定义有4个方面: (1)vertical-align属性用于定义“周围的文字.inline元素以及inline-block元素”相对于该元素基线的垂 ...
- CentOS6.5使用本地光盘做yum源 (参考:http://www.jb51.net/os/RedHat/43343.html)
一.使用光盘做yum源安装软件 mkdir /media/CentOS #新建CentOS挂载目录 mount -t auto /dev/cdrom /media/CentOS #挂载CentOS光 ...
- PHP扩展Redis编译安装
PHP扩展Redis编译安装 1.下载PHP官方Redis源码包 wget http://pecl.php.net/get/redis-2.2.4.tgz 注:我用的是Redhat系统,ubunt ...
- php 获取客户端IP地址
/** * 获取真实IP地址 */ /* 在PHP中getenv(参数)函数是一个用于获取环境变量的函数,根据提供不同的参数可以获取不同的环境变量, getenv("REMOTE_ADDR& ...
- 一些static_cast const_cast
static_cast:干杂活的,那三个都有各自的专有用途,那三个不做的都由这个转型符来做,只要它能做的,用C语法的强制类型转换运算符也一定能够完成:但话又说回来了,C强制类型转换能做的,它可不一定都 ...
- Ubuntu 在右键快捷菜单中添加“Open in Terminal”
操作步骤翻译如下: 1.打开一个Terminal(ctrl+alt+t),输入如下指令 sudo apt-get install nautilus-open-terminal 2.使用以下指令来重启N ...