[Android] compileSdk を上げるタイミングについて
導入
前の記事で Android 14 (API Level 34)は現状ベータリリースだが platform stability なので compileSdk を 34 に上げても大丈夫らしいと書いたのですが、理屈をよく分かっていなかったのですこし深堀りしました。
compileSdk
- アプリのコンパイル時に使用する android.jar のバージョンを指定するもの
- android.jar はそのバージョンでの Android SDK の API を定義する
- android.jar は実装の無いスタブファイルであり、アプリ(apk)にバンドルされない。アプリの実行時には Android OS 側に配置されている Andriod SDK の実装が参照される [1]
platform stability
- 2020年から導入された Android OS のリリースの状態
- ベータリリース状態の次期OSの SDK / NDK の API が確定したことを意味する
つまり
API が確定するということは次期バージョンの android.jar が確定する ということであり、かつ android.jar は API定義のみで実装を含まない為「platform stability に達した時点で compileSdk を最新にしても問題ない」ということになります。
ただし、API の差分には追加だけなく変更・削除も含まれるため、アプリのコードの修正が必要になる可能性はあります。
API の差分具体例
実際に compileSdk を更新する際は、とにかく一旦アップデートしてしまい、Android Studio で警告・エラーが出たら対応という流れで十分かと思われますが、具体的なAPIの差分がどのようなものかは以下ページで確認できます。
-
https://developer.android.com/sdk/api_diff/34/changes.html
- 例えば Level 34 では
android.adservices.AdServicesVersion
が削除されているのが分かります - 実際にこのクラスを参照してみると、 compileSdk 33 では import できるが 34 に変更すると Unresolved reference に変わることが確認できます。
- 例えば Level 34 では
疑問
-
古い API でコンパイルしたアプリが新しい API で削除されたクラスを参照している場合、新しいOSでアプリを起動するとエラーになる?
-
試しに API Level 33 で削除された
android.webkit.WebSettings.setAppCacheEnabled(boolean)
を呼び出すコードを compileSdk 32 でビルドし API 33 のエミュレータで実行してみると、エラーにはならなかった -
おそらく OS側の実装には setAppCacheEnabled が残っている?
-
Android のポリシーとして前方互換性が重視されているそうなので、古い API でコンパイルしたアプリが新しいOSでも動くような配慮?はされている模様
-
-
仮に API のメソッドの引数が変更された場合、新しい API でコンパイルしたら古いOS で動かなくなったりするのでは?
- そういう場合、メソッドのオーバーロードで別の(同名の)メソッドの追加という形になり、今までのメソッドはそのまま残るので、既存のコードが動かなくなるということはなさそうです。 [2]
-
追加された API を使ったら古いOS でエラーになるのでは?
- エラーになるので
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.XXX)
のようなコードで分岐させることになります。 [3]
- エラーになるので
おわりに
通常は CompileSdk と TargetSdk を同時に上げる感じでよいかと思いますが、CompileSdk は TargetSdk と比較して割とカジュアルに上げても問題なさそうなので、ライブラリに要求されたり、アップデートが大変なときに先んじて CompileSdk のみ上げるという選択はアリかと思いました。
参考
-
Google Developers Japan: Android 11 Beta 2 リリースと Platform Stability
-
ローカル単体テストを作成する | Android デベロッパー | Android Developers
単体テストの実行に使用される android.jar ファイルには実際のコードが含まれていないためです(Android SDK の API は、デバイス上の Android システム イメージからのみ提供されます)
(あまり公式でこの辺をはっきり解説している文書がないのですが、単体テストのページに上記の記述があります。
-
【保存版】Android SDK内部のソースコードを読む際に役立つ(かもしれない)ツールやウェブサイト6選 - heihei blog
おまけ
そもそも新しい AndroidOS で既存のアプリがちゃんと動くか?に関しては以下ページを確認するのがよさそうです。
-
若干抽象的な表現なのは、apk には Java バイトコード(*.class)が変換された dex ファイルが入っていて、Android Runtime (ART) はアプリのインストール時に dex を oat (ネイティブコード)に変換しているらしいのですが、具体的に Android SDK の実装がどこにどういう形式で存在し、アプリから参照されるのかよくわからなかったためです... ↩︎
-
場合によっては既存のAPIが Deprecated になるパターンもあると思われますが、Deprecated なしでいきなり Removed になるパターンはなさそうでした。 ↩︎
-
platform stability 状態で新しいAPIを使うのはリスクがゼロではないので、使っても大丈夫な API か検討・検証が必要かと思います ↩︎
Discussion