LoginSignup
0
1

More than 1 year has passed since last update.

androidxで見るMetadataHolderとはなんぞや

Last updated at Posted at 2023-01-31

背景

ちょうど最近ライブラリが更新されたということで、アプリ別言語設定を触っていてAndroidManifestで設定した項目がこちら。

AndroidManifest.xml
<application>
  <!-- ... -->
  <service
    android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
    android:enabled="false"
    android:exported="false">
    <meta-data
      android:name="autoStoreLocales"
      android:value="true" />
  </service>
  <!-- ... -->
</application>

あるいはandroidx.credentialsでも見た項目はこちら。 (追記: 実際利用する際にこの記述は不要でした)

AndroidManifest.xml
<application>
  <!-- ... -->
  <service android:name="androidx.credentials.playservices.CredentialProviderMetadataHolder">
    <meta-data
      android:name="androidx.credentials.CREDENTIAL_PROVIDER_KEY"
      android:value="androidx.credentials.playservices.CredentialProviderPlayServicesImpl" />
  </service>
</application>

参考: https://qiita.com/verno3632/items/6d8812e3c1f205a0e2a1#androidmanifest

両者とも MetadataHolder なるものが使われているが、一体なんぞや?

その謎を解明するため、調査班はAndroid Code Searchの奥地へと向かったーーー

結論

ライブラリの挙動をアプリ側で変更したい場合にメタデータの指定先にするServiceです。
ライブラリの挙動をアプリ側で変更するにはコードから変える方法もありますが、アプリケーション単位で変更する場合どこで初期化するかという話になるため、メタデータとして指定するのがシンプルということかと思われます。

なぜApplicationにメタデータを指定しないのか

applicationに対してmeta-dataを指定することも出来ます。しかしライブラリ側で applicationにmeta-dataを指定する という使われ方を選択してしまった場合、そのライブラリを利用するアプリではapplicationにmeta-dataの情報が乗ってしまいます。
端末内の別アプリからアプリのactivityのリストを取得することが出来ますが、それぞれにライブラリのmeta-dataのコピーを含むことになります。
ライブラリ側の一つの が大量の例外とクラッシュを引き落とすことに繋がる可能性があるので、このような使い方を行っていません。

特に今回調査中に発見したように、様々なアプリで広く使われるandroidxでこのように指定すると影響も大きそうです。

参考: https://android.googlesource.com/platform/frameworks/support/+/androidx-main/docs/api_guidelines/resources.md#resources-manifest-metadata

MetadataHolderというService

MetadataHolder という名前がついていますが、そのようなクラスがあるわけではなく単なるServiceです。
このような使い方に対して MetadataHolder と名前をつけているようです。
meta-dataを保持するためだけのServiceなので、呼び出されませんし、 enabledexportedfalse で宣言するのが正しいです。

使用例

いくつかのandroidxのライブラリで使用されています。

androidx.camera.core

CameraXConfig.Provider を指定します。

androidx.credentials:credentials-play-services-auth

認証機能(パスワードマネージャー)を設定します。現在使えそうなのはこのライブラリで指定されている CredentialProviderPlayServicesImpl くらいのようです。

androidx.car.app

CAR_HARDWARE_MANAGER を指定します。

androidx.car.app:app-projected androidx.car.app:app-automotive それぞれのライブラリで別のハードウェアマネージャーが用意されています。

androidx.appcompat

アプリ別言語設定をAndroid13未満でどこで管理するか?を表す autoStoreLocales を保持します。
androidxのライブラリに任せる(実態はファイル)か、自前でやるかの選択になります。

終わりに

MetadataHolderService について調査しました。
自前でライブラリを作り、挙動をメタデータで変えたいときに利用方法として整備するのが良いのかも知れません。

0
1
0

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
0
1