나는 이전에 다양한 버전의 덱스 부식을 보았지만 이것은 새로운 것이다. 청소 / 다시 시작 등은 도움이되지 않습니다. 라이브러리 프로젝트는 손상되지 않은 것으로 보이며 종속성이 올바르게 연결된 것 같습니다.
Unable to execute dex: method ID not in [0, 0xffff]: 65536
Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536
또는
Cannot merge new index 65950 into a non-jumbo instruction
또는
java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536
tl; dr : Google의 공식 솔루션이 마침내 나왔습니다!
http://developer.android.com/tools/building/multidex.html
작은 팁 하나만 있으면 덱싱 할 때 메모리 부족을 방지하기 위해이 작업을 수행해야합니다.
dexOptions {
javaMaxHeapSize "4g"
}
덜 안정적인 방식으로이 문제를 해결할 수있는 점보 모드도 있습니다.
dexOptions {
jumboMode true
}
업데이트 : 앱이 뚱뚱하고 기본 앱 내에 너무 많은 방법이있는 경우 앱을 다시 구성해야합니다
http://blog.osom.info/2014/12/too-many-methods-in-main-dex.html
답변
업데이트 3 (
2014 년 11 월 3 일) Google은 마침내 공식 설명을 발표했습니다 .
Android 용 업데이트 2 ( 2014 년 10 월 31 일 ) Gradle 플러그인 v0.14.0 에는 멀티 덱스 지원 이 추가 되었습니다. 활성화하려면 build.gradle 에 선언해야합니다 .
android {
defaultConfig {
...
multiDexEnabled true
}
}
응용 프로그램이 5.0 이전의 Android를 지원하는 경우 (즉, minSdkVersion
20 이하인 경우) 응용 프로그램 ClassLoader 를 동적으로 패치해야 하므로 보조 dexe에서 클래스를로드 할 수 있습니다. 다행히도이를위한 라이브러리 가 있습니다. 앱의 종속성에 추가하십시오.
dependencies {
...
compile 'com.android.support:multidex:1.0.0'
}
가능한 빨리 ClassLoader 패치 코드를 호출해야합니다. MultiDexApplication
클래스의 문서에는 세 가지 방법이 있습니다 ( 가장 편리한 방법 중 하나를 선택 하십시오).
1- AndroidManifest.xmlMultiDexApplication
에서 애플리케이션으로 클래스를 선언 하십시오 .
<?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>
2- Application
클래스가 MultiDexApplication 클래스를 확장하도록 하십시오 .
public class MyApplication extends MultiDexApplication { .. }
3- MultiDex#install
당신의 Application#attachBaseContext
방법 에서 전화 :
public class MyApplication {
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
....
}
....
}
업데이트 1 ( 2014 년 10 월 17 일 ) :
예상대로 멀티 덱스 지원 은 Android 지원 라이브러리의 개정판 21에 제공됩니다. android-support-multidex.jar은 / sdk / extras / android / support / multidex / library / libs 폴더에 있습니다.
멀티 덱스 지원으로이 문제를 해결합니다. dx 1.8은 이미 여러 dex 파일을 생성 할 수 있습니다.
Android L은 기본적으로 멀티 덱스를 지원하며, 다음 버전의 지원 라이브러리는 이전 릴리스를 API 4로 다시 지원합니다.
Anwar Ghuloum 의이 Android Developers Backstage 팟 캐스트 에피소드 에서 언급되었습니다 . 나는 한 성적 증명서 게시 된 관련 부분 (일반 멀티 덱스 설명).
답변
이미 언급했듯이 프로젝트와 라이브러리에 너무 많은 메소드 (65k 이상)가 있습니다.
문제 방지 : Play Services 6.5 이상 및 support-v4 24.2 이상으로 방법 수 감소
Google Play 서비스는 종종 20 만 개 이상의 메소드를 사용하여 “낭비하는”메소드의 주요 용의자 중 하나입니다 . Google Play 서비스 버전 6.5 이상 에서는 여러 개의 작은 클라이언트 라이브러리를 사용하여 애플리케이션에 Google Play 서비스 를 포함시킬 수 있습니다. 예를 들어 GCM과지도 만 필요한 경우 다음 종속성 만 사용하도록 선택할 수 있습니다.
dependencies {
compile 'com.google.android.gms:play-services-base:6.5.+'
compile 'com.google.android.gms:play-services-maps:6.5.+'
}
하위 라이브러리의 전체 목록과 책임은 공식 google doc에서 찾을 수 있습니다 .
업데이트 : Support Library v4 v24.2.0부터 다음 모듈로 분할되었습니다.
support-compat
,support-core-utils
,support-core-ui
,support-media-compat
및support-fragment
dependencies {
compile 'com.android.support:support-fragment:24.2.+'
}
그러나를 사용 support-fragment
하면 다른 모든 모듈에 종속됩니다 (즉, 사용 android.support.v4.app.Fragment
하지 않는 경우 )
support-v4 lib의 공식 릴리스 노트를 참조하십시오.
멀티 덱싱 활성화
Lollipop (일명 빌드 도구 21+)이므로 다루기가 매우 쉽습니다. 이 방법은 덱스 파일 당 65k 메서드 문제를 해결하여 앱에 여러 덱스 파일을 만드는 것입니다. gradle 빌드 파일에 다음을 추가하십시오 ( 이는 65k 이상의 메소드가있는 응용 프로그램의 공식 Google 문서에서 가져옵니다 ).
android {
compileSdkVersion 21
buildToolsVersion "21.1.0"
defaultConfig {
...
// Enabling multidex support.
multiDexEnabled true
}
...
}
dependencies {
compile 'com.android.support:multidex:1.0.1'
}
두 번째 단계는 애플리케이션 클래스를 준비하거나 애플리케이션을 확장하지 않는 경우 MultiDexApplication
Android Manifest에서를 사용하는 것 입니다.
이것을 Application.java에 추가하십시오.
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
또는 mutlidex lib에서 제공된 응용 프로그램을 사용하십시오.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.myapplication">
<application
...
android:name="android.support.multidex.MultiDexApplication">
...
</application>
</manifest>
MultiDex로 OutOfMemory 방지
추가 팁으로, OutOfMemory
빌드 단계에서 예외가 발생하면 다음을 사용하여 힙을 확대 할 수 있습니다.
android {
...
dexOptions {
javaMaxHeapSize "4g"
}
}
힙을 4 기가 바이트로 설정합니다.
dex 힙 메모리 문제에 대한 자세한 내용은이 질문을 참조하십시오.
문제의 원인 분석
메소드의 소스를 분석하기 위해 gradle 플러그인 https://github.com/KeepSafe/dexcount-gradle-plugin 은 gradle이 제공하는 종속성 트리와 함께 도움이 될 수 있습니다.
.\gradlew app:dependencies
답변
프로젝트가 너무 큽니다. 방법이 너무 많습니다. 애플리케이션 당 65536 개의 메소드 만있을 수 있습니다. 여기에서 볼 https://code.google.com/p/android/issues/detail?id=7147#c6
답변
Gradle을 사용하면 아래 코드가 도움이됩니다. 불필요한 Google 서비스 (사용중인 것으로 가정)를 쉽게 제거하여 65k 임계 값 아래로 돌아갈 수 있습니다. 이 게시물에 대한 모든 크레딧 : https://gist.github.com/dmarcato/d7c91b94214acd936e42
편집 2014-10-22 : 위에서 언급 한 요점에 대해 많은 흥미로운 토론이있었습니다. TLDR? 이것 하나를보십시오 : https://gist.github.com/Takhion/10a37046b9e6d259bb31
이 코드를 build.gradle 파일의 맨 아래에 붙여 넣고 필요하지 않은 Google 서비스 목록을 조정하십시오.
def toCamelCase(String string) {
String result = ""
string.findAll("[^\\W]+") { String word ->
result += word.capitalize()
}
return result
}
afterEvaluate { project ->
Configuration runtimeConfiguration = project.configurations.getByName('compile')
ResolutionResult resolution = runtimeConfiguration.incoming.resolutionResult
// Forces resolve of configuration
ModuleVersionIdentifier module = resolution.getAllComponents().find { it.moduleVersion.name.equals("play-services") }.moduleVersion
String prepareTaskName = "prepare${toCamelCase("${module.group} ${module.name} ${module.version}")}Library"
File playServiceRootFolder = project.tasks.find { it.name.equals(prepareTaskName) }.explodedDir
Task stripPlayServices = project.tasks.create(name: 'stripPlayServices', group: "Strip") {
inputs.files new File(playServiceRootFolder, "classes.jar")
outputs.dir playServiceRootFolder
description 'Strip useless packages from Google Play Services library to avoid reaching dex limit'
doLast {
copy {
from(file(new File(playServiceRootFolder, "classes.jar")))
into(file(playServiceRootFolder))
rename { fileName ->
fileName = "classes_orig.jar"
}
}
tasks.create(name: "stripPlayServices" + module.version, type: Jar) {
destinationDir = playServiceRootFolder
archiveName = "classes.jar"
from(zipTree(new File(playServiceRootFolder, "classes_orig.jar"))) {
exclude "com/google/ads/**"
exclude "com/google/android/gms/analytics/**"
exclude "com/google/android/gms/games/**"
exclude "com/google/android/gms/plus/**"
exclude "com/google/android/gms/drive/**"
exclude "com/google/android/gms/ads/**"
}
}.execute()
delete file(new File(playServiceRootFolder, "classes_orig.jar"))
}
}
project.tasks.findAll { it.name.startsWith('prepare') && it.name.endsWith('Dependencies') }.each { Task task ->
task.dependsOn stripPlayServices
}
}
답변
custom_rules.xml 빌드 스크립트와 몇 줄의 코드를 사용하여이 문제를 해결하는 샘플 프로젝트를 공유했습니다.
나는 내 자신의 프로젝트에서 그것을 사용했고 1M + 장치에서 완벽하게 실행됩니다 (android-8에서 최신 android-19까지). 도움이 되길 바랍니다.
답변
같은 문제에 직면하고 dependencies 섹션에서 build.gradle 파일을 편집하여 다음을 제거하여 해결했습니다.
compile 'com.google.android.gms:play-services:7.8.0'
그리고 그것을 다음과 같이 대체하십시오 :
compile 'com.google.android.gms:play-services-location:7.8.0'
compile 'com.google.android.gms:play-services-analytics:7.8.0'
답변
build.gradle에 아래 코드를 추가해보십시오.
compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
multiDexEnabled true
}