PC パソコン

Android Studio「Duplicate class found in modules」の原因と解決方法

Android Studioでアプリをビルドしたときに、
Duplicate class ... found in modules ...
と表示され、ビルドできないことがあります。

このエラーは、
同じクラスが複数のライブラリや依存関係に含まれているため、
Androidのビルドシステムがどちらのクラスを使用すればよいか判断できない場合に発生します。

この記事では、
Duplicate class found in modulesが発生する主な原因と、
Android Studioで重複している依存関係を確認し、
エラーを解消する方法を順番に解説します。

Duplicate class found in modulesとは

Duplicate class found in modulesは、
Android Studioでアプリをビルドするときに、
同じ名前のクラスが複数のモジュールやライブラリから見つかった場合に発生するエラーです。

Androidアプリでは、
Gradleを利用してさまざまなライブラリをプロジェクトへ追加できます。
しかし、追加した複数のライブラリが同じクラスを含んでいる場合や、
同じライブラリの異なるバージョンが同時に読み込まれている場合には、
クラスの重複が発生することがあります。

この状態では、
ビルド時にどのクラスを使用するのか決定できないため、
ビルドが停止します。

ポイント:
Duplicate class found in modulesは、
JavaやKotlinのソースコードに同じクラスを2回書いた場合だけでなく、
Gradleの依存関係が重複している場合にも発生します。
実際にはライブラリ同士の依存関係が原因になっているケースが多くあります。

代表的なエラー表示

Duplicate class com.example.SomeClass found in modules
library-a.jar and library-b.jar

実際には、
modulesの後に重複しているライブラリや
JAR、AARなどの名前が表示されます。

たとえば次のように、
同じクラスが2つの依存関係から読み込まれていることが分かる場合があります。

Duplicate class com.example.SomeClass found in modules
library-one-1.0.jar
and
library-two-2.0.jar

この場合は、
エラーメッセージに表示されている2つのモジュールを確認し、
なぜ両方がプロジェクトへ追加されているのかを調べます。

まずエラーメッセージで重複しているライブラリを確認する

Duplicate class found in modulesが発生した場合は、
最初にBuild Outputに表示されているエラー全文を確認します。

特に重要なのは、
found in modulesの後に表示されるライブラリ名です。

Duplicate class ...
found in modules
library-a
and
library-b

この2つが、
同じクラスを含んでいる依存関係です。

エラーには多数の
Duplicate classが連続して表示されることがありますが、
すべて別々の問題とは限りません。

1組のライブラリが重複していることによって、
そのライブラリ内に含まれる多数のクラスがまとめて重複エラーとして表示される場合があります。

原因1:同じライブラリを二重に追加している

最も単純な原因は、
同じライブラリを複数回追加しているケースです。

たとえば、
モジュールのGradle設定に同じ依存関係が重複して記述されている場合があります。

dependencies {
    implementation("com.example:sample-library:1.0.0")
    implementation("com.example:sample-library:1.0.0")
}

この場合は、
不要な方の依存関係を削除します。

dependencies {
    implementation("com.example:sample-library:1.0.0")
}

build.gradle
build.gradle.ktsを確認し、
同じライブラリが複数回追加されていないか確認します。

原因2:同じライブラリの異なるバージョンが含まれている

同じライブラリの異なるバージョンが、
別々の依存関係を経由してプロジェクトへ含まれることがあります。

たとえば、
アプリ側では新しいバージョンを直接指定している一方で、
別のライブラリが古いバージョンを依存関係として持っている場合があります。

implementation("com.example:library-a:2.0.0")
implementation("com.example:library-b:1.0.0")

library-bが内部で
library-a:1.0.0を利用している場合などは、
依存関係の組み合わせによって重複が発生することがあります。

この場合は、
どのライブラリがどの依存関係を追加しているのか確認する必要があります。

Gradleの依存関係を確認する

依存関係の重複元が分からない場合は、
Gradleの依存関係ツリーを確認します。

Android StudioのTerminalから、
プロジェクトに応じて次のようなコマンドを実行します。

./gradlew app:dependencies

Windowsでは、
環境によって次のように実行します。

gradlew app:dependencies

実行すると、
アプリモジュールで使用されている依存関係がツリー形式で表示されます。

エラーに表示されているライブラリ名を探し、
どのライブラリから追加されているのか確認します。

特定の依存関係を詳しく確認する

特定のライブラリがどこから追加されているのか詳しく調べたい場合は、
Gradleの
dependencyInsightを利用できます。

./gradlew app:dependencyInsight \
--dependency ライブラリ名 \
--configuration debugRuntimeClasspath

これにより、
指定した依存関係がどの経路から追加されているのか確認できます。

使用しているビルドタイプによっては、
debugRuntimeClasspathではなく
releaseRuntimeClasspathなどを指定する場合があります。

解決方法1:不要な依存関係を削除する

重複しているライブラリのうち、
アプリ側で直接追加する必要がないものがある場合は、
不要な依存関係を削除します。

たとえば、
あるライブラリを直接追加しているものの、
別のライブラリからすでに同じものが読み込まれている場合があります。

dependencies {
    implementation("com.example:library-a:1.0.0")
    implementation("com.example:library-b:1.0.0")
}

library-b
library-aを内部で含んでおり、
アプリ側から直接追加する必要がないのであれば、
library-aの直接指定を削除できる場合があります。

解決方法2:excludeで重複する依存関係を除外する

必要なライブラリの内部から、
重複している別の依存関係が追加されている場合は、
Gradleの
excludeを利用して除外できます。

Kotlin DSLでは、
たとえば次のように記述します。

implementation("com.example:library-a:1.0.0") {
    exclude(group = "com.example", module = "duplicate-library")
}

Groovy DSLでは、
次のような形式になります。

implementation("com.example:library-a:1.0.0") {
    exclude group: "com.example", module: "duplicate-library"
}

これにより、
指定したライブラリを経由して追加される
duplicate-libraryを除外できます。

注意:
excludeで依存関係を削除すると、
元のライブラリがその依存関係を必要としている場合に
実行時エラーなどが発生する可能性があります。
重複しているからという理由だけで除外せず、
どちらのライブラリを残すべきか確認してから設定します。

解決方法3:ライブラリのバージョンを揃える

異なるバージョンのライブラリが混在している場合は、
できるだけ同じバージョン系列へ揃えることを検討します。

たとえば複数の関連ライブラリを使用している場合、
一部だけ古いバージョンになっていることで
依存関係の不整合が発生することがあります。

implementation("com.example:library-core:2.0.0")
implementation("com.example:library-ui:2.0.0")

ライブラリの公式ドキュメントなどを確認し、
互換性のあるバージョンの組み合わせを使用します。

原因3:古いSupport LibraryとAndroidXが混在している

古いプロジェクトでは、
Android Support LibraryとAndroidXが混在することで
クラス重複や依存関係の問題が発生する場合があります。

たとえば、
古いSupport Libraryを使用するライブラリと、
AndroidXを使用するライブラリが同時に含まれている場合です。

プロジェクトをAndroidXへ移行している場合は、
gradle.propertiesなどの設定も確認します。

android.useAndroidX=true
android.enableJetifier=true

ただし、
使用しているAndroid Gradle Pluginやライブラリの状況によっては、
Jetifierを必要としない構成もあります。

古いライブラリを利用している場合は、
AndroidXへ対応した新しいバージョンが提供されていないか確認します。

原因4:JARやAARを手動追加している

libsフォルダへJARやAARを直接追加している場合、
Gradleの依存関係として同じライブラリも追加されていると、
クラスが二重に読み込まれることがあります。

たとえば、
次のようなファイルがプロジェクトにあるとします。

app/libs/sample-library.jar

さらにGradleでも同じライブラリを指定している場合、
同じクラスが重複する可能性があります。

implementation("com.example:sample-library:1.0.0")

この場合は、
JARやAARを手動で使用するのか、
Gradle経由で使用するのかを確認し、
不要な方を削除します。

libsフォルダを確認する

原因が分からない場合は、
アプリモジュール内の
libsフォルダも確認します。

app/libs/

この中に古いJARやAARが残っている場合、
現在Gradleから取得しているライブラリと重複している可能性があります。

以前手動で追加したライブラリを、
後からGradle依存関係へ変更した場合などは特に確認します。

原因5:ローカルモジュールと外部ライブラリが重複している

プロジェクト内に同じ機能を持つローカルモジュールが存在し、
同時に同じライブラリを外部依存関係として追加している場合にも、
クラスが重複することがあります。

たとえば、
ローカルモジュールとして次のように追加しているとします。

implementation(project(":samplelibrary"))

さらに、
同じライブラリの公開版を追加している場合です。

implementation("com.example:samplelibrary:1.0.0")

同じクラスが両方に含まれている場合は、
どちらか一方だけを使用するようにします。

原因6:FirebaseやGoogle Play servicesの依存関係が不統一

FirebaseやGoogle Play servicesなど、
多数の関連ライブラリを使用するサービスでは、
依存関係の組み合わせによって問題が発生することがあります。

古いバージョンのライブラリと新しいバージョンのライブラリを
同時に使用している場合などは、
依存関係の構成を確認します。

Firebaseを使用している場合は、
Firebase BoMを利用して関連ライブラリのバージョンを管理する方法もあります。

implementation(platform("com.google.firebase:firebase-bom:VERSION"))
implementation("com.google.firebase:firebase-analytics")
implementation("com.google.firebase:firebase-auth")

VERSIONには、
使用するFirebase BoMのバージョンを指定します。

原因7:古いライブラリが別のライブラリを内部に含んでいる

一部の古いライブラリでは、
必要な依存ライブラリをAARやJARの内部へ直接含めている場合があります。

このようなライブラリと、
同じ依存ライブラリをGradleから追加すると、
同一クラスが重複することがあります。

この場合は、
ライブラリの新しいバージョンが提供されていないか確認し、
可能であれば依存関係の管理方法が改善された新しいバージョンへ更新します。

同じクラスを自分で作成していないか確認する

依存関係だけでなく、
プロジェクト内のソースコード自体に
同じ完全修飾クラス名を持つクラスが存在していないかも確認します。

たとえば、
同じパッケージ内に同名のクラスが複数存在すると、
重複が発生します。

com.example.app.SampleClass

ファイルをコピーした後に古いファイルが残っている場合や、
Java版とKotlin版の同じクラスを両方残している場合なども確認します。

依存関係を修正したらGradle Syncを実行する

build.gradle
build.gradle.ktsの依存関係を修正した場合は、
Gradle Syncを実行します。

Android Studio上でGradleの同期を行い、
新しい依存関係の構成をプロジェクトへ反映します。

その後、
再度アプリをビルドして
Duplicate class found in modulesが解消されたか確認します。

Clean ProjectやRebuild Projectも確認する

依存関係を修正した後もエラーが残っている場合は、
古いビルド結果が残っている可能性もあります。

Android Studioの
Buildメニューから、
使用しているAndroid Studioのバージョンで利用可能な
CleanやRebuildに相当する処理を実行します。

その後、
もう一度ビルドしてエラーが残っているか確認します。

それでもDuplicate class found in modulesが直らない場合

エラーが解消しない場合は、
エラーメッセージに表示されているクラス名とモジュール名を基準に、
依存関係を一つずつ確認します。

  1. Build OutputでDuplicate classのエラー全文を確認します。
  2. found in modulesに表示されている2つのライブラリを確認します。
  3. ./gradlew app:dependenciesで依存関係を確認します。
  4. 必要に応じてdependencyInsightで依存元を確認します。
  5. 同じライブラリを直接二重に追加していないか確認します。
  6. 同じライブラリの異なるバージョンが含まれていないか確認します。
  7. libsフォルダのJARやAARを確認します。
  8. ローカルモジュールと外部ライブラリが重複していないか確認します。
  9. 必要に応じて不要な依存関係を削除するかexcludeを設定します。
  10. Gradle Sync後に再度ビルドします。

エラーに大量のDuplicate classが表示される場合

Build Outputに数十件から数百件の
Duplicate classが表示されることがあります。

この場合でも、
すべてのクラスを1つずつ修正する必要があるとは限りません。

1つのライブラリが丸ごと重複している場合、
そのライブラリに含まれる多数のクラスがすべて
Duplicate classとして表示されます。

最初の数件のエラーに表示されている
found in modulesの内容を確認し、
同じ2つのライブラリが繰り返し表示されている場合は、
その依存関係の重複を解消します。

大量のDuplicate classが表示されても、
大量のソースコード修正が必要とは限りません。
1つの重複した依存関係を修正するだけで、
多数のエラーがまとめて解消される場合があります。

まとめ

Android Studioの
Duplicate class found in modulesは、
同じクラスが複数のライブラリやモジュールに含まれている場合に発生するエラーです。

まずBuild Outputに表示されている
found in modulesの内容を確認し、
どの2つのライブラリが重複しているのかを特定します。

そのうえで、
同じライブラリの二重登録、
異なるバージョンの混在、
推移的依存関係、
JARやAARの手動追加、
ローカルモジュールとの重複などを確認します。

依存元が分からない場合は、
./gradlew app:dependencies
dependencyInsightを利用すると、
どのライブラリから依存関係が追加されているのか確認できます。

Duplicate class found in modulesを解決するときは、
エラーに表示されたクラスそのものを削除するのではなく、
「なぜ同じクラスが2つのモジュールから読み込まれているのか」を確認することが重要です。
重複している依存関係を特定し、
不要な依存関係の削除、バージョンの統一、
または必要に応じたexcludeで解消します。