状況
Android Studio で実行ボタンを押すか、adb install を実行すると、デバイスが次のエラーを返します:
Installation did not succeed.
The application could not be installed: INSTALL_FAILED_CONFLICTING_PROVIDER
スタックトレースも、何が競合しているかのヒントもありません。インストールはただ失敗します。
原因はこうです:別のインストール済みアプリが、同じ ContentProvider のオーソリティ文字列をすでに使用しています。Android はプロバイダーのオーソリティをデバイス上のすべてのアプリにまたがるグローバルな一意の ID として扱います。2 つのアプリが同じオーソリティを共有することはできません。システムは重複を即座に拒否します。
根本原因の分析
AndroidManifest.xml を開いて、<provider> タグを確認します:
<!-- よくある原因:ハードコードされたオーソリティを持つ FileProvider -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
...
</provider>
このハードコードされたオーソリティ文字列が問題です。debug、release、すべてのフレーバーなど、すべてのビルドバリアントがまったく同じオーソリティを宣言してしまいます。release ビルドがすでにインストールされているデバイスに debug ビルドをインストールしようとすると、Android は即座にブロックします。
サードパーティライブラリも別のよくある原因です。ハードコードされたオーソリティを持つ ContentProvider を同梱するライブラリは、それをインクルードするすべてのアプリで競合を引き起こします。デバイス上に共存できるのは 1 つだけです。
競合しているオーソリティを見つける
現在インストールされているアプリが登録しているオーソリティを確認します:
adb shell dumpsys package | grep -A2 "com.example"
または、最後のビルドでマージされたマニフェストを確認します:
# ./gradlew assembleDebug 実行後
cat app/build/intermediates/merged_manifests/debug/AndroidManifest.xml | grep -A5 "provider"
応急処置 — 競合するアプリをアンインストールする
今すぐアプリを動かす必要がありますか?ブロックしているアプリをアンインストールします:
# 競合するオーソリティを持つアプリを削除する
adb uninstall com.your.package.name
# 新しい APK をインストールする
adb install app-debug.apk
Android Studio から、デバイスのアプリ設定に移動して手動でアンインストールし、再実行します。これで動作します。ただし、これは応急処置にすぎません。どちらのバージョンを再インストールしても、また同じ問題に戻ります。
恒久的な修正 — オーソリティを一意にする
方法 1:applicationId を使用する(推奨)
ハードコードされた文字列を ${applicationId} に置き換えます:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
すべてのアプリは一意のパッケージ名を持つため、競合は起こり得なくなります。debug ビルドは com.example.app.debug.fileprovider を取得します。release は com.example.app.fileprovider を取得します。重複は一切ありません。
Java/Kotlin のコードもこれに合わせて更新します:
// 修正前 — ハードコード、ビルドバリアント間で壊れる
Uri fileUri = FileProvider.getUriForFile(
context,
"com.example.fileprovider",
file
);
// 修正後 — 動的、常に正しい
Uri fileUri = FileProvider.getUriForFile(
context,
context.getPackageName() + ".fileprovider",
file
);
方法 2:ライブラリのハードコードされたオーソリティをオーバーライドする
ライブラリのソースを変更できませんか?マニフェストで tools:replace を使ってオーバーライドします:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application>
<provider
android:name="com.thirdparty.library.SomeProvider"
android:authorities="${applicationId}.someprovider"
android:exported="false"
tools:replace="android:authorities" />
</application>
</manifest>
tools:replace="android:authorities" 属性は、マニフェストマージャーにライブラリが提供する値を破棄して自分の値を使用するよう指示します。ハードコードされたオーソリティ文字列を持つ読み取り専用の依存ライブラリに対して有効です。
方法 3:複数のバリアントに applicationIdSuffix を使用する
QA、ステージング、本番のビルドを同じデバイスに並べてインストールしていますか?Gradle レベルで各ビルドに異なるパッケージ名を付与します:
// build.gradle (app)
android {
buildTypes {
debug {
applicationIdSuffix ".debug" // → com.example.app.debug
}
staging {
applicationIdSuffix ".staging" // → com.example.app.staging
}
release {
// サフィックスなし → com.example.app
}
}
}
これをマニフェストの ${applicationId} オーソリティと組み合わせます。各バリアントは完全に一意のオーソリティを自動的に取得でき、追加の作業は一切不要です。
修正を確認する
インストール前に、マージされたマニフェストを確認してオーソリティが正しく解決されていることを確かめます:
./gradlew processDebugManifest
grep -n "authorities" app/build/intermediates/merged_manifests/debug/AndroidManifest.xml
完全なパッケージ名が埋め込まれていることを確認します:
android:authorities="com.example.app.debug.fileprovider"
次にインストールして、成功メッセージを確認します:
adb install -r app/build/outputs/apk/debug/app-debug.apk
# Performing Streamed Install
# Success
デバイス上でも確認します:
adb shell dumpsys package com.example.app.debug | grep -A3 "Provider"
それでも解決しない場合
競合しているアプリが明確でない場合もあります。システムアプリやポートフォリオ内の別のプロジェクトが同じオーソリティを保持している可能性があります。デバイスに登録されているすべてのプロバイダーをダンプして、キーワードで検索します:
adb shell dumpsys package providers | grep "fileprovider"
その出力から、どのパッケージがオーソリティを保持しているかが正確にわかります。そのパッケージをアンインストールし、恒久的な修正を適用すれば、問題は解決します。

