19
13

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 1 year has passed since last update.

新しくbuild.gradleで宣言するcompileSdkExtensionとは?SDK Extensionsとは?

Last updated at Posted at 2023-01-10

基本的には以下のドキュメントどおりなんですが、ちょっとややこしい部分があってコード読んだりしたので紹介しておきます。

OSのバージョンによらずに、Androidのシステムをアップデートできるようにしていこうという取り組みのようで、そのアップデートした部分をアプリから使えるようにしたいということのようです。

例えば、ACTION_PICK_IMAGESはAndroid 13 (API level 33で追加されたものだが、Android 11以上でR Extensions Version 2のSDK extensionsが入っている端末でも使えます。

基本

例えばACTION_PICK_IMAGESを使いたければ、ACTION_PICK_IMAGESはR Extensions 2であるとドキュメントからわかります。

image.png

Version 2以上のバージョンのExtensionをAndroid StudioのSDK Managerから入れる。

image.png

そのSDKに入っているACTION_PICK_IMAGESなどをimportするためにcompileSdkExtensionを宣言して、ビルド時に参照できるようにする。compileSdkを新しくすると新しいAndroidのAPIがコードから使えるようになるのと一緒。

android {
    compileSdk = 33
    compileSdkExtension = 4
    ...
}

以下のように判定して2以上であることを判定して、使えるとわかるので、利用する。この場合ちゃんと古いOSでも使える場合もtrueになる。

SdkExtensions.getExtensionVersion(Build.VERSION_CODES.R) >= 2

何がややこしいのか

このSdkExtensions.getExtensionVersion(Build.VERSION_CODES.R)の引数のBuild.VERSION_CODES.Rって何。。?SdkExtensions.getExtensionVersion() >= 2ならわかるけど。。? しかもbuild.gradleでもcompileSdkExtension = 4って宣言してたからMapみたいな感じではなくない??

SdkExtensions.getExtensionVersion(Build.VERSION_CODES.R) >= 2

(ちなみにRはAPI Level 30 Android 11に相当する)

こういうときはコードを見ましょう。
以下のブランチを見るとそのコードを見ることができます。
https://android.googlesource.com/platform/packages/modules/SdkExtensions/+/refs/heads/android13-mainline-art-release

以下に実際のSdkExtensionsのコードがあります
https://android.googlesource.com/platform/packages/modules/SdkExtensions/+/refs/heads/android13-mainline-art-release/java/android/os/ext/SdkExtensions.java

以下のように単にHashMapになっています。

        R_EXTENSION_INT = SystemProperties.getInt("build.version.extensions.r", 0);
        S_EXTENSION_INT = SystemProperties.getInt("build.version.extensions.s", 0);
        T_EXTENSION_INT = SystemProperties.getInt("build.version.extensions.t", 0);
        AD_SERVICES_EXTENSION_INT =
                SystemProperties.getInt("build.version.extensions.ad_services", 0);
        Map<Integer, Integer> extensions = new HashMap<Integer, Integer>();
        extensions.put(VERSION_CODES.R, R_EXTENSION_INT);
        if (SdkLevel.isAtLeastS()) {
            extensions.put(VERSION_CODES.S, S_EXTENSION_INT);
        }
        if (SdkLevel.isAtLeastT()) {
            extensions.put(VERSION_CODES.TIRAMISU, T_EXTENSION_INT);
        }
        extensions.put(AD_SERVICES, AD_SERVICES_EXTENSION_INT);
        ALL_EXTENSION_INTS = Collections.unmodifiableMap(extensions);

以下のようにすると端末の実際の状況が取得できます。Pixel5aで取得したところ以下のようになりました。つまり、それぞれのvalueに4が入っているという状況のようです。 

adb shell getprop | grep build.version.extensions
[build.version.extensions.ad_services]: [4]
[build.version.extensions.r]: [4]
[build.version.extensions.s]: [4]
[build.version.extensions.t]: [4]

このSdkExtensions.getExtensionVersion()の引数になり得るものは以下のように定義されています。

image.png

AdServicesのAPIでは以下のようになっていて、Ad Servicesが指定されていたりします。
https://developer.android.com/design-for-safety/privacy-sandbox/reference/adservices/AdServicesState
image.png

結局の所build.gradleのcompileSdkExtension = 4とbuild.version.extensionsの数字の関係性は今の所分かっていません。おそらく今は全部1つのバージョンで管理していて、将来的にbuild.version.extensions.ad_servicesbuild.version.extensions.r毎に別々の数字が使われたり、別々のアップデートされるようになった場合に、またGradle側のAPI変更の対応などが入るという想定なのかもしれません。 (不明。わかる方いれば教えて下さい)

アプリ側のとり得る戦略

基本的にはおそらくcompileSdkExtensionは上げてしまって(おそらくライブラリのアップデート時に設定しないとアップデートできなくなる)、あとは基本的に直接SdkExtensions.getExtensionVersion()などを使わず、JetpackなどにActivityResultContracts.PickVisualMedia.isPhotoPickerAvailable()などがあり判定できるので、それで適切に対応していくのでいいのではないかなと思います。

19
13
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
19
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?