minSdk vs targetSdk vs compileSdk
Tags: android, gradle, beginners
Published: 2023-03-10 23:00:00

**What is the difference between minSdk, targetSdk and compileSdk in your build Gradle script?**

Let's have a look at what `minSdk`, `targetSdk` and `compileSdk` really means in **build.gradle** script.

```kotlin
android {
    compileSdk 32
    defaultConfig {
        /*...*/
        minSdk 21        
        targetSdk 32        
        /*...*/ 
    }
}
```

* **minSdk** - What is the minimum API Level required for the app to run?
    
* **targetSdk** - Which API level the app was designed and tested on?
    
* **compileSdk** - Which API level is used by Gradle to compile your app?
    

## minSdk

If your `minSdk` is set to `21`, your app cannot be run on any Android version that is below API level 21. If the Android version (API level 20) attempts to install your app, you get this error.

> Installation did not succeed. The application could not be installed: INSTALL\_FAILED\_OLDER\_SDK

The Google Play Store prevents the user from installing the app too if the phone's Android version doesn't meet the `minSdk` requirement by the app.

## targetSdk

### App runs on API level &gt; targetSdk

If the app is run on the Android version (API level) that is higher than the `targetSdk`, the Android operating system will try to **run backward compatibility behavior to match behavior as in** `targetSdk` API level.

For example, runtime app permission is introduced in API level 23. Before API level 23, runtime app permission is not needed.

If your `targetSdk` is set to `22` and your app runs on Android version (API level 23), the Android OS will try to match the behavior as in API level 22. Thus, no runtime permission is requested.

If your `targetSdk` is set to `23` and your app runs on Android version (API level 23 or higher), runtime permission is requested.

### App runs on API level &lt; targetSdk

What about the app that runs on the Android version (API level) that is &lt; `targetSdk`? The app behaves based on that Android version (API level).

If your `targetSdk` is set to `23` and your app runs on Android version (API level 22), runtime permission is not requested.

*You can try to play around with this demo app which requests runtime permission:*

- [Simple Google Map App - Jetpack Compose](https://vtsen.hashnode.dev/simple-google-map-app-jetpack-compose)

## compileSdk

If your app uses an API that is introduced in API level 26, your `compileSdk` must be set to minimum `26`. If you set it to `25`, it fails to compile.

Assuming the `minSdk` is `21`, you likely get this warning/error too

> Call requires API level 26 (current min is 21): `android.app.NotificationChannel()`

As recommended by the Android Studio IDE, you can fix the warning/error by annotating your function with

```kotlin
@RequiresApi(Build.VERSION_CODES.O)
private fun yourFunction() {
    /*...*/ 
}
```

However, if you run your App on the Android version (&lt; API level 26), it will NOT crash but fails silently. You will notice the error messages in the logcat. So, I think **adding the** `@RequiresApi()` **is a bad practice** here.

What you should do is handle the code above the app runs below the API level 26.

```kotlin
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    /* Code for API level >= 26 */
} else {
   /* code for API level >= 23 and < 26) */
}
```

An example is the notification channel is only required / available for API level 26. Then, we should wrap it with `Build.VERSION_CODES.O`.

```kotlin
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

    val notificationChannel = NotificationChannel(
        notificationChannelId,
        "DemoWorker",
        NotificationManager.IMPORTANCE_DEFAULT,
    )

    val notificationManager: NotificationManager? =
        getSystemService(applicationContext, NotificationManager::class.java)

    notificationManager?.createNotificationChannel(notificationChannel)
}
```

This code is taken from the work manager demo app below:

- [Simple Example to Use WorkManager and Notification](https://vtsen.hashnode.dev/simple-example-to-use-workmanager-and-notification) 


> **\[Updated - Sept 16, 2022\]:** I find that using `Build.VERSION_CODES.O` is not readable at all. It doesn't bring any meaning because everywhere else (e.g. warning messages from Android Studio, `build.gradle`) is using the number(i.e. 26). I have no idea the `O` represents the `26` and I can't memorize it. Instead, I prefer to use the hard-coded value `26`!

```kotlin
if (Build.VERSION.SDK_INT >= 26) {
    /* Code for API level >= 26 */
} else {
   /* code for API level >= 23 and < 26) */
}
```

> **\[Updated - Jan 20, 2023\]:** I still find hardcoding value 26 is not very readable. So I created this **BuildUtils** Android library recently to make this more readable.

```kotlin
if (BuildExt.VERSION.isNotificationChannelSupported()) {
    // Create notification channel here
}
```

- [BuildUtils Android Library](https://github.com/vinchamp77/buildutils)

## Conclusion

In general,

> `minSdk` &lt; `targetSdk` &lt;= `compileSdk`

but ideally and practically,

> `minSdk` &lt; `targetSdk` == `compileSdk` == latest SDK version

Don't use `@RequiresApi()` and handle the different API versions' behavior in the code.

---

*Originally published at [https://vtsen.hashnode.dev](https://vtsen.hashnode.dev/minsdk-vs-targetsdk-vs-compilesdk)*.