Android Studio 3.0 で Unable to merge dex ビルドエラーの対処法

Android Studio 3.0 へ移行するための動作確認を行って際に結構ハマったので情報共有します。

## エラー内容
- [Android Studio 2.3から3.0へのマイグレーションポイント - Qiita](https://qiita.com/eaglesakura/items/133aa7130dea81c9fc1e)
- [Migrate to Android Plugin for Gradle 3.0.0 - Android Devlper](https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html)

上記などを参考に移行の作業を行い、最後に実機での確認を行った際に下記エラーが発生。

```
 Execution failed for task ':app:transformDexArchiveWithExternalLibsDexMergerForDebug'.
14:57:28.124 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] 
> com.android.builder.dexing.DexArchiveMergerException: Unable to merge dex
```

## 原因
Gradleに登録しているライブラリが依存しているライブラリ（日本語難しいですね）が、重複していたため
例えば、AというライブラリはBライブラリを使用していて、CライブラリもBライブラリを使用していた、など。

## 対処法
まずは、コンパイルオプションに`--stacktrace` を付けてビルドし、何が重複したのかを特定します。
コンパイルオプションは、`Preference > Build, Execution, Development > Compiler > Command-line Options`で帰れます。今回の問題のみならず、何かコンパイルでエラーが発生したときはこれを使えばだいたい何が悪いのかわかります。

今回こちらの環境では下記が問題になっていました。

```
Caused by: com.android.dex.DexException: Multiple dex files define Lorg/objectweb/asm/AnnotationWriter;
```

`org.objectweb`とか`asm`というのが問題のようです。

続いて、どのライブラリが上記使っているのかを探します。

コマンドラインで下記コマンドを入力します。Windowsの人は適宜読み替えてください。

`./gradlew app:dependencies`

すると、下記のように使用しているライブラリの依存ツリーが表示されるので、どのライブラリが使っているのかを特定します。

```
debugRuntimeClasspath - Resolved configuration for runtime for variant: debug
    +--- org.jacoco:org.jacoco.agent:0.7.4.201502262128
    +--- com.android.support:design:26.0.2
    |    +--- com.android.support:support-v4:26.0.2
    |    |    +--- com.android.support:support-compat:26.0.2
    |    |    |    \--- com.android.support:support-annotations:26.0.2 -> 26.1.0
    |    |    +--- com.android.support:support-media-compat:26.0.2
    |    |    |    +--- com.android.support:support-annotations:26.0.2 -> 26.1.0
    |    |    |    \--- com.android.support:support-compat:26.0.2 (*)
    |    |    +--- com.android.support:support-core-utils:26.0.2
    |    |    |    +--- com.android.support:support-annotations:26.0.2 -> 26.1.0
    |    |    |    \--- com.android.support:support-compat:26.0.2 (*)
    |    |    +--- com.android.support:support-core-ui:26.0.2
    |    |    |    +--- com.android.support:support-annotations:26.0.2 -> 26.1.0
    |    |    |    \--- com.android.support:support-compat:26.0.2 (*)
    |    |    \--- com.android.support:support-fragment:26.0.2
    |    |         +--- com.android.support:support-compat:26.0.2 (*)
    |    |         +--- com.android.support:support-core-ui:26.0.2 (*)
    |    |         \--- com.android.support:support-core-utils:26.0.2 (*)
    |    +--- com.android.support:appcompat-v7:26.0.2
    |    |    +--- com.android.support:support-annotations:26.0.2 -> 26.1.0
    |    |    +--- com.android.support:support-v4:26.0.2 (*)
    |    |    +--- com.android.support:support-vector-drawable:26.0.2
    |    |    |    +--- com.android.support:support-annotations:26.0.2 -> 26.1.0
    |    |    |    \--- com.android.support:support-compat:26.0.2 (*)
    |    |    \--- com.android.support:animated-vector-drawable:26.0.2
    |    |         +--- com.android.support:support-vector-drawable:26.0.2 (*)
    |    |         \--- com.android.support:support-core-ui:26.0.2 (*)
    |    +--- com.android.support:recyclerview-v7:26.0.2
    |    |    +--- com.android.support:support-annotations:26.0.2 -> 26.1.0
    |    |    +--- com.android.support:support-compat:26.0.2 (*)
    |    |    \--- com.android.support:support-core-ui:26.0.2 (*)
    |    \--- com.android.support:transition:26.0.2
    |         +--- com.android.support:support-annotations:26.0.2 -> 26.1.0
    |         \--- com.android.support:support-v4:26.0.2 (*)
    +--- com.android.support:appcompat-v7:26.0.2 (*)
    +--- com.squareup.retrofit2:retrofit:2.3.0
    |    \--- com.squareup.okhttp3:okhttp:3.8.0
    |         \--- com.squareup.okio:okio:1.13.0
    +--- com.squareup.retrofit2:retrofit-mock:2.3.0
    |    \--- com.squareup.retrofit2:retrofit:2.3.0 (*)
    +--- com.squareup.retrofit2:converter-gson:2.3.0
    |    +--- com.squareup.retrofit2:retrofit:2.3.0 (*)
    |    \--- com.google.code.gson:gson:2.7 -> 2.8.2
    +--- com.squareup.retrofit2:adapter-rxjava:2.3.0
    |    +--- com.squareup.retrofit2:retrofit:2.3.0 (*)
    |    \--- io.reactivex:rxjava:1.3.0
    +--- com.squareup.okhttp3:logging-interceptor:3.8.0
    |    \--- com.squareup.okhttp3:okhttp:3.8.0 (*)
    +--- io.reactivex:rxandroid:1.2.1
    |    \--- io.reactivex:rxjava:1.1.6 -> 1.3.0
    +--- io.reactivex:rxjava:1.1.6 -> 1.3.0
    +--- com.trello:rxlifecycle:1.0
    |    +--- io.reactivex:rxjava:1.2.1 -> 1.3.0
    |    \--- com.google.code.findbugs:jsr305:3.0.1
    +--- com.trello:rxlifecycle-android:1.0
    |    +--- com.trello:rxlifecycle:1.0 (*)
    |    \--- com.jakewharton.rxbinding:rxbinding:0.4.0
    |         +--- io.reactivex:rxandroid:1.1.0 -> 1.2.1 (*)
    |         +--- io.reactivex:rxjava:1.1.0 -> 1.3.0
    |         \--- com.android.support:support-annotations:23.1.0 -> 26.1.0
    +--- com.trello:rxlifecycle-components:1.0
    |    +--- com.trello:rxlifecycle-android:1.0 (*)
    |    +--- io.reactivex:rxjava:1.2.1 -> 1.3.0
    |    \--- com.android.support:appcompat-v7:25.0.0 -> 26.0.2 (*)
    +--- com.google.guava:guava:20.0
    +--- com.google.code.gson:gson:2.8.2
    +--- com.jayway.jsonpath:json-path:2.0.0
    |    +--- org.slf4j:slf4j-api:1.7.10
    |    \--- net.minidev:json-smart:2.1.1
    |         \--- net.minidev:asm:1.0.2
    |              \--- asm:asm:3.3.1
    +--- me.dm7.barcodescanner:zxing:1.9.8
    |    +--- me.dm7.barcodescanner:core:1.9.8
    |    |    \--- com.android.support:support-v4:25.3.1 -> 26.0.2 (*)
    |    \--- com.google.zxing:core:3.3.0
    +--- com.twilio:video-android:1.3.4
    |    +--- com.android.support:support-annotations:26.1.0
    |    \--- com.getkeepsafe.relinker:relinker:1.2.2
    +--- com.wang.avi:library:2.1.3
    +--- uk.co.chrisjenx:calligraphy:2.3.0
    |    \--- com.android.support:appcompat-v7:25.3.1 -> 26.0.2 (*)
    +--- com.jakewharton:butterknife:8.8.1
    |    +--- com.jakewharton:butterknife-annotations:8.8.1
    |    |    \--- com.android.support:support-annotations:25.3.0 -> 26.1.0
    |    +--- com.android.support:support-annotations:25.3.0 -> 26.1.0
    |    \--- com.android.support:support-compat:25.3.0 -> 26.0.2 (*)
    +--- com.daimajia.easing:library:2.1
    |    \--- com.android.support:appcompat-v7:25.1.1 -> 26.0.2 (*)
    +--- com.daimajia.androidanimations:library:2.3
    +--- com.microsoft.azure.mobile:mobile-center-analytics:0.12.0
    |    \--- com.microsoft.azure.mobile:mobile-center:0.12.0
    +--- com.microsoft.azure.mobile:mobile-center-crashes:0.12.0
    |    \--- com.microsoft.azure.mobile:mobile-center:0.12.0
    \--- net.danlew:android.joda:2.9.9
         \--- joda-time:joda-time:2.9.9

```
`json-path`が、`net.minidev:asm:1.0.2`を使っているのがわかりました。
そこで、このライブラリに対してexcludeコマンドをつかって除外してやります。

```
compile('com.jayway.jsonpath:json-path:2.0.0') {
    exclude group: 'net.minidev', module: 'asm'
}

```

これで終わりです。

あとは、念のために、プロジェクト直下の`./gradle`,`build`と`app/build`を削除して、`Clean` -> `Rebuild`します。
私はこの方法で解消できました。

## その他のアプローチ

いろいろ調べていく中で他の方法でも、上手く行った人がいるようなのでご紹介します。試してみると良いかもしれません。

- ただ単に、`Clean` -> `Rebuild`
- `app/build.gradle` に `multiDexEnabled true` を追加
- `compileSdkVersion`, `compileSdkVersion`, `supportLibVersion` を全て同じバージョンに揃える
- プロジェクト直下の`./gradle`,`build`と`app/build`を削除して、`Clean` -> `Rebuild`
- Google Play Services を最新バージョンにアップデート
- `app/build.gradle` に `dexOption` に `jumboMode true` を追加する
- complie を implementationに、 testCompiple を testImplementationに、 testImplementation を androidTestImplementationに置き換える

## 参考
- https://stackoverflow.com/questions/47360856/unable-to-merge-dex-android-studio-3-0-build-error/47383686#47383686

- https://stackoverflow.com/questions/46980900/android-studio-3-0-unable-to-merge-dex