targetSdkVersion: Key Concepts, Behavioural Changes, and Google Play

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

targetSdkVersion — the Android API Level against which the application has been tested and optimized. This parameter is specified in build.gradle and determines which behavioural changes will be applied to the application at runtime. If targetSdkVersion is lower than the device's API Level, Android disables behavioural changes introduced in newer versions, maintaining compatibility for older apps. According to Android Developers, Google Play requires targetSdkVersion no older than 1 year from the current API Level.

Key Takeaways

  • targetSdkVersion — the API Level the app is tested against; affects behavioural changes
  • Behavioural changes — system modifications (Scoped Storage, Permissions) applied based on targetSdk
  • Google Play requires targetSdk no older than 1 year from the current API Level, otherwise blocks publishing
  • Upgrading targetSdk requires testing all behavioural changes of the new Android version
  • Difference between targetSdk and compileSdk: targetSdk — runtime, compileSdk — compilation

What is targetSdkVersion in Android?

targetSdkVersion is an integer parameter in build.gradle that declares the API Level against which the app has been tested. The Android system uses this parameter to decide which behavioural changes to apply to the app at runtime. If targetSdkVersion = 33, Android applies all behavioural changes introduced up to API 33 inclusive, but does not apply changes from API 34+. If targetSdkVersion = 34 — changes up to API 34 are applied, and so on.

The key difference between targetSdkVersion and minSdkVersion is the mechanism of action. minSdk is checked once during installation and blocks installation if the condition is not met. targetSdkVersion affects the runtime behavior of the system on each device, regardless of which Android version the app is running on. The same app with targetSdk 31 will behave differently on Android 13, 14, and 15, because behavioural changes above 31 are disabled.

The targetSdkVersion mechanism is a backward compatibility tool built into Android. Without it, every OS update would break thousands of old apps. Google introduced this mechanism in Android 2.1 (API Level 7) and has since used it as the standard way to introduce new security, privacy, and resource management rules without breaking existing applications.

kotlin
// build.gradle.kts — targetSdkVersion in defaultConfig
android {
    namespace = "com.example.myapp"
    compileSdk = 36

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

// Checking current targetSdk in code
fun isUsingScopedStorage(): Boolean {
    // Context.getApplicationInfo().targetSdkVersion contains the app's targetSdk
    return context.applicationInfo.targetSdkVersion >= VERSION_CODES.Q
}

In the example, targetSdk = 36 enables all behavioural changes of Android 16. The code checks targetSdkVersion via context.applicationInfo.targetSdkVersion — this allows dynamically determining which compatibility mode is enabled. The helper function is useful for libraries that need to adapt to the targetSdk of the calling application.

Behavioural Changes: How targetSdk Affects the App

Behavioural changes are modifications to the Android system behavior that only apply to apps with targetSdkVersion >= a certain API Level. Each new major Android release introduces behavioural changes, and if an app does not update targetSdk, these changes do not take effect. This mechanism allows developers to update their app at their own pace, rather than synchronously with a new OS release.

Scoped Storage (API 29) is one of the most significant behavioural changes. Apps with targetSdk 29+ cannot directly get File access to shared directories Pictures, Downloads, Music, Documents. Instead, MediaStore is used for media, SAF (Storage Access Framework) for arbitrary files, and getExternalFilesDir() for private storage. Older apps with targetSdk 28 and below continue to work with legacy Full Storage Access, but this creates a security risk.

POST_NOTIFICATIONS (API 33) is a runtime permission for sending notifications. Apps with targetSdk 33+ must request Manifest.permission.POST_NOTIFICATIONS from the user through the standard dialog. If permission is not granted, NotificationManager.silent() does not show notifications to the user. On Android 13+ without this permission, push notifications and local notifications simply do not display, which can significantly reduce user engagement.

API LevelBehavioural ChangeRequired Actions When Updating
29Scoped StorageMigrate to MediaStore and SAF for files outside sandbox
30Package VisibilityAdd <queries> to manifest for package interaction
31Foreground Service NotificationShow notification within 10 seconds after service start
33POST_NOTIFICATIONSRuntime permission request for sending notifications
34Foreground Service TypesDeclare foreground service type in manifest
35Privacy SandboxRestrict advertising identifiers (Advertising ID)

How to Check Current targetSdk

The targetSdkVersion value can be obtained via ADB: the command adb shell dumpsys package com.example.myapp | grep targetSdk outputs targetSdk=34. In code, context.getApplicationInfo().targetSdkVersion returns an integer. For analytics, it is useful to log targetSdk together with android.os.Build.VERSION.SDK_INT to understand which behavioural changes are actually active in each session.

Google Play Requirements for targetSdkVersion (2026)

Google Play sets mandatory targetSdkVersion requirements for all published apps. Since August 2024, the minimum targetSdk = 33 (Android 13). Since August 2025, targetSdk = 34. It is expected that from August 2026, Google will require targetSdk = 35 (Android 15). New apps and updates to existing ones must comply with these requirements, otherwise the console blocks publishing. This is a Google Play policy, not an Android Runtime restriction: an app with targetSdk 34 can run on Android 16, but cannot be published on Play Store.

Android App Bundle (AAB) is the mandatory publishing format since August 2021. APK is no longer accepted in Google Play (except for apps larger than 150 MB and some legacy projects). The AAB format allows Google to generate optimized APKs for each API Level and screen density, reducing download size by 15-30%. To check targetSdk, Google Play analyzes the AAB manifest and issues an error with the minimum required value if it does not comply.

PeriodMinimum targetSdkAndroid VersionNote
August 202433Android 13Tiramisu — mandatory POST_NOTIFICATIONS
August 202534Android 14Upside Down Cake — foreground service types
August 202635Android 15Vanilla Ice Cream — Privacy Sandbox
August 2027 (planned)36Android 16Baklava — T+

Google Play Console checks targetSdkVersion not only when uploading a new AAB, but also when updating an existing app. If your app has targetSdk 33 and Google raises the minimum threshold to 34 — you will not be able to release any updates until you raise targetSdk. For apps that have not been updated for a long time, Google Play may automatically unpublish them.

How to Update targetSdkVersion Without Errors

Updating targetSdkVersion is not just changing a number in build.gradle. Each behavioural change can break existing functionality if the code is not prepared in advance. It is recommended to start preparation 3-6 months before the Google Play deadline, especially if the app is large and uses many system APIs.

Step-by-step process: Step 1 — study the behavioural changes for the new API Level in the Android Developers documentation (page "Behavioural Changes by API Level"). Step 2 — create a targetSdk-update branch and change targetSdk to the new value. Step 3 — run the app on an emulator or device with the new API Level and check every feature related to the changes. Step 4 — fix errors: add permissions, change file handling, update the manifest.

Step 5 — test on older devices. Raising targetSdk does not affect devices with API Level below the new targetSdk, but behavioural changes apply to all devices with API Level >= targetSdk. If you raised targetSdk from 33 to 34, then on devices with API 34+ the behavioural changes of API 34 will be enabled. On devices with API 33 nothing will change.

kotlin
// Preparing for targetSdk 35: Privacy Sandbox
import android.os.Build
import android.os.Build.VERSION_CODES
import com.google.android.gms.ads.identifier.AdvertisingIdClient

class AdsManager {

    fun getAdvertisingId(context: android.content.Context): String? {
        // Privacy Sandbox restricts Advertising ID from API 35
        if (Build.VERSION.SDK_INT >= VERSION_CODES.VANILLA_ICE_CREAM) {
            // API 35+ — identifier unavailable, use MeasurementManager
            return null
        }
        return try {
            val adInfo = AdvertisingIdClient.getAdvertisingIdInfo(context)
            adInfo.getId()
        } catch (e: Exception) {
            null
        }
    }

    // Check: which behavioural changes are active
    fun getActiveChanges(context: android.content.Context): List<String> {
        val sdkInt = Build.VERSION.SDK_INT
        val targetSdk = context.applicationInfo.targetSdkVersion
        return buildList {
            if (sdkInt >= VERSION_CODES.Q && targetSdk >= VERSION_CODES.Q)
                add("ScopedStorage")
            if (sdkInt >= VERSION_CODES.TIRAMISU && targetSdk >= VERSION_CODES.TIRAMISU)
                add("PostNotifications")
            if (sdkInt >= VERSION_CODES.UPSIDE_DOWN_CAKE && targetSdk >= VERSION_CODES.UPSIDE_DOWN_CAKE)
                add("FgsTypes")
        }
    }
}

The AdsManager class demonstrates preparation for Privacy Sandbox (API 35). Advertising ID becomes unavailable starting from API 35 with targetSdk 35+. The function getActiveChanges shows the correct pattern for checking behavioural changes: you need to check both the device's SDK_INT and the app's targetSdk. Only when both conditions match is the change actually active.

Android 15 (API 35): Key Behavioural Changes

Android 15 (API 35, Vanilla Ice Cream) introduces several critical behavioural changes that developers must consider when updating targetSdk to 35. First — Privacy Sandbox for Android. This is Google's initiative to replace Advertising ID with more private APIs: Topics API (user interests), Protected Audience (retargeting), and Attribution Reporting (conversions). Starting from API 35, Advertising ID ceases to be a stable identifier and may return a null value.

The second change — Foreground Service Types (API 34, continued in API 35). Starting from API 34, every app with targetSdk 34+ must specify the foreground service type in the manifest: dataSync, systemExempted, shortService, location, mediaPlayback, and others. Without this, the system throws ForegroundServiceTypeNotAllowedException. In API 35, a new health type has been added and validation of existing types has been tightened. All foreground services must be reviewed.

The third change — restriction on SCHEDULE_EXACT_ALARM. Starting from API 35, apps with targetSdk 35+ cannot use SCHEDULE_EXACT_ALARM without explicit user permission. The system shows a dialog, and the user must approve exact scheduling. For alarms and timers, this means an additional UX step. An alternative is to use inexact alarms with a 10-minute buffer.

kotlin
// Android 15 (API 35): checking SCHEDULE_EXACT_ALARM
import android.app.AlarmManager
import android.os.Build
import android.provider.Settings

class AlarmScheduler {

    fun canScheduleExactAlarms(context: android.content.Context): Boolean {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
            // API 35+: user permission required
            val alarmManager = context.getSystemService(
                android.content.Context.ALARM_SERVICE
            ) as AlarmManager
            return alarmManager.canScheduleExactAlarms()
        }
        // Below API 35 — exact alarms available without permission
        return true
    }

    fun requestExactAlarmPermission(activity: android.app.Activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
            val intent = android.content.Intent(
                Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM
            ).apply {
                data = android.net.Uri.fromParts(
                    "package", activity.packageName, null
                )
            }
            activity.startActivity(intent)
        }
    }
}

Privacy Sandbox and the alarm restriction are the two most critical behavioural changes of API 35. Ad SDKs will need to migrate to Topics API and Attribution Reporting. For apps with alarms and reminders — UX adaptation for the permission dialog. Ignoring these changes will lead to app crashes at runtime on Android 15 or broken ad monetization.

Difference Between targetSdk and compileSdk

The difference between targetSdkVersion and compileSdkVersion is one of the most common sources of confusion among Android developers. compileSdkVersion is the version of the SDK against which the code is compiled. It determines which APIs are available at compile time but does not affect runtime behavior. targetSdkVersion is the version against which the app is tested — it determines which behavioural changes apply at runtime. compileSdk can and should be higher than or equal to targetSdk.

The rule is simple: compileSdk >= targetSdk >= minSdk. compileSdk is usually equal to the latest stable API Level (in 2026 — 36). targetSdk should be as high as possible among versions you have tested. minSdk should be as low as possible for maximum reach. Raising compileSdk does not require testing behavioural changes — it only opens access to new APIs for the compiler. Raising targetSdk requires a full testing cycle of all behavioural changes.

ParameterTime of EffectAffectsCan Be Higher Than Others
compileSdkVersionCompilationAPI availability for codeYes, always higher than targetSdk
targetSdkVersionRuntimeBehavioural changesYes, but lower than compileSdk
minSdkVersionInstallationDevice compatibilityNo, always the lowest

In practice: if you want to use a new API from Android 16 (API 36) but have not yet tested behavioural changes of API 36, set compileSdk = 36, targetSdk = 35. The code will compile with the new APIs, but behavioural changes of API 36 will not apply. Once you have tested all changes — raise targetSdk to 36.

Frequently Asked Questions

What is targetSdkVersion in Android?

targetSdkVersion is the API Level against which the app is tested. Android uses it to apply behavioural changes — behavioral changes introduced in that version. If targetSdk is lower than the device's API Level, behavioural changes are not applied. Google Play requires targetSdk no older than 1 year from the current API Level for publishing new versions and updates.

How is targetSdkVersion different from compileSdkVersion?

targetSdkVersion affects runtime behavior: it enables behavioural changes of a specific API Level. compileSdkVersion only affects compilation: it determines which APIs are available to the compiler. compileSdk can be higher than targetSdk, but not vice versa. Raising compileSdk does not require testing; raising targetSdk requires checking all behavioural changes.

What behavioural changes does Android 15 (API 35) introduce?

Android 15 (API 35) introduces key behavioural changes: Privacy Sandbox with Advertising ID restrictions, Foreground Service Types with mandatory declaration, SCHEDULE_EXACT_ALARM restriction with a permission dialog, tightened Scoped Storage, and automatic migration to credential-less authentication. Apps with targetSdk 35+ must go through a full testing cycle under API 35.

What happens if I don't update targetSdkVersion?

If you don't update targetSdkVersion, Google Play will block publishing new versions of your app. Each year Google raises the minimum targetSdk: from August 2025 — targetSdk 34+, from August 2026 targetSdk 35+ is expected. Apps that do not meet the requirements are removed from the store. Additionally, security behavioural changes are not applied, making the app vulnerable.

How to check targetSdkVersion of an installed app?

To check targetSdkVersion, use ADB: adb shell dumpsys package com.example.myapp | grep targetSdk. In Android Studio, open APK Analyzer: Build → Analyze APK → AndroidManifest.xml → uses-sdk. In code: context.applicationInfo.targetSdkVersion. In Google Play Console, targetSdk is displayed on the release page under Artifact Details.

Summary

  • targetSdkVersion is the API Level against which the app is tested; determines which behavioural changes apply at runtime
  • Behavioural changes — Scoped Storage, POST_NOTIFICATIONS, Foreground Service Types, Privacy Sandbox — are activated by targetSdk
  • Google Play requires targetSdk no older than 1 year from the current API Level, otherwise blocks publishing updates
  • Upgrading targetSdk requires 3-6 months of preparation: studying behavioural changes, testing, fixing code
  • Privacy Sandbox (API 35+) changes how advertising identifiers work — requires Topics API and Attribution Reporting
  • compileSdk handles compilation and API access; targetSdk handles runtime behavior; compileSdk >= targetSdk
  • Checking active behavioural changes: context.applicationInfo.targetSdkVersion + Build.VERSION.SDK_INT

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