Expert guide for adapting Android apps to new Android versions (8.0-15.0). Invoke when updating targetSDK, fixing crashes on new Android versions, or handling permission changes.
This skill provides a comprehensive checklist and solution guide for adapting Android applications to newer Android versions, ranging from Android 8.0 (Oreo) to Android 15 (Vanilla Ice Cream).
compileSdkVersion: Always compile with the latest SDK to access new APIs.targetSdkVersion Incrementally: Update one version at a time (e.g., 30 -> 31 -> 32) and test thoroughly.Ref: Official Android 15 Migration Guide
WindowInsets to handle overlaps.<item name="android:windowOptOutEdgeToEdgeEnforcement">true</item> in your theme (Temporary).window.statusBarColor and window.navigationBarColor are ignored.dataSync and mediaProcessing foreground services have a roughly 6-hour execution limit.WindowManager.addScreenRecordingCallback.QUERY_ALL_PACKAGES permission.Ref: Official Android 14 Migration Guide
android:foregroundServiceType in Manifest for all services calling startForeground().camera, location, mediaPlayback, dataSync, microphone, phoneCall, connectedDevice, etc.<service android:name=".MyService" android:foregroundServiceType="mediaPlayback" />SCHEDULE_EXACT_ALARM permission is no longer pre-granted to most apps.USE_EXACT_ALARM (if eligible) or prompt user to grant permission.READ_MEDIA_VISUAL_USER_SELECTED permission.Ref: Official Android 13 Migration Guide
POST_NOTIFICATIONS is required to post notifications.READ_EXTERNAL_STORAGE is deprecated. Use granular permissions:READ_MEDIA_IMAGESREAD_MEDIA_VIDEOREAD_MEDIA_AUDIONEARBY_WIFI_DEVICES permission for local Wi-Fi scanning. No longer requires Location permission for this use case.Ref: Official Android 12 Migration Guide
androidx.core:core-splashscreen library to customize it.PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_MUTABLE.android:exported="true" or "false" for activities/services/receivers with intent filters.BLUETOOTH_SCAN, BLUETOOTH_CONNECT, BLUETOOTH_ADVERTISE. Legacy BLUETOOTH and BLUETOOTH_ADMIN are deprecated.Ref: Official Android 11 Migration Guide
<queries> in Manifest to declare packages you interact with.WRITE_EXTERNAL_STORAGE is deprecated and has no effect on API 30+.MediaStore or Storage Access Framework (SAF). For file managers, request MANAGE_EXTERNAL_STORAGE.READ_PHONE_STATE no longer grants access to phone numbers. Use READ_PHONE_NUMBERS.requestLegacyExternalStorage="true" (Only works up to API 29).ACCESS_BACKGROUND_LOCATION required for accessing location while app is in background.android:usesCleartextTraffic="true" in Manifest or configure network_security_config.xml.FOREGROUND_SERVICE permission (normal permission, auto-granted).JobScheduler or WorkManager.REQUEST_INSTALL_PACKAGES permission.fun checkNotificationPermission(activity: Activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.POST_NOTIFICATIONS), 101)
}
}
}
fun createNotificationChannel(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = "My Channel"
val descriptionText = "Channel description"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel("CHANNEL_ID", name, importance).apply {
description = descriptionText
}
val notificationManager: NotificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
Required for sharing files (installing APKs, taking photos).
AndroidManifest.xml:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
res/xml/file_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
<cache-path name="cache_files" path="."/>
</paths>
AndroidManifest.xml:
<application
android:networkSecurityConfig="@xml/network_security_config"
...>
res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- Allow Cleartext Traffic -->
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
<!-- Allow User Certificates for Debugging (Charles/Fiddler) -->
<debug-overrides>
<trust-anchors>
<certificates src="user" />
<certificates src="system" />
</trust-anchors>
</debug-overrides>
</network-security-config>
AndroidManifest.xml:
<manifest package="com.example.app">
<queries>
<!-- Specific apps -->
<package android:name="com.whatsapp" />
<package android:name="com.facebook.katana" />
<!-- Intent signatures -->
<intent>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="image/jpeg" />
</intent>
</queries>
...
</manifest>