SKILL.md
Android Version Adaptation Guide
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).
🚀 Adaptation Strategy
- Update
compileSdkVersion: Always compile with the latest SDK to access new APIs. - Update
targetSdkVersionIncrementally: Update one version at a time (e.g., 30 -> 31 -> 32) and test thoroughly. - Review Changes: Check "Behavior changes: all apps" and "Behavior changes: apps targeting Android X" for the specific version.
- Test: Test on emulators or real devices running the target version.
📱 Version-Specific Changes
Android 15 (API 35) - Vanilla Ice Cream
Ref: Official Android 15 Migration Guide
- Edge-to-Edge Enforcement:
- Change: Apps targeting SDK 35 are displayed edge-to-edge by default. Status bar and navigation bar backgrounds are transparent. - Action: Use WindowInsets to handle overlaps. - Opt-out: Set <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item> in your theme (Temporary). - Deprecated: window.statusBarColor and window.navigationBarColor are ignored.
- Foreground Service Timeouts:
- Change: dataSync and mediaProcessing foreground services have a roughly 6-hour execution limit.
- Screen Recording Detection:
- New API: Apps can detect if they are being recorded using WindowManager.addScreenRecordingCallback.
- Package Visibility:
- Change: Stopped apps are no longer visible to other apps, even if they have QUERYALLPACKAGES permission.
Android 14 (API 34) - Upside Down Cake
Ref: Official Android 14 Migration Guide
- Foreground Service Types (Mandatory):
- Change: Must specify android:foregroundServiceType in Manifest for all services calling startForeground(). - Types: camera, location, mediaPlayback, dataSync, microphone, phoneCall, connectedDevice, etc. - Action: <service android:name=".MyService" android:foregroundServiceType="mediaPlayback" />
- Exact Alarms Denied by Default:
- Change: SCHEDULEEXACTALARM permission is no longer pre-granted to most apps. - Action: Use USEEXACTALARM (if eligible) or prompt user to grant permission.
- Selected Photos Access:
- Change: User can grant access to only selected photos. - Action: Handle READMEDIAVISUALUSERSELECTED permission.
- Implicit Intents:
- Change: Implicit intents are restricted for internal app components. Exported components must be explicit.
Android 13 (API 33) - Tiramisu
Ref: Official Android 13 Migration Guide
- Notification Permission:
- Change: Runtime permission POST_NOTIFICATIONS is required to post notifications. - Action: Request permission at runtime.
- Granular Media Permissions:
- Change: READEXTERNALSTORAGE is deprecated. Use granular permissions: - READMEDIAIMAGES - READMEDIAVIDEO - READMEDIAAUDIO
- Nearby Wi-Fi Devices:
- Change: NEARBYWIFIDEVICES permission for local Wi-Fi scanning. No longer requires Location permission for this use case.
- Photo Picker:
- New API: System UI for picking photos without requiring full storage permissions.
Android 12 (API 31/32) - Snow Cone
Ref: Official Android 12 Migration Guide
- Splash Screen:
- Change: System enforces a default splash screen. - Action: Use androidx.core:core-splashscreen library to customize it.
- PendingIntent Mutability:
- Change: Must specify PendingIntent.FLAGIMMUTABLE or PendingIntent.FLAGMUTABLE.
- Exported Components:
- Change: Must explicitly set android:exported="true" or "false" for activities/services/receivers with intent filters.
- Bluetooth Permissions:
- Change: New runtime permissions BLUETOOTHSCAN, BLUETOOTHCONNECT, BLUETOOTHADVERTISE. Legacy BLUETOOTH and BLUETOOTHADMIN are deprecated.
Android 11 (API 30) - Red Velvet Cake
Ref: Official Android 11 Migration Guide
- Package Visibility:
- Change: Apps can no longer see all installed packages. - Action: Use <queries> in Manifest to declare packages you interact with.
- Scoped Storage (Enforced):
- Change: WRITEEXTERNALSTORAGE is deprecated and has no effect on API 30+. - Action: Use MediaStore or Storage Access Framework (SAF). For file managers, request MANAGEEXTERNALSTORAGE.
- Toast:
- Change: Custom toasts from background are blocked.
- Phone Number Access:
- Change: READPHONESTATE no longer grants access to phone numbers. Use READPHONENUMBERS.
Android 10 (API 29) - Quince Tart
- Scoped Storage (Introduced):
- Action: Can opt-out using requestLegacyExternalStorage="true" (Only works up to API 29).
- Background Location:
- Change: ACCESSBACKGROUNDLOCATION required for accessing location while app is in background.
- Device Identifiers:
- Change: IMEI/Serial no longer accessible to non-system apps. Use Android ID or GUID.
Android 9.0 (API 28) - Pie
- Cleartext Traffic (HTTP):
- Change: HTTP is disabled by default. - Action: Add android:usesCleartextTraffic="true" in Manifest or configure networksecurityconfig.xml.
- Foreground Service Permission:
- Change: Requires FOREGROUND_SERVICE permission (normal permission, auto-granted).
Android 8.0 (API 26) - Oreo
- Notification Channels:
- Change: Mandatory. All notifications must be assigned to a channel.
- Background Execution Limits:
- Change: Services cannot run in background when app is idle. Use JobScheduler or WorkManager.
- APK Installation:
- Change: Requires REQUESTINSTALLPACKAGES permission.
🛠 Common Solutions & Code Snippets
1. Notification Permission Check (Android 13+)
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)
}
}
}
2. Creating Notification Channel (Android 8.0+)
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)
}
}
3. FileProvider Configuration (Android 7.0+)
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>
4. Network Security Config (Allow HTTP)
AndroidManifest.xml:
<application
android:networkSecurityConfig="@xml/network_security_config"
...>
res/xml/networksecurityconfig.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>
5. Package Visibility (Android 11+)
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>