はじめに
中古のAndroidスマートフォンを調べていたのですが、安価で買えるのがどれも2017年や2018年に販売された端末でAndroid 8.0などのOSがデフォルトでインストールされているものがほとんどだったりします。
そこで開発中のアプリがそれらの中古スマートフォンで正しく動作してくれるのかを調べていくとcompileSdkやtargetSdk、それにminSdkなどの設定が大事だとわかりました。
今まで、ふんわりとした意識で使っていたこれらの設定を改めて調べて、まとめて自分の忘備録として使用しようと思いこの記事を書きました。
あくまで忘備録として書かれているということを意識しながら読んでいただくと幸いです。
Android SDKとは
AndroidSDKはGoogleが開発したAndroidプラットフォーム用のソフトウェア開発キットです。
AndroidSDKには、Androidアプリの開発に必要な開発ツールやテストのために必要な全てーのツール及びライブラリがコンポーネントという形で含まれています。
Androidの新しいバージョンやアップデートがリリースされるたびに、それに対応したAndroid SDKの新しいバージョンも公開されています。
Android SDK Build-Tools
Android SDK Build-Toolsは、AndroidSDKに含まれているコンポーネントの一つです。
Android SDK Build-Toolsは、Androidアプリをビルドするために必要なAndroid SDKのコンポーネントです。
Android SDK Platform Tools
Android SDK Platform-Toolsは、AndroidSDKに含まれているコンポーネントの一つです。
Android SDK Platform-Toolsには、主にadbやfastbootなどのAndroidプラットフォームとのインターフェースとなるツールが含まれています。
SDK Platformとは
SDK PlatformとはAndroid StudioのSDK Managerからダウンロード可能な、SDKパッケージのことです。
これはAndroid 13やAndroid 12といった、各バージョンごとにダウンロード可能なパッケージです。
そして、このパッケージにはAndroid SDK Platform パッケージ、System Image パッケージ、Sources for Android パッケージが含まれています。
特に注意が必要なのが、compileSDKに指定されたAPI レベルと対応するSDK Platformがダウンロードされていない場合です。ビルド時にエラーが発生してビルドできなくなってしまうので、注意が必要です。
なぜかというと、SDK Platformに含まれているAndroid SDK Platformパッケージが各バージョン用にアプリをコンパイルする際に必要なパッケージだからです。
API レベルとは
API レベルとは、Android 13やAndroid 12といった各バージョンごとに提供されるAndrdoi SDKなどのフレームワーク APIと呼ばれるもののリビジョン(更新)を、それぞれ識別するために用いられる整数の値のことです。
例えば、Android1.0からAndroid2.0までに、API レベルの値は1から5に変化しています。これはAndroid1.0から2.0になるまでに1.1、1.5、1.6といったマイナーアップデートを挟んでいるためその度にリビジョンが更新されるのでAPI レベルもその分更新されたことを意味します。
compileSdkとは
compileSdkは、アプリをコンパイルする際にgradleによって使われるAndroid SDKのバージョンを表します。
compileSdkに指定したAPI レベル以下のAPIにて提供されている機能も利用可能なため、新しい機能はもちろんのこと、古い機能もそのまま使えることを意味しています。したがって、この値は常に最新のAPI レベルを指定して良いということです。
compileSdkとtargetSdkの組み合わせは何を意味しているのか
次の文章を見つけました。
Both compileSdkVersion and targetSdkVersion are crucial to handle forward compatibility in Android - so they both are connected with what to do when the new Android SDK version appears.
つまり、compileSdkとtargetSdkの値は前方互換性を処理する場合にとても重要な値ということであり、新しいバージョンのAndroid SDKが登場した時にどうすべきかということを意味しています。
minSdkとは
minSdkは、アプリが動作するのを保証する下限のAPI レベルを表します。
Google Play Storeにおいては、ユーザーのデバイスがminSdkに指定されているAPI レベルを保証していて、動作可能かを確認する目的で使用されます。
そして、minSdkを指定する際は、アプリが依存しているライブラリのminSdkの値に強く影響を受けます。依存しているライブラリがアプリのminSdkに指定されている値よりも大きい場合には、そのライブラリのminSdkの値に追随させる必要があります。
そして、複数のライブラリに依存していて、各ライブラリのminSdkの値がバラバラの場合は、一番高いminSdkの値と少なくとも同じ値かそれより上のminSdkを指定することが推奨されています。
もし、依存しているライブラリのminSdkよりも低いminSdkを指定しないといけない場合は、徹底的にエラーが出ないようにテストなどを行い動作を保証する必要があります。
新しいAPIでしか提供されていない機能をminSdkで指定したAPI レベルで使用するのを防ぐためには、実行時にシステムのAPI レベルを確認して動作の可否を決定するという手法が広く利用されています。
また、lintを使うことでminSdkを超えるAPIを使用している際に警告を出すことができるので、互換性に関する問題を回避することができるようになっています。
おいしい健康さんの記事に面白い記述がありました。
おいしい健康はリリース以降、minSDK 21だったので、Android L(5)の端末まで後方互換性がある状態でした。
つまり、minSDKの値が小さいとその分サポート対象の端末が増えるという意味になります。
新しいライブラリを導入する時にもminSDKの要件を意識する必要があります。現状は導入したいライブラリがminSDK >= 21であることが多かったので、ブロッカーになることはありませんでしたが、今後要件が上がっていく可能性はあります。
そして依存しているライブラリによっては、minSDKが開発しているアプリのminSDKの値より上の場合は要件を満たせなくなるため、API レベルを上げる必要が出てくることも意味しています。
targetSdkとは
targetSdkを使うことでAndroidでは前方互換性の維持を行なっています。
つまり、compileSdkのAPI レベルが上がったとしても、targetSdkを更新しなければ動作に対する新しい変更を適用しないため、前方互換性を維持することができるという仕組みをAndroidでは提供しているのです。
そして、targetSdkは開発中のアプリがメインターゲットにしているSdkのバージョンを表します。
つまり、このSdkのバージョンで動くことを目標に開発されているということを意味していて、かつアプリにとってこのtargetSdkで指定されたAPI レベルが最適なAndroid SDKのバージョンであり、正しく動きますよということをシステムに伝えるためのAPI レベルを表します。
もちろん端末のAndroidのAPI レベルが、それより上であろうが、それより下の値であろうが動く可能性はあるが、このtargetSdkで指定されているAPI レベルが一番最適ですよということを表します。
特に、Google Play Storeのような市場では、targetSdkのAPI レベルによって最新の状態を表すことで、このアプリがどのくらいモダンであり最新の機能をサポートしているのかを表現しています。
compileSdkとtargetSdkに指定する値の理想
targetSdkはcompileSdkよりも大きな値を指定することはできません。
そして、targetSdkとcompileSdkは同じAPI レベルを表していて、両方とも最新の値を指定することが望ましいとされています。
targetSdkよりも新しいAPI レベルのバージョンを表すAndroidがインストールされている端末でアプリを実行した場合
設定されたtargetSdkよりも新しいAPI レベルのバージョンのAndroidがインストールされた端末でアプリをユーザーが実行した場合、AndroidはtargetSdkで指定されたAPI レベルとの後方互換性を維持しアプリの動作を保証するために、UIにおける新しい見た目や動作などをtargetSdkで動作するものに置き換えたりする可能性があります。
Android SDKの新しいバージョンでのみ提供されている新しいAPIを使いたい場合
targetSdkはアプリがどのAndroidバージョン向けに設計とテストがされたかをAndroidシステムに伝えるためのプロパティとして使われています。
そして、アプリから最新のAPIにアクセスできるようにするためには、compileSdkの値をそのAPI レベルにアップデートする必要があります。
これにより、Android StudioでそのAPIに関する新しいプロパティやメソッドにアクセスすることが可能となります。
しかし、この時minSdkの値がcompileSdkの値よりも低い場合には、古いバージョンの端末では新しいSDKで公開されたAPIにアクセスできないので対処する必要があります。例えば、実行時にシステムのAPI レベルを確認して、動作の可否を検証するなどの手法です。
そして逆に、新しいAndroid SDKでは、従来提供されていたAPIがDeplicatedになっていたりコンパイル時に警告やエラーが発生する可能性があるので、こちらもまた対処する必要があります。
実際にcomileSdkで指定したAPI レベルで提供されている新しいAPIをアプリで使えるようにするためには、targetSdkを変更してcompileSdkと同じ値にする必要があります。
この変更によりAndroidのシステムはアプリが新しいAPIにアクセスできることを知ることができるのです。
各種sdkバージョンの意味のまとめ
| 種類 | 主な意味 |
|---|---|
| compileSdk | 基本的には常に最新のAPI レベル |
| targetSdk | アプリが一番快適に動くことが期待されている現在地のAPI レベル(理想的に言えば、compileSdkと同じ値が望ましい) |
| minSdk | アプリがサポートする一番古いAPI レベル |
まとめ
普段はなんとなく設定しているbuild.gradleのcompileSdk、targetSdkそしてminSdk。しかし改めて調べてみると、当然ですがそれぞれに役割や意味があり互換性を維持するために重要な役割を果たしていることがわかりました。
改めて調べてみることで、ふわっとなっていたそれぞれのバージョンに対するイメージが、より鮮明になった気がします。
参考にした記事

