行為變更:指定 Android 15 以上版本的應用程式

和先前版本一樣,Android 15 也包含可能會影響應用程式的行為變更。以下行為變更僅適用於指定 Android 15 以上版本的應用程式。如果您的應用程式指定 Android 15 以上版本,建議您視情況修改應用程式,以支援這些行為。

此外,無論應用程式的 targetSdkVersion 為何,請務必查看影響所有在 Android 15 上執行的應用程式行為變更清單。

核心功能

Android 15 會修改或擴充 Android 系統的各種核心功能。

前景服務異動

我們將對 Android 15 的前景服務進行下列異動。

資料同步處理前景服務逾時行為

Android 15 introduces a new timeout behavior to dataSync for apps targeting Android 15 (API level 35) or higher. This behavior also applies to the new mediaProcessing foreground service type.

The system permits an app's dataSync services to run for a total of 6 hours in a 24-hour period, after which the system calls the running service's Service.onTimeout(int, int) method (introduced in Android 15). At this time, the service has a few seconds to call Service.stopSelf(). When Service.onTimeout() is called, the service is no longer considered a foreground service. If the service does not call Service.stopSelf(), the system throws an internal exception. The exception is logged in Logcat with the following message:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type dataSync did not stop within its timeout: [component name]"

To avoid problems with this behavior change, you can do one or more of the following:

  1. Have your service implement the new Service.onTimeout(int, int) method. When your app receives the callback, make sure to call stopSelf() within a few seconds. (If you don't stop the app right away, the system generates a failure.)
  2. Make sure your app's dataSync services don't run for more than a total of 6 hours in any 24-hour period (unless the user interacts with the app, resetting the timer).
  3. Only start dataSync foreground services as a result of direct user interaction; since your app is in the foreground when the service starts, your service has the full six hours after the app goes to the background.
  4. Instead of using a dataSync foreground service, use an alternative API.

If your app's dataSync foreground services have run for 6 hours in the last 24, you cannot start another dataSync foreground service unless the user has brought your app to the foreground (which resets the timer). If you try to start another dataSync foreground service, the system throws ForegroundServiceStartNotAllowedException with an error message like "Time limit already exhausted for foreground service type dataSync".

Testing

To test your app's behavior, you can enable data sync timeouts even if your app is not targeting Android 15 (as long as the app is running on an Android 15 device). To enable timeouts, run the following adb command:

adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name

You can also adjust the timeout period, to make it easier to test how your app behaves when the limit is reached. To set a new timeout period, run the following adb command:

adb shell device_config put activity_manager data_sync_fgs_timeout_duration duration-in-milliseconds

新的媒體處理前景服務類型

Android 15 推出了新的前景服務類型 mediaProcessing。此服務類型適合用於轉碼媒體檔案等作業。舉例來說,媒體應用程式可能會下載音訊檔案,需要將其轉換成其他格式後再播放。您可以使用 mediaProcessing 前景服務,確保即使應用程式處於背景執行狀態,轉換也能繼續進行。

系統允許應用程式的 mediaProcessing 服務在 24 小時內執行總共 6 小時,之後系統會呼叫執行中的服務 Service.onTimeout(int, int) 方法 (在 Android 15 中推出)。此時,服務有幾秒的時間可以呼叫 Service.stopSelf()。如果服務未呼叫 Service.stopSelf(),系統會擲回內部例外狀況。例外狀況會記錄在 Logcat 中,並顯示以下訊息:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type mediaProcessing did not stop within its timeout: [component name]"

為避免例外狀況,您可以採取下列其中一種做法:

  1. 請讓服務實作新的 Service.onTimeout(int, int) 方法。應用程式收到回呼時,請務必在幾秒內呼叫 stopSelf()。(如果您沒有立即停止應用程式,系統會產生失敗)。
  2. 請確認應用程式的 mediaProcessing 服務在任何 24 小時內的總執行時間不超過 6 小時 (除非使用者與應用程式互動,重新設定計時器)。
  3. 只有在使用者直接互動時才啟動 mediaProcessing 前景服務;由於您的應用程式在服務啟動後位於前景,因此應用程式進入背景後,您的服務剩下六小時。
  4. 請改用 WorkManager 等其他 API,而非 mediaProcessing 前景服務。

如果應用程式的 mediaProcessing 前景服務在過去 24 小時內已執行 6 小時,您就無法啟動其他 mediaProcessing 前景服務,除非使用者將應用程式移至前景 (這樣會重設計時器)。如果您嘗試啟動其他 mediaProcessing 前景服務,系統會擲回 ForegroundServiceStartNotAllowedException,並顯示「前景服務類型 mediaProcessing 的時間限制已用盡」等錯誤訊息。

如要進一步瞭解 mediaProcessing 服務類型,請參閱「Android 15 的前景服務類型變更:媒體處理」。

測試

如要測試應用程式的行為,您可以啟用媒體處理逾時,即使應用程式並未以 Android 15 為目標版本 (只要應用程式在 Android 15 裝置上執行),也能啟用。如要啟用逾時值,請執行下列 adb 指令:

adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name

您也可以調整逾時期限,方便測試應用程式在達到上限時的行為。如要設定新的逾時期限,請執行下列 adb 指令:

adb shell device_config put activity_manager media_processing_fgs_timeout_duration duration-in-milliseconds

BOOT_COMPLETED 廣播接收器啟動前景服務的限制

BOOT_COMPLETED 廣播接收器啟動有一些新限制 前景服務BOOT_COMPLETED 接收器無法啟動 下列類型的前景服務:

如果 BOOT_COMPLETED 接收器嘗試啟動任何這些類型的前景 服務就會擲回 ForegroundServiceStartNotAllowedException

測試

如要測試應用程式的行為,即使應用程式並非以 Android 15 為目標版本 (只要應用程式是在 Android 15 裝置上執行),您也可以啟用這些新限制。執行下列 adb 指令:

adb shell am compat enable FGS_BOOT_COMPLETED_RESTRICTIONS your-package-name

如要在不重新啟動裝置的情況下傳送「BOOT_COMPLETED」廣播訊息,請按照下列步驟操作: 執行下列 adb 指令:

adb shell am broadcast -a android.intent.action.BOOT_COMPLETED your-package-name

應用程式擁有 SYSTEM_ALERT_WINDOW 權限時,啟動前景服務的限制

Previously, if an app held the SYSTEM_ALERT_WINDOW permission, it could launch a foreground service even if the app was currently in the background (as discussed in exemptions from background start restrictions).

If an app targets Android 15, this exemption is now narrower. The app now needs to have the SYSTEM_ALERT_WINDOW permission and also have a visible overlay window. That is, the app needs to first launch a TYPE_APPLICATION_OVERLAY window and the window needs to be visible before you start a foreground service.

If your app attempts to start a foreground service from the background without meeting these new requirements (and it does not have some other exemption), the system throws ForegroundServiceStartNotAllowedException.

If your app declares the SYSTEM_ALERT_WINDOW permission and launches foreground services from the background, it may be affected by this change. If your app gets a ForegroundServiceStartNotAllowedException, check your app's order of operations and make sure your app already has an active overlay window before it attempts to start a foreground service from the background. You can check if your overlay window is currently visible by calling View.getWindowVisibility(), or you can override View.onWindowVisibilityChanged() to get notified whenever the visibility changes.

Testing

To test your app's behavior, you can enable these new restrictions even if your app is not targeting Android 15 (as long as the app is running on an Android 15 device). To enable these new restrictions on starting foreground services from the background, run the following adb command:

adb shell am compat enable FGS_SAW_RESTRICTIONS your-package-name

變更應用程式修改零打擾模式全域狀態的時機

指定 Android 15 (API 級別 35) 以上版本的應用程式,將無法再變更裝置上的勿擾模式 (DND) 全域狀態或政策 (透過修改使用者設定或關閉勿擾模式)。相反地,應用程式必須提供 AutomaticZenRule,系統會將其與現有的最嚴格政策優先方案結合為全域政策。呼叫先前影響全域狀態的現有 API (setInterruptionFiltersetNotificationPolicy) 會導致建立或更新隱含的 AutomaticZenRule,而 AutomaticZenRule 的開啟和關閉狀態會根據這些 API 呼叫的呼叫週期而定。

請注意,只有在應用程式呼叫 setInterruptionFilter(INTERRUPTION_FILTER_ALL) 且預期該呼叫會停用先前由其擁有者啟用的 AutomaticZenRule 時,這項變更才會影響可觀察的行為。

OpenJDK API 異動

Android 15 持續更新 Android 核心程式庫,以便與最新版 OpenJDK LTS 中的功能保持一致。

以下部分變更可能會影響以 Android 15 (API 級別 35) 為目標版本的應用程式相容性:

  • 字串格式 API 異動:使用下列 String.format()Formatter.format() API 時,對引數索引、標記、寬度和精確度的驗證會更加嚴格:

    舉例來說,如果使用 0 的引數索引 (格式字串中的 %0),系統會擲回下列例外狀況:

    IllegalFormatArgumentIndexException: Illegal format argument index = 0
    

    在這種情況下,您可以使用 1 的引數索引 (格式字串中的 %1) 來修正問題。

  • 變更 Arrays.asList(...).toArray() 的元件類型:使用 Arrays.asList(...).toArray() 時,產生的陣列元件類型現在是 Object,而不是基礎陣列元素的類型。因此,以下程式碼會擲回 ClassCastException

    String[] elements = (String[]) Arrays.asList("one", "two").toArray();
    

    在這種情況下,如要將 String 保留為結果陣列中的元件類型,您可以改用 Collection.toArray(Object[])

    String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
    
  • 語言代碼處理方式異動:使用 Locale API 時,希伯來文、意第緒文和印尼文的語言代碼將不再轉換為舊版 (希伯來文:iw、意第緒文:ji、印尼文:in)。指定這些語言代碼時,請改用 ISO 639-1 的代碼 (希伯來文:he、意第緒文:yi、印尼文:id)。

  • 隨機整數序列的變更:根據 https://bugs.openjdk.org/browse/JDK-8301574 所做的變更,下列 Random.ints() 方法現在會傳回與 Random.nextInt() 方法不同的數字序列:

    一般來說,這項變更不應導致應用程式中斷行為,但程式碼不應預期從 Random.ints() 方法產生的序列會與 Random.nextInt() 相符。

在應用程式的建構設定中更新 compileSdk 以使用 Android 15 (API 級別 35)後,新的 SequencedCollection API 可能會影響應用程式的相容性:

  • kotlin-stdlib 中的 MutableList.removeFirst()MutableList.removeLast() 擴充函式發生衝突

    Java 中的 List 類型會對應至 Kotlin 中的 MutableList 類型。由於 List.removeFirst()List.removeLast() API 已在 Android 15 (API 級別 35) 中推出,因此 Kotlin 編譯器會將函式呼叫 (例如 list.removeFirst()) 靜態解析為新的 List API,而非 kotlin-stdlib 中的擴充功能函式。

    如果應用程式重新編譯時,compileSdk 設為 35minSdk 設為 34 或更低版本,然後在 Android 14 以下版本上執行應用程式,系統就會擲回執行階段錯誤:

    java.lang.NoSuchMethodError: No virtual method
    removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;
    

    Android Gradle 外掛程式中現有的 NewApi lint 選項可以擷取這些新的 API 用法。

    ./gradlew lint
    
    MainActivity.kt:41: Error: Call requires API level 35 (current min is 34): java.util.List#removeFirst [NewApi]
          list.removeFirst()
    

    如要修正這個例外狀況和 Lint 錯誤,請在 Kotlin 中將 removeFirst()removeLast() 函式呼叫分別替換為 removeAt(0)removeAt(list.lastIndex)。如果您使用的是 Android Studio Ladybug | 2024.1.3 以上版本,則可針對這些錯誤使用快速修正選項。

    如果已停用 Lint 選項,建議您移除 @SuppressLint("NewApi")lintOptions { disable 'NewApi' }

  • 與 Java 中的其他方法衝突

    我們已在現有類型中新增新方法,例如 ListDeque。這些新方法可能與其他介面和類別中具有相同名稱和引數類型的其他方法不相容。如果方法簽章與不相容的項目發生衝突,javac 編譯器會輸出建構時間錯誤。例如:

    錯誤示例 1:

    javac MyList.java
    
    MyList.java:135: error: removeLast() in MyList cannot implement removeLast() in List
      public void removeLast() {
                  ^
      return type void is not compatible with Object
      where E is a type-variable:
        E extends Object declared in interface List
    

    錯誤示例 2:

    javac MyList.java
    
    MyList.java:7: error: types Deque<Object> and List<Object> are incompatible;
    public class MyList implements  List<Object>, Deque<Object> {
      both define reversed(), but with unrelated return types
    1 error
    

    錯誤示例 3:

    javac MyList.java
    
    MyList.java:43: error: types List<E#1> and MyInterface<E#2> are incompatible;
    public static class MyList implements List<Object>, MyInterface<Object> {
      class MyList inherits unrelated defaults for getFirst() from types List and MyInterface
      where E#1,E#2 are type-variables:
        E#1 extends Object declared in interface List
        E#2 extends Object declared in interface MyInterface
    1 error
    

    如要修正這些建構錯誤,實作這些介面的類別應覆寫方法,並使用相容的傳回類型。例如:

    @Override
    public Object getFirst() {
        return List.super.getFirst();
    }
    

安全性

Android 15 包含提升系統安全性的變更,有助於保護應用程式和使用者免受惡意應用程式的侵害。

啟動安全的背景活動

Android 15 可保護使用者不受惡意應用程式侵擾,並讓使用者進一步控管 方法是加入可防止惡意背景應用程式的變更 將其他應用程式移至前景、提升其權限並濫用 互動。自以下日期起,系統已限制啟動背景活動: Android 10 (API 級別 29)。

禁止與堆疊頂端 UID 不符的應用程式啟動活動

惡意應用程式可能會在同一工作中啟動其他應用程式的活動,然後 疊加在上,營造出該應用程式的錯覺這項「工作」 駭客」攻擊會避開目前的背景啟動限制,因為這 發生在相同的可見工作中為降低這種風險,Android 15 新增了 旗標,防止應用程式啟動與堆疊上頂層 UID 不符的應用程式 活動。如要選擇加入應用程式的所有活動,請更新 allowCrossUidActivitySwitchFromBelow敬上 屬性加入應用程式的 AndroidManifest.xml 檔案中:

<application android:allowCrossUidActivitySwitchFromBelow="false" >

如果符合下列所有條件,系統就會啟用新的安全措施:

  • 執行啟動作業的應用程式以 Android 15 為目標。
  • 工作堆疊頂端的應用程式以 Android 15 為目標。
  • 所有可見的活動已選擇採用新的保護措施

啟用安全措施後,應用程式可能會返回主畫面,而非 則最後顯示的應用程式。

其他變更

除了 UID 比對的限制外,下列其他變更也會 包含:

  • 變更 PendingIntent 位創作者,禁止開啟背景活動,包括: default。這可避免應用程式意外 PendingIntent,可能遭不肖人士濫用。
  • 除非 PendingIntent 傳送者,否則請勿將應用程式移至前景 這項異動旨在避免惡意應用程式濫用 可在背景啟動活動根據預設,應用程式 允許將工作堆疊移至前景,除非創作者允許 背景活動啟動權限或傳送者有背景活動 啟動權限。
  • 控管工作堆疊的主要活動如何完成任務。如果 完成一項任務後,Android 就會回到 上次使用時間。此外,如果非頂層活動完成任務,Android 就會 返回主畫面。也不會阻斷 活動。
  • 避免從其他應用程式啟動任意活動 工作。這項變更藉由建立 假冒其他應用程式的活動。
  • 禁止將不可見的視窗視為背景活動 產品發布。避免惡意應用程式濫用背景 使用者啟動活動後,系統會顯示擾人或惡意的內容。

更安全的意圖

Android 15 推出了新的選用安全措施,讓意圖更安全可靠。這些異動旨在防止意圖遭到惡意應用程式濫用,並避免潛在的安全漏洞。Android 15 針對意圖的安全性進行了兩項主要改善:

  • 比對目標意圖篩選器:如果意圖指定特定元件,就必須準確符合目標的意圖篩選器規格。如果您傳送意圖來啟動其他應用程式的活動,目標意圖元件必須與接收活動宣告的意圖篩選器相符。
  • 意圖必須包含動作:沒有動作的意圖將不再與任何意圖篩選器相符。也就是說,用於啟動活動或服務的意圖必須有明確的動作定義。

如要檢查應用程式如何回應這些變更,請在應用程式中使用 StrictMode。如要查看 Intent 使用違規的詳細記錄,請新增下列方法:

Kotlin


fun onCreate() {
    StrictMode.setVmPolicy(VmPolicy.Builder()
        .detectUnsafeIntentLaunch()
        .build()
    )
}

Java


public void onCreate() {
    StrictMode.setVmPolicy(new VmPolicy.Builder()
            .detectUnsafeIntentLaunch()
            .build());
}

使用者體驗和系統使用者介面

Android 15 包含一些變更,旨在打造更一致、直覺的使用者體驗。

視窗插邊變更

Android 15 有兩項與視窗內嵌相關的變更:預設會強制執行邊到邊,且有設定變更,例如系統列的預設設定。

Edge-to-edge enforcement

如果應用程式指定 Android 15 (API 級別 35),則在搭載 Android 15 的裝置上,應用程式預設會採用無邊框畫面。

指定 Android 14 為目標版本的應用程式,且在 Android 15 裝置上並非從邊到邊顯示。


指定 Android 15 (API 級別 35) 為目標版本的應用程式,且在 Android 15 裝置上呈現邊到邊的效果。這個應用程式主要使用可自動套用插邊的 Material 3 Compose 元件。這個畫面不會受到 Android 15 無邊框強制執行措施的負面影響。

這是重大變更,可能會對應用程式的使用者介面造成負面影響。這項變更會影響下列 UI 區域:

  • 手勢操作導覽列
    • 預設為透明。
    • 停用底部偏移,因此除非套用插邊,否則內容會在系統導覽列後方繪製。
    • setNavigationBarColorR.attr#navigationBarColor 已淘汰,不會影響手勢操作模式。
    • setNavigationBarContrastEnforcedR.attr#navigationBarContrastEnforced 仍不會影響手勢操作模式。
  • 3 按鈕操作
    • 不透明度預設為 80%,顏色可能會與視窗背景相符。
    • 停用底部偏移,因此除非套用插邊,否則內容會在系統導覽列後方繪製。
    • setNavigationBarColorR.attr#navigationBarColor 預設會設為與視窗背景相符。視窗背景必須是可繪顏色,才能套用這個預設值。這個 API 已淘汰,但仍會影響 3 鍵導覽功能。
    • setNavigationBarContrastEnforcedR.attr#navigationBarContrastEnforced 預設為 true,會在 3 鍵導覽中加入 80% 不透明的背景。
  • 狀態列
    • 預設為透明。
    • 頂端偏移值已停用,因此除非套用插邊,否則內容會在狀態列後方繪製。
    • setStatusBarColorR.attr#statusBarColor 已淘汰,對 Android 15 沒有任何影響。
    • setStatusBarContrastEnforcedR.attr#statusBarContrastEnforced 已淘汰,但仍會對 Android 15 產生影響。
  • 螢幕缺孔
    • 非浮動式視窗的 layoutInDisplayCutoutMode 必須為 LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYSSHORT_EDGESNEVERDEFAULT 會解讀為 ALWAYS,這樣使用者就不會看到螢幕缺口造成的黑色條紋,且螢幕會顯示為無邊框。

以下範例顯示應用程式在指定 Android 15 (API 級別 35) 之前與之後,以及套用插邊之前與之後的畫面。

指定 Android 14 為目標版本的應用程式,且在 Android 15 裝置上並非從邊到邊顯示。
以 Android 15 (API 級別 35) 為目標版本的應用程式,且在 Android 15 裝置上是從邊到邊顯示。不過,由於 Android 15 強制實施無邊框設計,許多元素現在都會被狀態列、3 鍵導覽列或螢幕凹口隱藏。隱藏的 UI 包括 Material 2 頂端應用程式列、浮動動作按鈕和清單項目。
以 Android 15 (API 級別 35) 為目標版本的應用程式,在 Android 15 裝置上會是從邊到邊,並套用內嵌,以免 UI 遭到隱藏。
如何確認應用程式是否已採用全螢幕設計

如果您的應用程式已採用從邊到邊的設計,並套用內嵌,則大多不會受到影響,但以下情境除外:不過,即使您認為自己不會受到影響,也建議您測試應用程式。

  • 您有非浮動式視窗,例如使用 SHORT_EDGESNEVERDEFAULT 而非 LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYSActivity。如果應用程式在啟動時異常終止,可能是因為啟動畫面。您可以將核心 SplashScreen 依附元件升級至 1.2.0-alpha01 以上版本,或是設定 window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always
  • 可能會有流量較低的畫面,其中包含遮蔽的 UI。確認這些較少造訪的畫面沒有遮蔽的 UI。流量較低的螢幕包括:
    • 新手上路或登入畫面
    • 設定頁面
如果應用程式未採用全螢幕顯示,請檢查以下事項

如果您的應用程式未採用全螢幕設計,很可能會受到影響。除了已採用全螢幕設計的應用程式情境之外,您還應考量下列事項:

  • 如果應用程式在 Compose 中使用 Material 3 元件 (androidx.compose.material3),例如 TopAppBarBottomAppBarNavigationBar,這些元件可能不會受到影響,因為它們會自動處理插邊。
  • 如果應用程式使用 Compose 的 Material 2 元件 (androidx.compose.material),這些元件不會自動處理插邊。不過,您可以存取插邊,然後手動套用。在 androidx.compose.material 1.6.0 以上版本中,請使用 windowInsets 參數,為 BottomAppBarTopAppBarBottomNavigationNavigationRail 手動套用插邊。同樣地,對 Scaffold 也是使用 contentWindowInsets 參數。
  • 如果應用程式使用 View 和 Material 元件 (com.google.android.material),大多數以 View 為基礎的 Material 元件 (例如 BottomNavigationViewBottomAppBarNavigationRailViewNavigationView) 都會處理插邊,因此不需要額外處理。不過,如果您使用 AppBarLayout,就需要新增 android:fitsSystemWindows="true"
  • 如為自訂可組合項,請手動將插邊套用為邊框間距。如果內容位於 Scaffold 中,您可以使用 Scaffold 邊框間距值使用內嵌內容。否則,請使用 WindowInsets 之一套用邊框間距。
  • 如果應用程式使用檢視畫面和 BottomSheetSideSheet 或自訂容器,請使用 ViewCompat.setOnApplyWindowInsetsListener 套用邊框間距。對於 RecyclerView,也請使用這個事件監聽器套用邊框間距,同時新增 clipToPadding="false"
如果應用程式必須提供自訂背景保護功能,應檢查哪些項目

如果應用程式必須為 3 鍵導覽或狀態列提供自訂背景保護,則應使用 WindowInsets.Type#tappableElement() 將可組合項或檢視畫面置於系統列後方,以取得 3 鍵導覽列高度或 WindowInsets.Type#statusBars

其他邊緣到邊緣資源

如要進一步瞭解套用內嵌區的注意事項,請參閱「Edge to Edge Views」和「Edge to Edge Compose」指南。

已淘汰的 API

下列 API 已淘汰,但未停用:

下列 API 已淘汰並停用:

Stable configuration

If your app targets Android 15 (API level 35) or higher, Configuration no longer excludes the system bars. If you use the screen size in the Configuration class for layout calculation, you should replace it with better alternatives like an appropriate ViewGroup, WindowInsets, or WindowMetricsCalculator depending on your need.

Configuration has been available since API 1. It is typically obtained from Activity.onConfigurationChanged. It provides information like window density, orientation, and sizes. One important characteristic about the window sizes returned from Configuration is that it previously excluded the system bars.

The configuration size is typically used for resource selection, such as /res/layout-h500dp, and this is still a valid use case. However, using it for layout calculation has always been discouraged. If you do so, you should move away from it now. You should replace the use of Configuration with something more suitable depending on your use case.

If you use it to calculate the layout, use an appropriate ViewGroup, such as CoordinatorLayout or ConstraintLayout. If you use it to determine the height of the system navbar, use WindowInsets. If you want to know the current size of your app window, use computeCurrentWindowMetrics.

The following list describes the fields affected by this change:

elegantTextHeight 屬性預設為 true

針對指定 Android 15 (API 級別 35) 的應用程式,elegantTextHeight TextView 屬性預設會變成 true,將預設使用的緊湊字型取代為具有大型垂直指標的某些指令碼,以便更容易閱讀。我們推出了精簡字型,以免版面配置中斷;Android 13 (API 級別 33) 允許文字版面配置利用 fallbackLineSpacing 屬性拉長垂直高度,藉此避免許多這類中斷情形。

在 Android 15 中,系統仍會保留精簡字型,因此應用程式可以將 elegantTextHeight 設為 false,以便取得與先前相同的行為,但未來版本不太可能支援這項功能。因此,如果您的應用程式支援下列文字:阿拉伯文、老撾文、緬甸文、泰米爾文、古吉拉特文、卡納達文、馬拉雅拉姆文、奧里雅文、泰盧固文或泰文,請將 elegantTextHeight 設為 true 來測試應用程式。

elegantTextHeight 指定 Android 14 (API 級別 34) 以下版本為目標版本的應用程式行為。
elegantTextHeight 指定 Android 15 為目標版本的應用程式行為。

針對複雜字母形狀變更 TextView 寬度

在舊版 Android 中,部分草書字型或形狀複雜的語言,可能會在前一個或下一個字元的區域中繪製字母。在某些情況下,這類信件會在開頭或結尾處遭到裁切。自 Android 15 起,TextView 會分配寬度,以便繪製這類字母的空間,並允許應用程式要求左側額外的邊框間距,以防裁剪。

由於這項變更會影響 TextView 決定寬度的做法,因此如果應用程式指定 Android 15 (API 級別 35) 以上版本,TextView 預設會分配更多寬度。您可以在 TextView 上呼叫 setUseBoundsForWidth API,啟用或停用這項行為。

由於新增左邊邊框間距可能會導致現有版面配置不對齊,因此即使應用程式指定 Android 15 以上版本,也不會預設新增邊框間距。不過,您可以呼叫 setShiftDrawingOffsetForStartOverhang 新增額外的邊框間距,避免發生裁剪情形。

以下範例說明這些變更如何改善部分字型和語言的文字版面配置。

以草書字型顯示的英文文字標準版面配置。部分字母會遭到裁剪。以下是對應的 XML:

<TextView
    android:fontFamily="cursive"
    android:text="java" />
相同英文文字的版面配置,具有額外寬度和邊框間距。以下是對應的 XML:

<TextView
    android:fontFamily="cursive"
    android:text="java"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />
泰文的標準版面配置。部分字母遭到裁剪。 以下是對應的 XML:

<TextView
    android:text="คอมพิวเตอร์" />
相同泰文文字的版面配置,並增加寬度和邊框間距。以下是對應的 XML:

<TextView
    android:text="คอมพิวเตอร์"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />

EditText 的依地區設定的預設行高

在 Android 先前版本中,文字版面配置會拉伸文字高度,以符合與目前語言代碼相符的字型行高。舉例來說,如果內容是日文,由於日文字型的行高略大於拉丁字型,因此文字高度會稍微變高。不過,儘管行高有這些差異,EditText 元素的大小仍保持一致,不受使用語言代碼影響,如下圖所示:

三個方塊代表 EditText 元素,可包含英文 (en)、日文 (ja) 和緬甸文 (my) 的文字。EditText 的高度相同,即使這些語言的行高不同。

針對指定 Android 15 (API 級別 35) 的應用程式,現在會為 EditText 保留最小行高,以便與指定語言代碼的參考字型相符,如以下圖片所示:

三個方塊代表 EditText 元素,可包含英文 (en)、日文 (ja) 和緬甸文 (my) 的文字。EditText 的高度現在包含空格,可容納這些語言字型預設的行高。

如有需要,應用程式可以將 useLocalePreferredLineHeightForMinimum 屬性指定為 false,藉此還原先前的行為,並使用 Kotlin 和 Java 中的 setMinimumFontMetrics API 設定自訂的垂直最小指標。

相機和媒體

Android 15 會針對指定 Android 15 以上版本為目標版本的應用程式,對相機和媒體行為進行下列變更。

要求音訊焦點的限制

Apps that target Android 15 (API level 35) must be the top app or running a foreground service in order to request audio focus. If an app attempts to request focus when it does not meet one of these requirements, the call returns AUDIOFOCUS_REQUEST_FAILED.

You can learn more about audio focus at Manage audio focus.

更新非 SDK 限制

基於與 Android 開發人員合作及最新的內部測試,Android 15 包含更新後的受限制非 SDK 介面清單。在限制非 SDK 介面之前,我們盡可能確保公開替代方案的可得性。

如果您的應用程式並未以 Android 15 為目標版本,則此處所述的某些變更可能不會立即對您造成影響。不過,雖然應用程式可以存取某些非 SDK 介面 (視應用程式的目標 API 級別而定),但使用任何非 SDK 方法或欄位時,均可能面臨應用程式故障的高度風險。

如果不確定應用程式是否使用非 SDK 介面,您可以測試應用程式來確認。如果您的應用程式仰賴非 SDK 介面,則建議您開始規劃遷移至 SDK 替代方案。不過,我們瞭解有些應用程式可使用非 SDK 介面運作。如果您除了為應用程式中的某個功能使用非 SDK 介面外,已別無他法,則應要求新的公用 API

如要進一步瞭解此 Android 版本中的變更,請參閱「Android 15 的非 SDK 介面限制更新內容」。如要進一步瞭解非 SDK 介面的一般資訊,請參閱「非 SDK 介面的限制」。