43
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Android12対応でexported属性を設定したのに怒られた時の対処法

Last updated at Posted at 2021-07-27

Android12から、セキュリティ面の改善を目的として、インテントフィルタを使用するアクティビティやサービスなどのコンポーネントでandroid:exported属性を明示的に宣言する必要があります。

しかし私の手元では、インテントフィルタを使用する全てのコンポーネントでandroid:exported属性を宣言したにも関わらず**「exported属性を指定してくれ」とエラーになってコンパイルできない事象**がありました。

そこでこの記事ではどのようにしてその事象を解決したかを紹介します。

結論

自分で用意したManifestではexported属性をちゃんと宣言してても、依存ライブラリでのManifestで条件を満たしていない場合、最終的にmergeされたManifest内で条件を満たさないことになるため、コンパイルエラーになります。

条件を満たしていないAndroidManifestを持つライブラリやモジュールを探し、(外部ライブラリの場合は)exported属性を宣言されてるバージョンにアップデートすることで解決できるかと思います。

前提条件

  • Android12 SDKのセットアップが完了している
  • 自分で定義したAndroidManifestファイル内で、インテントフィルタを使用する全てのコンポーネントでandroid:exported属性を宣言している

エラー内容

まず、コンパイルできなかった時のエラー内容は以下です。

Manifest merger failed with multiple errors, see log
Error: Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported` when the corresponding component has an intent filter defined

「Android12以上をターゲットにするときは、インテントフィルターが定義されてるコンポーネントにはandroid:exportedを明示してな」と怒られています。

なぜエラーになるか

でも、どんなに辛抱強くAndroidManifest内を見ても、インテントフィルターを定義してるコンポーネントでは、やっぱり全部exportedを宣言してるな。。。なぜだ。。。

とここで、先ほどのエラーログをもう一度見ると、Manifest merger failed with multiple errorsとあります。

そういえばそうだ、AndroidManifestは一つではなく、ライブラリの中にも含まれているんだった。

ドキュメントにはこうあります。

APK ファイルに含めることのできる AndroidManifest.xml ファイルは 1 つだけに限られますが、Android Studio プロジェクト内には、メイン ソースセットや、ビルド バリアント、インポート ライブラリによって提供される複数のマニフェスト ファイルを含めることができます。そのため、アプリをビルドする際、Gradle ビルドは、すべてのマニフェスト ファイルを単一のマニフェスト ファイルにマージし、APK 内にパッケージ化します。

なので、最終的にマージされたAndroidManifestを見てみます。

Merged Manifestを見る

メインモジュール(appなど)のAndroidManifest.xmlを開くと、実は下にMerged Manifestというタブがあり、そこからプロジェクト内の、依存ライブラリも含んだ全てのAndroidManifest.xmlをマージしたManifestを見ることができます。

スクリーンショット 2021-07-28 1.07.09.png

この統合されたManifestファイルを改めて眺めていくと。。。

スクリーンショット 2021-07-27 18.30.37.png

おっ、この3つのactivityコンポーネントで、インテントフィルターが定義されてるのにexportedの宣言がないことが分かります。

原因はここにあった!!

で、こいつらのnameを見てみると、androidx.test:coreのライブラリであることが分かります。

依存ライブラリをアップデートする

Android Code Searchを使ってandroidx.test:coreのライブラリのアーティファクトを遡っていくと、androidx.test:core:1.3.1-alpha01から、Manifestの各コンポーネントでexported属性が宣言されてるのが分かります。

もし私のプロジェクトでandroidx.test:coreの依存関係をbuild.gradleに宣言していたら話は早かったのですが、残念なことに私のプロジェクトではこのライブラリは直接宣言しておらず、なんのライブラリが間接的にこのtest:coreに依存しているのかを探さなければなりません。

そこで、テスト関連の他のライブラリが何に依存しているのかをmavenやAndroidX Techを使って一個一個確認していったところ、

ということが分かり、これらを、不要なものは削除しつつ、androidx.test:core:1.4.0(1.3.1-alpha01以降)に依存しているバージョンまで上げることで解消することができました。

なお、私のプロジェクトでは、これ以外にも、

  • com.squareup.leakcanary:leakcanary-android:1.5.1もManifestFileでexported属性が宣言されておらず、バージョンアップをしました。

結論

自分で用意したManifestではexported属性をちゃんと宣言してても、依存ライブラリでのManifestで条件を満たしていない場合、最終的にmergeされたManifest内で条件を満たさないことになるため、コンパイルエラーになります。

条件を満たしていないAndroidManifestを持つライブラリやモジュールを探し、(外部ライブラリの場合は)exported属性を宣言されてるバージョンにアップデートすることで解決できるかと思います。

あと、今回の場合、ライブラリを定期的に更新していれば、こんな色々調べる羽目にはならなかったと思うので、ライブラリは定期的に更新しましょう!!

参考

43
19
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?