API Level: What It Is, API Versions and targetSdk

Author: IT Sectr Published: 2026-02-08 Reading time: 12 min

API Level Android is an integer identifier that uniquely corresponds to a specific release of the Android platform. Each OS version has its own unique number: Android 14 = API 34, Android 15 = API 35. The developer manages three parameters in build.gradle — minSdkVersion, targetSdkVersion and compileSdkVersion — to control compatibility and access to new features. According to Android Developers, choosing the right API Level is critical for security and audience coverage.

Key Takeaways

  • API Level — an integer identifier of the Android API version, from API 1 (Android 1.0) to API 36 (Android 16)
  • minSdkVersion — the minimum Android version required to install the app, determines audience coverage
  • targetSdkVersion — the version against which the app was tested; includes behavioural changes of that version
  • compileSdkVersion — the SDK version used for compilation; must be >= targetSdk, provides access to new APIs
  • Google Play requires targetSdkVersion no older than 1 year from the current API Level

What is API Level Android?

API Level Android is an integer identifier assigned to each public release of the Android Framework API. The first release Android 1.0 had API Level 1, Android 1.5 — API Level 3, Android 2.2 — API Level 8, Android 4.0 — API Level 14, Android 8.0 — API Level 26, Android 12 — API Level 31, Android 14 — API Level 34, Android 15 — API Level 35, Android 16 (2025) — API Level 36. Each new API Level may add new classes, methods, constants, permissions and change the behavior of existing ones.

API Level does not strictly increment by 1 with each release. For example, Android 4.4W (Wear) has API 20, while Android 5.0 — API 21. Gaps are related to internal iterations and Wear OS devices. It is important for the developer to know not the version name (KitKat, Lollipop, Tiramisu), but its API Level — it is what is used in code for compatibility checks.

The key purpose of API Level is backward compatibility. An app compiled against API 34 can run on devices with API 34 and below (if it does not use new APIs without checking). Android Runtime (ART) checks API calls at the system level and applies behavioural changes depending on the app's targetSdkVersion.

How Android handles API Level

When installing an app, PackageManager checks that the device's API Level >= minSdkVersion from AndroidManifest.xml. If the condition is not met — installation is blocked with the message "App not installed". During execution, Android Runtime monitors API calls that require a higher API Level and generates NoSuchMethodError or UnsatisfiedLinkError if the method is absent in the current version.

ComponentRole in API Level handling
PackageManagerChecks minSdkVersion during installation
Android Runtime (ART)Performs API compatibility checks at runtime
Google Play StoreFilters apps by device API Level
SDK ManagerDownloads platforms for compilation under the required API Level
lintStatic analyzer that warns about using APIs above minSdk

minSdk, targetSdk, compileSdk: Differences and Role of Each Parameter

In the build.gradle file (Module: app), the developer specifies three API Level parameters: minSdkVersion, targetSdkVersion and compileSdkVersion. Confusing them is one of the most common mistakes among beginner Android developers. Each parameter is responsible for a different aspect of compatibility, and their values must be consistent.

minSdkVersion

minSdkVersion is the minimum API Level at which the app can be installed and run. Devices with API Level below minSdk do not see the app in Google Play and cannot install it. The value is chosen based on the target audience: minSdk 21 (Android 5.0) covers 97% of devices, minSdk 26 (Android 8.0) — about 85%, minSdk 31 (Android 12) — about 55% (data from Android Studio Distribution Dashboard, 2026). The lower the minSdk, the greater the coverage, but the more backward compatibility code is needed.

targetSdkVersion

targetSdkVersion is the API Level against which the app was tested. Android uses targetSdk to apply behavioural changes: if the app specifies targetSdk 33, the system enables all behavioral changes introduced in API 33. If targetSdk is 31, the system does not apply API 32-33 changes, preserving compatibility with old behavior. This is the most important parameter for security: Google Play requires targetSdk no older than 1 year from the current API Level.

compileSdkVersion

compileSdkVersion is the Android SDK version against which the code is compiled. It determines which APIs are available at compile time. compileSdk must be >= targetSdk and, ideally, equal to the latest stable API Level. Increasing compileSdk does not affect runtime behavior — only the availability of new APIs for the compiler. After raising compileSdk, you need to check the code for deprecated APIs and new permission requirements.

kotlin
// build.gradle.kts — API Level configuration example
plugins {
    id("com.android.application") version "8.7.0"
    id("org.jetbrains.kotlin.android") version "2.1.0"
}

android {
    namespace = "com.example.myapp"
    compileSdk = 36  // Android 16

    defaultConfig {
        applicationId = "com.example.myapp"
        minSdk = 26      // Android 8.0
        targetSdk = 36    // Android 16
        versionCode = 1
        versionName = "1.0.0"
    }

    buildTypes {
        release {
            isMinifyEnabled = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }

    kotlinOptions {
        jvmTarget = "17"
    }
}

dependencies {
    implementation("androidx.core:core-ktx:1.15.0")
    implementation("androidx.appcompat:appcompat:1.7.0")
    implementation("androidx.activity:activity-ktx:1.9.3")
}

In the build.gradle.kts example, compileSdk = 36 (latest at the time of writing), targetSdk = 36, minSdk = 26 (Android 8.0). compileSdk 36 provides access to all Android 16 APIs. targetSdk 36 enables all Android 16 behavioural changes. minSdk 26 covers ~85% of devices. AndroidX Activity KTX and AppCompat provide backward compatibility for fragments and themes.

AndroidManifest.xml

The minSdk and targetSdk parameters can also be specified in AndroidManifest.xml, but modern projects use build.gradle — values from Gradle override the manifest. In the manifest, it may be useful to specify for libraries and modules that do not use Gradle build config.

Behavioural Changes: How targetSdk Affects App Behavior

Behavioural changes are modifications to how the Android system works that are applied only to apps with targetSdk >= a certain API Level. Each new Android release introduces behavioural changes that can break existing apps if they are not updated. This is a key Android security mechanism: old apps continue to work as before, new ones follow current rules.

Major behavioural changes by version

Android 10 (API 29) — Scoped Storage: apps with targetSdk 29+ do not have direct access to the shared file system, only via MediaStore, SAF or their own storage. Android 11 (API 30) — Package Visibility: package filter, apps only see installed packages they interact with. Android 12 (API 31) — Foreground Service Notification: all foreground services must show a notification within 10 seconds of starting. Android 13 (API 33) — POST_NOTIFICATIONS: runtime permission for push notifications. Android 14 (API 34) — Foreground Service Types: mandatory declaration of the foreground service type in the manifest.

kotlin
// Handling Android 13 (API 33) behavioural changes: POST_NOTIFICATIONS
import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat

class NotificationHelper {

    fun requestNotificationPermission(activity: MainActivity) {
        // POST_NOTIFICATIONS permission only works with API 33+
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
            return  // Below API 33 no permission is required
        }

        when {
            ContextCompat.checkSelfPermission(
                activity,
                Manifest.permission.POST_NOTIFICATIONS
            ) == PackageManager.PERMISSION_GRANTED -> {
                // Permission already granted, can send notifications
                showNotification(activity)
            }

            activity.shouldShowRequestPermissionRationale(
                Manifest.permission.POST_NOTIFICATIONS
            ) -> {
                // Show explanation why permission is needed
                activity.showRationale()
            }

            else -> {
                // Request permission
                activity.requestPermissionLauncher.launch(
                    Manifest.permission.POST_NOTIFICATIONS
                )
            }
        }
    }

    private fun showNotification(context: Context) {
        // Create and display notification
        val notification = android.app.Notification.Builder(context, "default_channel")
            .setSmallIcon(android.R.drawable.ic_dialog_info)
            .setContentTitle("Notification")
            .setContentText("New message")
            .build()
        val manager = context.getSystemService(Context.NOTIFICATION_SERVICE)
            as android.app.NotificationManager
        manager.notify(1, notification)
    }
}

// Register requestPermissionLauncher in Activity
class MainActivity : ComponentActivity() {
    val requestPermissionLauncher = registerForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) { isGranted: Boolean ->
        if (isGranted) {
            // Permission granted
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

Example of handling POST_NOTIFICATIONS in Kotlin: check Build.VERSION.SDK_INT >= TIRAMISU, request runtime permission via ActivityResultContracts.RequestPermission, handle the result in a callback. Without this permission, an app with targetSdk 33+ cannot show push notifications. Below API 33 the permission is not required — the check code prevents calling unavailable APIs.

Scoped Storage (Android 10+)

Scoped Storage is one of the most significant behavioural changes. Starting from API 29 (targetSdk 29+), the app cannot get direct File access to Pictures, Downloads, Music and Documents directories. Instead, MediaStore is used for media, SAF (Storage Access Framework) for arbitrary files, and getExternalFilesDir() for its own storage. The exception is apps with the MANAGE_EXTERNAL_STORAGE permission, which requires Google Play approval.

Google Play Requirements for API Level and targetSdk

Google Play sets mandatory targetSdkVersion requirements for publishing apps. Since August 2024, Google Play requires targetSdkVersion >= API 33 (Android 13). Each year the threshold rises: new apps and updates must specify targetSdk no older than 1 year from the current major API Level. Violating the requirement leads to publication blocking and removal of the app from the store.

Why Google Play tightens requirements

The main reason is security. Each new Android API Level introduces behavioural changes that close attack vectors: Scoped Storage (API 29) prevents file theft, POST_NOTIFICATIONS (API 33) protects against spam notifications, Foreground Service Types (API 34) restricts hidden background services. Apps with a low targetSdk do not receive these protections and become a threat to users. Google Play cannot allow outdated apps on modern devices.

Checking compliance with requirements

Google Play Console checks targetSdkVersion when uploading APK/AAB. If targetSdk is below the requirement — the console blocks publication with the message: "Your app currently targets API level X and must target at least API level Y". The developer must update build.gradle, recompile the app, test behavioural changes and re-upload. AAB format is recommended for all new publications (mandatory since August 2021).

DateMinimum targetSdkAndroid Version
August 202231Android 12
August 202333Android 13
August 202433Android 13
August 202534Android 14
August 2026 (planned)35Android 15

Checking API Level in Code: Build.VERSION.SDK_INT

Build.VERSION.SDK_INT is a static integer constant containing the API Level of the device on which the app is running. It is the primary tool for runtime Android version checks. Build.VERSION_CODES contains named constants for each API Level: VERSION_CODES.TIRAMISU (33), VERSION_CODES.UPSIDE_DOWN_CAKE (34), VERSION_CODES.VANILLA_ICE_CREAM (35). Comparison using if (SDK_INT >= VERSION_CODES.TIRAMISU) is the standard pattern.

kotlin
// Examples of checking API Level in Android code
import android.os.Build
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.graphics.drawable.AdaptiveIconDrawable

class ApiLevelHelper {

    // 1. Basic API Level check
    fun isAtLeastTiramisu(): Boolean {
        return VERSION.SDK_INT >= VERSION_CODES.TIRAMISU  // 33
    }

    // 2. Adaptive API call with check
    fun getAdaptiveIcon(drawable: android.graphics.drawable.Drawable):
            android.graphics.drawable.Drawable? {
        // AdaptiveIconDrawable is only available with API 26 (Android 8)
        if (VERSION.SDK_INT >= VERSION_CODES.O) {
            return AdaptiveIconDrawable(drawable, null)
        }
        return drawable  // fallback for old devices
    }

    // 3. Checking POST_NOTIFICATIONS permission (API 33+ only)
    fun canRequestNotificationPermission(): Boolean {
        return VERSION.SDK_INT >= VERSION_CODES.TIRAMISU
    }

    // 4. Selecting image provider by API Level
    fun getImagePickerProvider(): String {
        return when {
            VERSION.SDK_INT >= VERSION_CODES.UPSIDE_DOWN_CAKE -> {
                // API 34+ uses PhotoPicker
                "photo_picker"
            }
            VERSION.SDK_INT >= VERSION_CODES.KITKAT -> {
                // API 19+ uses Intent ACTION_OPEN_DOCUMENT
                "open_document"
            }
            else -> {
                // Legacy: ACTION_GET_CONTENT (all versions)
                "get_content"
            }
        }
    }

    // 5. Java-style check via @TargetApi (for backward compatibility)
    @Suppress("DEPRECATION")
    fun checkLegacyStorage(): Boolean {
        // Scoped Storage behavior depends on targetSdk, not SDK_INT
        return VERSION.SDK_INT < VERSION_CODES.Q  // Android 10
    }

    // 6. Build info for analytics
    fun getDeviceApiInfo(): Map<String, Any> {
        return mapOf(
            "sdk_int" to VERSION.SDK_INT,
            "release" to VERSION.RELEASE,
            "codename" to VERSION.CODENAME,
            "incremental" to VERSION.INCREMENTAL,
            "preview_sdk" to VERSION.PREVIEW_SDK_INT
        )
    }
}

// Testing
fun main() {
    val helper = ApiLevelHelper()
    println("API Level: ${VERSION.SDK_INT}")
    println("Is Tiramisu+: ${helper.isAtLeastTiramisu()}")
}

The ApiLevelHelper class demonstrates all the main API Level checking patterns: isAtLeastTiramisu with SDK_INT >= VERSION_CODES, getAdaptiveIcon with fallback for old versions, getImagePickerProvider with when multi-branching, getDeviceApiInfo for analytics. The key rule is not to call new APIs without checking SDK_INT, otherwise the app will crash with NoSuchMethodError on old devices.

ANT (Android New API) and lint

Android Studio includes the lint static analyzer, which warns about using APIs above minSdkVersion. If a method is called without checking SDK_INT, lint highlights it as an error: "Call requires API level 34 (current min is 26)". Solutions: add @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) to the method or an if-check of SDK_INT. @TargetApi is a deprecated annotation, @RequiresApi is recommended.

Table of API Level and Android Version Correspondence

API Level Table is a reference tool for the developer. Knowing the device API Level, you can determine the Android version and available features. The table lists all major Android releases from API Level 1 (2008) to API Level 36 (2025). Code names (Cupcake, Donut, Tiramisu, VanillaIceCream) are used inside Google and in VERSION_CODES.

API LevelAndroid VersionCode NameYear
11.02008
31.5Cupcake2009
82.2Froyo2010
144.0Ice Cream Sandwich2011
194.4KitKat2013
215.0Lollipop2014
236.0Marshmallow2015
268.0Oreo2017
289Pie2018
2910Quince Tart (10)2019
3011Red Velvet Cake2020
3112Snow Cone2021
3313Tiramisu2022
3414Upside Down Cake2023
3515Vanilla Ice Cream2024
3616Baklava2025

Table: Threshold API Levels for Behavioural Changes

The following table shows key API Levels that introduce behavioural changes which break backward compatibility when raising targetSdk:

API LevelBehavioural ChangeImpact on App
29Scoped StorageNo direct File access to Pictures/Downloads/Music
30Package VisibilityqueryIntentActivities() only sees interacting packages
31Foreground Service NotificationMandatory notification within 10 seconds
33POST_NOTIFICATIONSRuntime permission for notifications
34Foreground Service TypesForeground service type declaration in manifest
35Privacy SandboxAdvertising identifier restrictions

Frequently Asked Questions

What is API Level in Android?

API Level Android is an integer identifier of the Android API version. Each release has a unique number: Android 13 = API 33, Android 14 = API 34, Android 15 = API 35, Android 16 = API 36. The developer specifies minSdkVersion, targetSdkVersion and compileSdkVersion in build.gradle to manage compatibility. API Level determines available classes, methods and behavioral changes.

How is minSdk different from targetSdk and compileSdk?

minSdkVersion — the minimum Android version for installing the app. targetSdkVersion — the version against which the app was tested, includes behavioural changes. compileSdkVersion — the SDK version for compiling code. minSdk is the lowest, targetSdk should preferably be the latest, compileSdk must be at least targetSdk. All three are specified in build.gradle.

What happens if I set targetSdk lower than the device Android version?

If targetSdkVersion is lower than the device API Level, Android disables behavioural changes introduced after targetSdk. For example, with targetSdk = 28 on Android 14 (API 34), Scoped Storage, POST_NOTIFICATIONS, Foreground Service Types are not applied. Google Play requires targetSdkVersion no older than 1 year from the current API Level for user safety.

How do I check the device API Level?

The device API Level is available via the constant Build.VERSION.SDK_INT (e.g., 34 for Android 14). For comparison, use named constants from Build.VERSION_CODES: if (SDK_INT >= VERSION_CODES.TIRAMISU). Build.VERSION.RELEASE returns the version string ("14"). The SDK_INT value is cached when the class is loaded and is accessible from any thread.

Why does Google Play require a new targetSdk every year?

Google Play raises targetSdkVersion requirements annually to implement security behavioural changes. Each new API Level introduces Scoped Storage, POST_NOTIFICATIONS, Privacy Sandbox and other protections. Apps with a low targetSdk bypass these protections and create risks for users. The requirement ensures all apps in the store have been tested against current rules.

Summary

  • API Level — an integer identifier of the Android API version (1-36), used to manage app compatibility
  • minSdkVersion sets the minimum API Level for installation, targetSdkVersion — the version with behavioural changes, compileSdkVersion — the version for compilation
  • Behavioural changes (Scoped Storage, POST_NOTIFICATIONS, Foreground Service Types) apply only if targetSdk >= corresponding API Level
  • Google Play requires targetSdk no older than 1 year, otherwise blocks app publication
  • Build.VERSION.SDK_INT — runtime check of the device API Level for safely calling new APIs with fallback
  • lint in Android Studio warns about using APIs above minSdk and recommends @RequiresApi for methods
  • Behavioural changes API 34+ include mandatory foreground service types, API 35+ — Privacy Sandbox with advertising identifier restrictions

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also