Android Studioでアプリをビルドしたときに、
Program type already present
と表示され、ビルドできないことがあります。
このエラーは、
同じクラスが複数のライブラリや依存関係に含まれているため、
Androidのビルド処理で同一クラスが重複して検出された場合に発生します。
特に古いAndroid StudioやAndroid Gradle Pluginを使用しているプロジェクト、
古いライブラリを含むプロジェクト、
JARやAARを手動で追加しているプロジェクトなどで見られることがあります。
この記事では、
Program type already presentが発生する主な原因と、
Android Studioで重複しているクラスや依存関係を確認し、
エラーを解消する方法を順番に解説します。
- Program type already presentとは
- 代表的なエラー表示
- まずBuild Outputで重複しているクラス名を確認する
- 原因1:同じライブラリを二重に追加している
- 原因2:JARやAARとGradle依存関係が重複している
- libsフォルダを確認する
- 原因3:古いSupport LibraryとAndroidXが混在している
- AndroidXの設定を確認する
- 原因4:同じライブラリの異なるバージョンが含まれている
- Gradleの依存関係ツリーを確認する
- dependencyInsightで依存元を確認する
- 解決方法1:不要な依存関係を削除する
- 解決方法2:excludeで重複する依存関係を除外する
- 解決方法3:ライブラリのバージョンを揃える
- 原因5:Google Play servicesやFirebaseの依存関係が重複している
- 原因6:ローカルモジュールと公開ライブラリが重複している
- 原因7:古いライブラリが依存ライブラリを内部に含んでいる
- 原因8:プロジェクト内に同じクラスが複数存在する
- debugとreleaseなどのソースセットも確認する
- 依存関係を修正したらGradle Syncを実行する
- CleanやRebuildを実行する
- それでもProgram type already presentが直らない場合
- Program type already presentが大量に表示される場合
- Duplicate class found in modulesとの違い
- まとめ
Program type already presentとは
Program type already presentは、
Androidアプリをビルドするときに、
同じクラスが複数の場所から読み込まれている場合に発生するエラーです。
Androidアプリでは、
Gradleを利用して複数のライブラリを組み合わせることができます。
しかし、
2つ以上のライブラリに同じクラスが含まれていたり、
同じライブラリを別の方法で二重に追加していたりすると、
ビルド時に同じクラスが複数回検出されます。
その結果、
Program type already present
と表示されてビルドが停止することがあります。
ポイント:
Program type already presentは、
主に古いAndroidビルド環境で見られるエラー表示です。
現在のAndroid StudioやAndroid Gradle Pluginでは、
同様の重複問題が
Duplicate class ... found in modules ...
と表示されることがあります。
どちらも基本的には、
同じクラスが複数の依存関係から読み込まれていないか確認することが重要です。
代表的なエラー表示
Program type already present: com.example.SomeClass
実際のエラーでは、
Program type already present:
の後に重複しているクラスの完全修飾クラス名が表示されます。
たとえば、
次のような形式です。
Program type already present: android.support.v4.app.INotificationSideChannel
この場合は、
表示されたクラスがどのライブラリに含まれているのかを確認し、
同じクラスを持つ依存関係が複数追加されていないか調べます。
まずBuild Outputで重複しているクラス名を確認する
Program type already presentが発生した場合は、
最初にAndroid StudioのBuild Outputでエラー全文を確認します。
特に確認するのは、
Program type already present:
の後に表示されるクラス名です。
Program type already present: com.example.library.SampleClass
このクラス名から、
どのライブラリに属している可能性があるのか確認します。
エラーが多数表示される場合でも、
すべてが別々の原因とは限りません。
1つのライブラリが丸ごと重複していると、
そのライブラリ内の多数のクラスについて
Program type already present
が表示されることがあります。
原因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:JARやAARとGradle依存関係が重複している
libsフォルダへJARやAARを手動で追加している場合、
Gradleからも同じライブラリを取得していると、
同じクラスが二重に含まれることがあります。
たとえば、
次のようなファイルが存在しているとします。
app/libs/sample-library.jar
さらにGradleでも同じライブラリを追加している場合です。
implementation("com.example:sample-library:1.0.0")
この状態では、
同じクラスがJARとGradle依存関係の両方から読み込まれる可能性があります。
JARやAARを直接使用するのか、
Gradle経由で取得するのかを確認し、
不要な方を削除します。
libsフォルダを確認する
原因が分からない場合は、
アプリモジュール内の
libsフォルダを確認します。
app/libs/
古いJARやAARが残っている場合、
現在Gradleから取得しているライブラリと重複している可能性があります。
以前はJARを直接追加していたものの、
後からMaven RepositoryなどからGradleで取得する方法へ変更した場合は、
古いファイルが残っていないか確認します。
原因3:古いSupport LibraryとAndroidXが混在している
古いAndroidプロジェクトでは、
Android Support LibraryとAndroidXが混在することで
Program type already present
が発生することがあります。
たとえば、
アプリ本体ではAndroidXを使用している一方で、
古いライブラリが
com.android.support
系のSupport Libraryへ依存している場合です。
build.gradleなどに、
古いSupport Libraryが残っていないか確認します。
implementation("com.android.support:appcompat-v7:28.0.0")
AndroidXへ移行済みのプロジェクトでは、
AndroidX側のライブラリを使用しているか確認します。
implementation("androidx.appcompat:appcompat:VERSION")
VERSIONには、
使用するAndroidX AppCompatのバージョンを指定します。
AndroidXの設定を確認する
AndroidXへ移行している古いプロジェクトでは、
gradle.propertiesも確認します。
android.useAndroidX=true
android.enableJetifier=true
android.useAndroidX=trueは、
AndroidXライブラリを使用する設定です。
android.enableJetifier=trueは、
古いSupport Libraryを参照する一部の依存関係を
AndroidX向けに変換するために使用されてきた設定です。
使用しているAndroid Gradle PluginやライブラリがすべてAndroidXへ対応している場合は、
Jetifierが不要なこともあります。
古いプロジェクトの設定をそのまま追加するのではなく、
使用しているライブラリの対応状況を確認します。
原因4:同じライブラリの異なるバージョンが含まれている
同じライブラリの異なるバージョンが、
複数の依存関係から読み込まれている場合にも問題が発生することがあります。
たとえば、
アプリ側であるライブラリを直接追加し、
別のライブラリも内部で同じライブラリを依存関係として追加している場合です。
implementation("com.example:library-a:2.0.0")
implementation("com.example:library-b:1.0.0")
library-bが内部で
library-aの別バージョンを使用している場合は、
依存関係を確認します。
Gradleの依存関係ツリーを確認する
どのライブラリから重複した依存関係が追加されているのか分からない場合は、
Gradleの依存関係ツリーを確認します。
Android StudioのTerminalから、
プロジェクトに応じて次のようなコマンドを実行します。
./gradlew app:dependencies
Windowsでは、
環境によって次のように実行します。
gradlew app:dependencies
実行すると、
アプリモジュールへ追加されている依存関係がツリー形式で表示されます。
エラーに表示されたクラスに関連するライブラリを探し、
複数の経路から同じ依存関係が追加されていないか確認します。
dependencyInsightで依存元を確認する
特定のライブラリがどこから追加されているのか確認したい場合は、
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が追加されており、
アプリ側から直接指定する必要がない場合は、
不要な直接依存関係を削除できる場合があります。
解決方法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")
ライブラリの公式ドキュメントなどを確認し、
対応している組み合わせを使用します。
原因5:Google Play servicesやFirebaseの依存関係が重複している
Google Play servicesやFirebaseなど、
多数の関連ライブラリを利用するサービスでは、
古いライブラリと新しいライブラリが混在することで
依存関係の問題が発生することがあります。
特に古いAndroidプロジェクトでは、
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のバージョンを指定します。
原因6:ローカルモジュールと公開ライブラリが重複している
同じライブラリをローカルモジュールとして追加しながら、
公開されている同じライブラリもGradleから追加している場合、
同じクラスが二重に含まれることがあります。
たとえば、
次のようにローカルモジュールを追加しているとします。
implementation(project(":samplelibrary"))
さらに、
同じライブラリを外部依存関係として追加している場合です。
implementation("com.example:samplelibrary:1.0.0")
同じクラスが両方に含まれている場合は、
どちらか一方だけを使用します。
原因7:古いライブラリが依存ライブラリを内部に含んでいる
一部の古いJARやAARでは、
必要な別のライブラリのクラスを内部へ直接含んでいる場合があります。
その状態で、
同じライブラリをGradleから別途追加すると、
同じクラスが2回含まれることがあります。
この場合は、
使用しているライブラリに新しいバージョンがないか確認します。
可能であれば、
依存関係が適切に分離された新しいバージョンへ更新します。
原因8:プロジェクト内に同じクラスが複数存在する
ライブラリだけでなく、
アプリのソースコード内に同じ完全修飾クラス名を持つクラスが複数存在する場合も確認します。
たとえば、
次のクラスが複数のソースセットなどに存在している場合です。
com.example.app.SampleClass
ファイルをコピーしたときに古いクラスが残っている場合や、
Java版とKotlin版の同じクラスを両方残している場合なども確認します。
debugとreleaseなどのソースセットも確認する
Androidプロジェクトでは、
main以外に
debug、
release、
Product Flavorなどのソースセットを使用できます。
同じクラスを複数のソースセットへ配置している場合、
ビルドバリアントの構成によって重複することがあります。
src/main/java/
src/debug/java/
src/release/java/
特定のビルドバリアントだけでエラーが発生する場合は、
ソースセットの構成も確認します。
依存関係を修正したらGradle Syncを実行する
build.gradleや
build.gradle.ktsを変更した場合は、
Gradle Syncを実行します。
Android StudioでGradleの同期を行い、
修正した依存関係をプロジェクトへ反映します。
その後、
再度アプリをビルドして
Program type already present
が解消されたか確認します。
CleanやRebuildを実行する
依存関係を修正してもエラーが残っている場合は、
古いビルド結果や中間ファイルが残っている可能性があります。
Android Studioの
Buildメニューから、
使用しているAndroid Studioのバージョンで利用可能な
CleanやRebuildに相当する処理を実行します。
その後、
再度ビルドしてエラーが解消したか確認します。
それでもProgram type already presentが直らない場合
エラーが解消しない場合は、
エラーに表示されている完全修飾クラス名を基準に、
重複元を一つずつ確認します。
- Build Outputで
Program type already presentのエラー全文を確認します。 - エラーに表示された完全修飾クラス名を確認します。
build.gradleやbuild.gradle.ktsの依存関係を確認します。./gradlew app:dependenciesで依存関係ツリーを確認します。- 必要に応じて
dependencyInsightで依存元を確認します。 libsフォルダに古いJARやAARが残っていないか確認します。- Support LibraryとAndroidXが混在していないか確認します。
- 同じライブラリの異なるバージョンが含まれていないか確認します。
- ローカルモジュールと外部ライブラリが重複していないか確認します。
- 必要に応じて不要な依存関係を削除するか
excludeを設定します。 - Gradle Sync後に再度ビルドします。
Program type already presentが大量に表示される場合
Build Outputに多数の
Program type already present
が表示されることがあります。
この場合でも、
すべてのクラスを個別に修正する必要があるとは限りません。
1つのJARやライブラリ全体が重複している場合、
そのライブラリ内に存在する多数のクラスについて
同じエラーが表示されます。
最初に表示されている複数のクラスが
同じライブラリに属していないか確認し、
ライブラリ単位で重複を調べます。
大量の
Program type already present
が表示されても、
大量のJavaやKotlinコードを修正する必要があるとは限りません。
1つの重複したライブラリやJARを削除するだけで、
多数のエラーがまとめて解消される場合があります。
Duplicate class found in modulesとの違い
Program type already presentと
Duplicate class ... found in modules ...は、
表示形式は異なりますが、
どちらも同じクラスが複数の場所から読み込まれている場合に発生することがあります。
古いAndroid StudioやAndroid Gradle Pluginを使用したプロジェクトでは
Program type already presentと表示され、
より新しいビルド環境では
Duplicate class found in modules
と表示されることがあります。
そのため、
どちらのエラーでも基本的な確認方法は同じで、
重複しているクラスの依存元を特定することが重要です。
まとめ
Android Studioの
Program type already presentは、
同じクラスが複数のライブラリやモジュールから読み込まれている場合に発生するエラーです。
まずBuild Outputに表示されたクラス名を確認し、
Gradleの依存関係、
libsフォルダのJARやAAR、
Support LibraryとAndroidXの混在、
ローカルモジュールなどを確認します。
依存元が分からない場合は、
./gradlew app:dependenciesや
dependencyInsightを利用すると、
どのライブラリを経由して依存関係が追加されているのか確認できます。
重複している依存関係を特定したら、
不要なライブラリの削除、
JARやAARの整理、
ライブラリのバージョン統一、
AndroidXへの整理、
必要に応じた
exclude
などで解消します。
Program type already presentを解決するときは、
エラーに表示されたクラスを直接削除するのではなく、
「なぜ同じクラスが複数の場所から読み込まれているのか」を確認することが重要です。
重複元となっている依存関係を特定し、
どちらを残すべきか確認したうえで修正します。
