Android 16 Adaptation Notes
2025, Feb 12
Android 16 Development Timeline (2024-2025)
- Preview Phase (2024)
- November: Dev Preview 1 - Baseline version
- December: Dev Preview 2 - Feature updates
- Beta Phase (2025)
- January: Beta 1
- February: Beta 2
- March: Beta 3
- April-May: Final version testing
- Final release
- Final version expected in Q2 2025. As of today (February 11, 2025), Google has released up to Beta 1
Behavior Changes
All Applications: The following behavior changes apply to all applications regardless of targetSdkVersion
JobScheduler Quota Optimizations
- The system now has further execution time limits for JobScheduler, aimed at further restricting the frequency and resource consumption of background tasks to improve overall system performance and battery life. Developers should have certain expectations for this. (Google doesn’t mention the exact execution time, using the word “quota”, so you should prepare for the following situations)
- Affected areas:
- The system’s execution time quota for JobScheduler is determined by the app’s standby bucket. Developers should expect different quotas when in different standby buckets. You can handle this with the code below:
val usageStatsManager = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager val bucket = usageStatsManager.appStandbyBucket when (bucket) { UsageStatsManager.STANDBY_BUCKET_ACTIVE -> { // Active: More generous execution time quota } UsageStatsManager.STANDBY_BUCKET_RARE -> { // Rarely used: Stricter execution time quota } ... See API for more status details }
- Even if a Job is started when the app is visible, it will be subject to execution time limits once the app goes into the background
// Even if the Job is started when the app is visible val jobInfo = JobInfo.Builder(...) .build() jobScheduler.schedule(jobInfo) // When the app goes to the background // The Job will be subject to execution time quota restrictions
- If you simultaneously have:
- A running ForegroundService
- A task scheduled through JobScheduler When both are running simultaneously, the JobScheduler task will be subject to runtime quota restrictions.
- The system’s execution time quota for JobScheduler is determined by the app’s standby bucket. Developers should expect different quotas when in different standby buckets. You can handle this with the code below:
- The above “affected areas” will limit tasks scheduled using
WorkManager
,JobScheduler
, andDownloadManager
- To debug why a Job stopped, Google recommends calling
WorkInfo.getStopReason()
(for JobScheduler, callJobParameters.getStopReason()
) to see the reason for stopping. - Or you can use
JobScheduler#getPendingJobReasonsHistory
to see the reason for stopping.
- To debug why a Job stopped, Google recommends calling
- How to test different Job quota restriction scenarios during development using adb commands?
# Assuming your app package name is com.example.app # 1. Make foreground-launched Jobs not subject to quota restrictions adb shell am compat enable OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS com.example.app # 2. Make Jobs running simultaneously with Foreground Services not subject to quota restrictions adb shell am compat enable OVERRIDE_QUOTA_ENFORCEMENT_TO_FGS_JOBS com.example.app # 3. Manually set the app's standby bucket adb shell am set-standby-bucket com.example.app active # Optional buckets: # - active # - working_set # - frequent # - rare # - restricted # Query the app's current standby bucket adb shell am get-standby-bucket com.example.app
Complete Deprecation of JobInfo#setImportantWhileForeground and JobInfo#isImportantWhileForeground()
- The function of
setImportantWhileForeground
is: telling the system that this Job is important while the app is in the foreground, hoping to prioritize this Job when the app is in the foreground or when the app is temporarily not restricted in the background# Marked as deprecated in Android 12 # Completely deprecated in Android 16, the system will ignore it even if used val jobInfo = JobInfo.Builder(jobId, componentName) .setImportantWhileForeground(true) .build()
Ordered broadcast
priority scope no longer global
- Setting order in broadcasts may no longer be effective
- Previous behavior:
- Android allowed applications to set priorities for broadcast receivers
This could be done in two ways:
- Using the android:priority attribute in the manifest file
- Using code IntentFilter#setPriority() to set it
- The system would send broadcasts sequentially from
high to low
priority
- Android allowed applications to set priorities for broadcast receivers
This could be done in two ways:
- Changes in
Android 16
:- Cross-process priority is no longer guaranteed:
- The order of broadcast reception between different processes is no longer guaranteed to follow priority
- Priority is only effective within
the same application process
- Priority range limitation:
- Priority values will be automatically limited to the range
(SYSTEM_LOW_PRIORITY + 1, SYSTEM_HIGH_PRIORITY - 1)
- Only
system components
can use the highest and lowest system priorities
- Priority values will be automatically limited to the range
- Cross-process priority is no longer guaranteed:
Potentially affected situations
:- Applications that register the same
broadcast intent
indifferent processes
and expect to receive them in a specific order - Applications that need to interact with
other processes
and rely on the order of broadcast reception
- Applications that register the same
ART Internal Changes (Android Runtime)
- Background info: https://source.android.com/docs/core/ota/modular-system
- Android 10 introduced Mainline (modular system components): Mainline modularizes certain
Android system components
and updates these components outside of Android’s normal release cycle - So now Google Play can update system components via Mainline
- Android 10 introduced Mainline (modular system components): Mainline modularizes certain
- Android 16 includes the latest ART updates
- Improved execution performance
- More Java feature support
- These improvements are available to devices running
Android 12
and above (over a billion devices) throughGoogle Play system updates
- Official ART blog from Google
Potential compatibility issues
- Applications depending on ART libraries may not function properly on Android 16
- This issue also affects
older Android versions
where the ART module is updated via Google Play system updates
- Impact on developers:
- Need to test if affected by ART updates
- Check the official version information for related compatibility issues: Click here
User Experience and System UI Adjustments
- Announcement about deprecated disruptive accessibility tools
- Android 16 has deprecated
accessibility announcements
that use announceForAccessibility or dispatch TYPE_ANNOUNCEMENT Impact on developers
: Mainly API adjustments, so you can refer directly to the documentation
- Android 16 has deprecated
- Support for 3-button navigation
3-button navigation
: Mainly refers to the addition of thepredictive back
feature. Predictive back is when the userlong presses
the back button in the navigation bar, allowing them to move to their desired navigation position based on gesture. See the video in this link for details: https://developer.android.com/about/versions/16/behavior-changes-all#three-button-predictive-back- However, it says
Support
, soat this stage
developers need to support it for it to work, and it’s not certain whether every manufacturer’s OTA supports it. If you’re using it, you should check. (Or targeting Android 16 SDK will enable it by default) - Actual system evolution:
- Android 13 (API 33): Need to enable “Predictive Back Animations” in developer options Even if the app implements the relevant functionality, developer options are required to see the animation effects
- Android 14 (API 34):
Can choose to enable/disable in Manifest for application or activity
<manifest ...> <application . . . android:enableOnBackInvokedCallback="false"> <activity android:name=".MainActivity" android:enableOnBackInvokedCallback="true" ... </activity> <activity android:name=".SecondActivity" android:enableOnBackInvokedCallback="false" ... </activity> </application> </manifest>
Need
developer options
to test animation effects - Android 15 (API 35) and above: No longer need developer options Animation effects will appear directly if the app has implemented and enabled the feature
- Impact on developers:
- Must use
AppCompat 1.6.0-alpha05 (AndroidX)
or higher API to implement the above functionality - Actual code can be referenced in the official documentation
- Apps targeting Android 16 and above need to handle related events or disable them.
- Must use
All Applications: Only apps targeting Android 16 and above will be affected
User Experience and System UI Adjustments
Developers
must migrate or opt out of predictive back functionality- Because the previous section mentioned that Android 16 behavior, regardless of targetSDK,
begins supporting
predictive back functionality - Now developers need to handle predictive back events or choose to disable them directly, with the
system enabling it by default
. (You can refer to the code or article in the section above)- Handle by implementing relevant code
- Disable by setting
android:enableOnBackInvokedCallback="false"
- Because the previous section mentioned that Android 16 behavior, regardless of targetSDK,
scheduleAtFixedRate Optimization
- Old version: When the app returns to an effective lifecycle, all missed execution jobs would execute immediately
- New version: Only one missed execution job will execute immediately at most
- API documentation: https://developer.android.com/reference/java/util/concurrent/ScheduledExecutorService#scheduleAtFixedRate(java.lang.Runnable,%20long,%20long,%20java.util.concurrent.TimeUnit)
Large Screen and Form Factor Specification Adjustments
- Large screen definition: Screens with a
minimum width
of 600 dp or greater -
Google says apps should be made with
adaptive layouts
, as limiting orientation and resizability is too restrictive in today’s multi-device world. (It feels like they may gradually remove related configurable parameters in the future, but currently it mainly targets large screens) - On targetSDK Android 16, on screens with minimum width ≥ 600dp, the system will ignore:
Screen orientation restrictions
,Resize restrictions
,Display ratio restrictions
- The following settings will be ignored on large screen devices
screenOrientation resizableActivity minAspectRatio maxAspectRatio setRequestedOrientation() getRequestedOrientation()
- On large screens, the system will ignore the following values for screenOrientation, setRequestedOrientation() and getRequestedOrientation():
portrait reversePortrait sensorPortrait userPortrait landscape reverseLandscape sensorLandscape userLandscape
-
However, at this stage, Google also provides parameters to opt out of this behavior, giving you a transition period (up to API 37)
## Specify a page to opt out of this behavior (up to API 37) <activity> <property android:name="android.window.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY" android:value="true" /> </activity> ## Global opt-out of this behavior (up to API 37) <application ...> <property android:name="android.window.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY" android:value="true" /> </application>
健康與健身權限
BODY_SENSORS 權限轉換為更細緻的權限
:先前需要BODY_SENSORS
或BODY_SENSORS_BACKGROUND
的任何 API,現在都需要對應的android.permissions.health
權限- 對開發者的影響:permission細化,需處裡。
- 文件