Android Studioでアプリをビルドした際に、
「android:exported needs to be explicitly specified」
というエラーが表示されることがあります。
このエラーは、
intent-filterを持つActivity、Service、BroadcastReceiverなどに、
android:exportedが明示的に設定されていない場合などに発生します。
特にAndroid 12以降を対象とするアプリでは、
外部アプリから起動できるコンポーネントかどうかを明確にするため、
対象となるコンポーネントに
android:exported="true"または
android:exported="false"
を指定する必要があります。
この記事では、Android Studioで
「android:exported needs to be explicitly specified」が表示された場合に確認したい主な原因と、
基本的な解決方法を紹介します。
「android:exported needs to be explicitly specified」とは
android:exportedは、
Activity、Service、BroadcastReceiverなどのコンポーネントを、
他のアプリから起動できるようにするかどうかを指定する属性です。
<activity
android:name=".MainActivity"
android:exported="true" />
android:exported="true"の場合は、
条件を満たす他のアプリなどから
そのコンポーネントを起動できる可能性があります。
android:exported="false"の場合は、
基本的に外部アプリから直接起動できない設定になります。
Android 12以降を対象とするアプリでは、
intent-filterを持つActivity、Service、BroadcastReceiverに対して、
android:exportedを明示的に指定する必要があります。
このエラーが表示された場合は、
Build OutputやAndroidManifest.xmlを確認し、
どのコンポーネントにandroid:exportedが不足しているかを特定することが重要です。
主な原因
intent-filterを持つActivityにandroid:exportedがない
よくある原因の一つが、
intent-filterを持つActivityに
android:exportedが指定されていないケースです。
<activity
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
このようなActivityでは、
android:exportedを明示的に設定する必要があります。
Launcher Activityにandroid:exportedが設定されていない
アプリの起動時に使用されるLauncher Activityには、
通常、
MAINとLAUNCHERのintent-filterが設定されています。
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Launcher Activityはシステムのランチャーから起動されるため、
一般的にはandroid:exported="true"を指定します。
Serviceにintent-filterが設定されている
Activityだけでなく、
Serviceにintent-filterが設定されている場合も、
android:exportedの指定が必要になることがあります。
<service
android:name=".ExampleService"
android:exported="false">
<intent-filter>
<action android:name="com.example.ACTION_SAMPLE" />
</intent-filter>
</service>
外部アプリから起動させる必要がないServiceであれば、
android:exported="false"を検討します。
BroadcastReceiverにintent-filterが設定されている
BroadcastReceiverでも、
intent-filterを持つ場合は
android:exportedの指定を確認する必要があります。
<receiver
android:name=".ExampleReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.example.ACTION_SAMPLE" />
</intent-filter>
</receiver>
Receiverを外部アプリから利用させる必要があるかどうかを確認し、
適切な値を指定してください。
targetSdkを引き上げたことでエラーが発生した
以前は正常にビルドできていたプロジェクトでも、
targetSdkを引き上げたことで
android:exportedの明示的な指定が必要になり、
エラーが発生する場合があります。
特に古いプロジェクトを更新した直後に
このエラーが発生した場合は、
AndroidManifest.xml内の
Activity、Service、Receiverを確認してください。
古いプロジェクトのManifest設定が残っている
古いAndroidプロジェクトでは、
android:exportedを明示的に記述していない
Manifestが使用されている場合があります。
Android StudioやtargetSdkを更新した後に
ビルドできなくなった場合は、
古いManifest設定が現在の要件に合っているか確認してください。
ライブラリ側のManifestに問題がある
自分のAndroidManifest.xmlに問題がなくても、
使用しているライブラリのManifestに
android:exportedが不足している場合があります。
Build Outputにライブラリ名や
キャッシュ内のManifestパスなどが表示されている場合は、
ライブラリ側が原因である可能性があります。
古いライブラリを使用している
古いライブラリでは、
Android 12以降の要件に対応した
android:exported設定が含まれていない場合があります。
ライブラリが原因と考えられる場合は、
より新しいバージョンが公開されていないか確認してください。
解決方法
Build Outputで対象のコンポーネントを確認する
「android:exported needs to be explicitly specified」が表示された場合は、
最初にBuild Outputを確認します。
android:exported needs to be explicitly specified for element <activity#com.example.MainActivity>
この場合は、
MainActivityの
android:exported設定を確認します。
エラーメッセージにActivity、Service、Receiverなどの名前が表示されている場合は、
そのコンポーネントをManifestから探してください。
Launcher Activityにandroid:exported=”true”を設定する
アプリのLauncher Activityに
MAINとLAUNCHERのintent-filterが設定されている場合は、
android:exported="true"を設定します。
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Launcher Activityの場合は、
外部のランチャーから起動される必要があるため、
通常はtrueを指定します。
外部から起動する必要がないコンポーネントはfalseにする
外部アプリから起動する必要がないActivity、Service、Receiverでは、
android:exported="false"を指定できます。
<activity
android:name=".SettingsActivity"
android:exported="false" />
必要以上にtrueを設定するのではなく、
そのコンポーネントを外部に公開する必要があるかを確認してください。
android:exported="true"とすれば
単純にすべて解決するわけではありません。
外部アプリから起動される必要がないコンポーネントは、
不要に公開しないことが重要です。
すべてのintent-filterを確認する
AndroidManifest.xml内を検索し、
<intent-filter>を持つコンポーネントを確認します。
Activityだけでなく、
ServiceやReceiverについても確認してください。
intent-filterがあるコンポーネントについて、
用途に応じたandroid:exportedが設定されているかを確認します。
ライブラリを更新する
エラーの原因が外部ライブラリのManifestにある場合は、
ライブラリの更新を確認します。
新しいバージョンでAndroid 12以降への対応が行われている場合は、
ライブラリを更新することで解決できることがあります。
不要な古いライブラリを削除する
問題となっているライブラリを現在使用していない場合は、
Gradleの依存関係から削除する方法があります。
最近追加したライブラリの後からエラーが発生した場合は、
一度その依存関係を外してビルドし、
エラーが解消するか確認する方法もあります。
Merged Manifestを確認する
自分のManifestに対象のコンポーネントが見つからない場合は、
Merged Manifestを確認します。
ライブラリや別のsource setから追加されたActivity、Service、Receiverなどを確認することで、
どこから問題の設定が追加されているかを特定しやすくなります。
ManifestのXML記述を確認する
android:exportedを追加した後もエラーが出る場合は、
属性を正しい要素に追加しているか確認してください。
<activity
android:name=".MainActivity"
android:exported="true">
属性名の入力ミス、
引用符の不足、
タグの位置なども確認します。
Gradle Syncを実行する
Manifestやライブラリの設定を修正した後は、
Android Studioから
Sync Project with Gradle Files
を実行します。
Gradle Syncで別のエラーが表示された場合は、
そちらを先に修正してください。
Clean ProjectとRebuild Projectを実行する
android:exportedを修正してもエラーが残る場合は、
古いビルド生成物が残っている可能性があります。
Android Studioのメニューから
Build → Clean Project
を実行し、その後
Build → Rebuild Project
を実行します。
キャッシュを再構築する
Manifestや依存関係に問題が見つからず、
Android Studio側に古い情報が残っていると考えられる場合は、
File → Invalidate Caches
を試します。
キャッシュを削除してAndroid Studioを再起動し、
プロジェクトを再度ビルドします。
「android:exported needs to be explicitly specified」は、
Manifest内の設定不足が原因である場合が多いため、
最初からキャッシュ削除を試すよりも、
Build Outputに表示されているコンポーネント名と
Merged Manifestを確認する方が原因を特定しやすくなります。
エラーが直らない場合に確認したいポイント
「android:exported needs to be explicitly specified」が解消しない場合は、
次の点を順番に確認すると原因を探しやすくなります。
- Build Outputに表示されているコンポーネント名を確認する
- AndroidManifest.xml内のintent-filterを確認する
- Launcher Activityにandroid:exported=”true”が設定されているか確認する
- 外部公開が不要なコンポーネントはandroid:exported=”false”を検討する
- ActivityだけでなくServiceやReceiverも確認する
- targetSdkを変更した直後ではないか確認する
- 古いManifest設定が残っていないか確認する
- Merged Manifestを確認する
- ライブラリ側のManifestが原因ではないか確認する
- 古いライブラリを使用していないか確認する
- 必要に応じてライブラリを更新する
- Gradle Syncを実行する
- Clean ProjectとRebuild Projectを実行する
- 必要に応じてInvalidate Cachesを実行する
まとめ
「android:exported needs to be explicitly specified」は、
intent-filterを持つActivity、Service、BroadcastReceiverなどに、
android:exportedが明示的に設定されていない場合などに発生するエラーです。
特に、
targetSdkを引き上げた古いプロジェクト、
Launcher Activity、
intent-filterを持つServiceやReceiver、
Android 12以降への対応が行われていない古いライブラリなどが原因になることがあります。
エラーが表示された場合は、
Build Outputに表示されているコンポーネントを確認し、
外部から起動する必要があるかに応じて
android:exported=”true”またはandroid:exported=”false”を設定すること
が重要です。
自分のManifestに問題が見つからない場合はMerged Manifestやライブラリも確認し、
必要な修正を行ったうえで、
Gradle Sync、Clean Project、Rebuild Projectなどを実行することで、
多くの場合は解決できます。
