行為變更:指定 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 introduces a new foreground service type, mediaProcessing. This service type is appropriate for operations like transcoding media files. For example, a media app might download an audio file and need to convert it to a different format before playing it. You can use a mediaProcessing foreground service to make sure the conversion continues even while the app is in the background.

The system permits an app's mediaProcessing 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(). 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 mediaProcessing did not stop within its timeout: [component name]"

To avoid having the exception, you can do one 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 mediaProcessing 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 mediaProcessing 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 mediaProcessing foreground service, use an alternative API, like WorkManager.

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

For more information about the mediaProcessing service type, see Changes to foreground service types for Android 15: Media processing.

Testing

To test your app's behavior, you can enable media processing 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 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 continues the work of refreshing Android's core libraries to align with the features in the latest OpenJDK LTS releases.

Some of these changes can affect app compatibility for apps targeting Android 15 (API level 35):

  • Changes to string formatting APIs: Validation of argument index, flags, width, and precision are now more strict when using the following String.format() and Formatter.format() APIs:

    For example, the following exception is thrown when an argument index of 0 is used (%0 in the format string):

    IllegalFormatArgumentIndexException: Illegal format argument index = 0
    

    In this case, the issue can be fixed by using an argument index of 1 (%1 in the format string).

  • Changes to component type of Arrays.asList(...).toArray(): When using Arrays.asList(...).toArray(), the component type of the resulting array is now an Object—not the type of the underlying array's elements. So the following code throws a ClassCastException:

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

    For this case, to preserve String as the component type in the resulting array, you could use Collection.toArray(Object[]) instead:

    String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
    
  • Changes to language code handling: When using the Locale API, language codes for Hebrew, Yiddish, and Indonesian are no longer converted to their obsolete forms (Hebrew: iw, Yiddish: ji, and Indonesian: in). When specifying the language code for one of these locales, use the codes from ISO 639-1 instead (Hebrew: he, Yiddish: yi, and Indonesian: id).

  • Changes to random int sequences: Following the changes made in https://bugs.openjdk.org/browse/JDK-8301574, the following Random.ints() methods now return a different sequence of numbers than the Random.nextInt() methods do:

    Generally, this change shouldn't result in app-breaking behavior, but your code shouldn't expect the sequence generated from Random.ints() methods to match Random.nextInt().

The new SequencedCollection API can affect your app's compatibility after you update compileSdk in your app's build configuration to use Android 15 (API level 35):

  • Collision with MutableList.removeFirst() and MutableList.removeLast() extension functions in kotlin-stdlib

    The List type in Java is mapped to the MutableList type in Kotlin. Because the List.removeFirst() and List.removeLast() APIs have been introduced in Android 15 (API level 35), the Kotlin compiler resolves function calls, for example list.removeFirst(), statically to the new List APIs instead of to the extension functions in kotlin-stdlib.

    If an app is re-compiled with compileSdk set to 35 and minSdk set to 34 or lower, and then the app is run on Android 14 and lower, a runtime error is thrown:

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

    The existing NewApi lint option in Android Gradle Plugin can catch these new API usages.

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

    To fix the runtime exception and lint errors, the removeFirst() and removeLast() function calls can be replaced with removeAt(0) and removeAt(list.lastIndex) respectively in Kotlin. If you're using Android Studio Ladybug | 2024.1.3 or higher, it also provides a quick fix option for these errors.

    Consider removing @SuppressLint("NewApi") and lintOptions { disable 'NewApi' } if the lint option has been disabled.

  • Collision with other methods in Java

    New methods have been added into the existing types, for example, List and Deque. These new methods might not be compatible with the methods with the same name and argument types in other interfaces and classes. In the case of a method signature collision with incompatibility, the javac compiler outputs a build-time error. For example:

    Example error 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
    

    Example error 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
    

    Example 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
    

    To fix these build errors, the class implementing these interfaces should override the method with a compatible return type. For example:

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

安全性

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

受限 TLS 版本

Android 15 限制了对 TLS 版本 1.0 和 1.1 的使用。这些版本之前已在 Android 中被弃用,但现在不允许面向 Android 15 的应用使用。

安全的背景活動啟動

Android 15 可保护用户免受恶意应用的侵害,并让用户更好地控制 来防止恶意后台应用 将其他应用置于前台、提升其权限以及滥用 用户互动自以下时间以来,后台活动启动一直受到限制 Android 10(API 级别 29)。

禁止与堆栈中的顶部 UID 不匹配的应用启动 activity

恶意应用可以在同一任务中启动另一个应用的 activity,然后 叠加在上面,营造出像该应用一样的错觉。这个“任务” 劫持"攻击绕过了当前的后台启动限制, 会发生在同一个可见任务中。为了降低这种风险,Android 15 新增了 用于阻止与堆栈中的顶层 UID 不匹配的应用启动的标志 活动。如需选择启用应用的所有活动,请更新 allowCrossUidActivitySwitchFromBelow 属性:AndroidManifest.xml

<application android:allowCrossUidActivitySwitchFromBelow="false" >

如果满足以下所有条件,则启用新的安全措施:

  • 执行启动的应用以 Android 15 为目标平台。
  • 任务堆栈顶部的应用以 Android 15 为目标平台。
  • 所有可见活动都已选择启用新保护措施

如果启用了安全措施,应用可能会返回主屏幕,而不是返回 最后一个可见应用(如果他们自行完成任务)。

其他变更

除了限制 UID 匹配之外,这些其他变更也 包括:

  • 更改 PendingIntent 创作者,以阻止后台活动启动,具体方法是: 默认。这有助于防止应用意外创建 可能被恶意操作者滥用的 PendingIntent
  • 请勿将应用调到前台,除非 PendingIntent 发送者 允许它。此变更旨在防止恶意应用滥用 在后台启动 activity 的功能。默认情况下,应用 允许将任务堆栈转到前台,除非创建者允许 后台活动启动权限或发送者有后台活动 启动权限
  • 控制任务堆栈的顶层 activity 完成其任务的方式。如果 顶层 activity 完成一项任务后,Android 会返回到之前执行的 上次活动时间。此外,如果非顶层 activity 完成其任务,Android 将 返回主屏幕;因此不会阻碍这个非顶层的 活动。
  • 防止将其他应用中的任意 activity 启动到您自己的 activity 任务。这项变更旨在防止恶意应用 看起来像是来自其他应用的活动
  • 禁止将不可见窗口视为后台活动 发布。这有助于防止恶意应用滥用后台 activity 来向用户显示不需要或恶意的内容。

更安全的意圖

Android 15 引入了新的可选安全措施,以提高 intent 的安全性和稳健性。这些变更旨在防止潜在的漏洞以及恶意应用可能利用的 intent 滥用行为。Android 15 对 intent 的安全性进行了两项主要改进:

  • 与目标 intent 过滤器匹配:定位到特定组件的 intent 必须与目标的 intent 过滤器规范完全匹配。如果您发送 intent 来启动其他应用的 activity,目标 intent 组件需要与接收 activity 声明的 intent 过滤器保持一致。
  • intent 必须具有操作:没有操作的 intent 将不再与任何 intent 过滤器匹配。这意味着,用于启动 activity 或服务的 intent 必须具有明确定义的操作。

如需检查您的应用对这些更改的响应方式,请在应用中使用 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 中与窗口内边距相关的两项变更:默认强制执行边到边,此外还有配置变更,例如系统栏的默认配置。

全面实施政策

Apps are edge-to-edge by default on devices running Android 15 if the app is targeting Android 15 (API level 35).

An app that targets Android 14 and is not edge-to-edge on an Android 15 device.


An app that targets Android 15 (API level 35) and is edge-to-edge on an Android 15 device. This app mostly uses Material 3 Compose Components that automatically apply insets. This screen is not negatively impacted by the Android 15 edge-to-edge enforcement.

This is a breaking change that might negatively impact your app's UI. The changes affect the following UI areas:

  • Gesture handle navigation bar
    • Transparent by default.
    • Bottom offset is disabled so content draws behind the system navigation bar unless insets are applied.
    • setNavigationBarColor and R.attr#navigationBarColor are deprecated and don't affect gesture navigation.
    • setNavigationBarContrastEnforced and R.attr#navigationBarContrastEnforced continue to have no effect on gesture navigation.
  • 3-button navigation
    • Opacity set to 80% by default, with color possibly matching the window background.
    • Bottom offset disabled so content draws behind the system navigation bar unless insets are applied.
    • setNavigationBarColor and R.attr#navigationBarColor are set to match the window background by default. The window background must be a color drawable for this default to apply. This API is deprecated but continues to affect 3-button navigation.
    • setNavigationBarContrastEnforced and R.attr#navigationBarContrastEnforced is true by default, which adds an 80% opaque background across 3-button navigation.
  • Status bar
    • Transparent by default.
    • The top offset is disabled so content draws behind the status bar unless insets are applied.
    • setStatusBarColor and R.attr#statusBarColor are deprecated and have no effect on Android 15.
    • setStatusBarContrastEnforced and R.attr#statusBarContrastEnforced are deprecated but still have an effect on Android 15.
  • Display cutout
    • layoutInDisplayCutoutMode of non-floating windows must be LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS. SHORT_EDGES, NEVER, and DEFAULT are interpreted as ALWAYS so that users don't see a black bar caused by the display cutout and appear edge-to-edge.

The following example shows an app before and after targeting Android 15 (API level 35), and before and after applying insets.

An app that targets Android 14 and is not edge-to-edge on an Android 15 device.
An app that targets Android 15 (API level 35) and is edge-to-edge on an Android 15 device. However, many elements are now hidden by the status bar, 3-button navigation bar, or display cutout due to the Android 15 edge-to-edge enforcements. Hidden UI includes the Material 2 top app bar, floating action buttons, and list items.
An app that targets Android 15 (API level 35), is edge to edge on an Android 15 device and applies insets so that UI is not hidden.
What to check if your app is already edge-to-edge

If your app is already edge-to-edge and applies insets, you are mostly unimpacted, except in the following scenarios. However, even if you think you aren't impacted, we recommend you test your app.

  • You have a non-floating window, such as an Activity that uses SHORT_EDGES, NEVER or DEFAULT instead of LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS. If your app crashes on launch, this might be due to your splashscreen. You can either upgrade the core splashscreen dependency to 1.2.0-alpha01 or later or set window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always.
  • There might be lower-traffic screens with occluded UI. Verify these less-visited screens don't have occluded UI. Lower-traffic screens include:
    • Onboarding or sign-in screens
    • Settings pages
What to check if your app is not already edge-to-edge

If your app is not already edge-to-edge, you are most likely impacted. In addition to the scenarios for apps that are already edge-to-edge, you should consider the following:

  • If your app uses Material 3 Components ( androidx.compose.material3) in compose, such as TopAppBar, BottomAppBar, and NavigationBar, these components are likely not impacted because they automatically handle insets.
  • If your app is using Material 2 Components ( androidx.compose.material) in Compose, these components don't automatically handle insets. However, you can get access to the insets and apply them manually. In androidx.compose.material 1.6.0 and later, use the windowInsets parameter to apply the insets manually for BottomAppBar, TopAppBar, BottomNavigation, and NavigationRail. Likewise, use the contentWindowInsets parameter for Scaffold.
  • If your app uses views and Material Components (com.google.android.material), most views-based Material Components such as BottomNavigationView, BottomAppBar, NavigationRailView, or NavigationView, handle insets and require no additional work. However, you need to add android:fitsSystemWindows="true" if using AppBarLayout.
  • For custom composables, apply the insets manually as padding. If your content is within a Scaffold, you can consume insets using the Scaffold padding values. Otherwise, apply padding using one of the WindowInsets.
  • If your app is using views and BottomSheet, SideSheet or custom containers, apply padding using ViewCompat.setOnApplyWindowInsetsListener. For RecyclerView, apply padding using this listener and also add clipToPadding="false".
What to check if your app must offer custom background protection

If your app must offer custom background protection to 3-button navigation or the status bar, your app should place a composable or view behind the system bar using WindowInsets.Type#tappableElement() to get the 3-button navigation bar height or WindowInsets.Type#statusBars.

Additional edge-to-edge resources

See the Edge to Edge Views and Edge to Edge Compose guides for additional considerations on applying insets.

Deprecated APIs

The following APIs are deprecated but not disabled:

The following APIs are deprecated and disabled:

稳定配置

如果您的应用以 Android 15(API 级别 35)或更高版本为目标平台,Configuration 不再排除系统栏。如果您使用 Configuration 类中的屏幕尺寸进行布局计算,则应根据需要将其替换为更好的替代方案,例如适当的 ViewGroupWindowInsetsWindowMetricsCalculator

Configuration 从 API 1 开始提供。它通常从 Activity.onConfigurationChanged 中获取。它提供窗口密度、屏幕方向和尺寸等信息。从 Configuration 返回的窗口大小的一个重要特征是,它之前会排除系统栏。

配置大小通常用于资源选择(例如 /res/layout-h500dp),这仍然是一个有效的用例。不过,我们一直不建议将其用于布局计算。如果您在使用此功能,请立即停止使用。您应根据自己的用例,将 Configuration 的使用替换为更合适的用法。

如果您使用它来计算布局,请使用适当的 ViewGroup,例如 CoordinatorLayoutConstraintLayout。如果您使用它来确定系统侧边栏的高度,请使用 WindowInsets。如果您想知道应用窗口的当前大小,请使用 computeCurrentWindowMetrics

以下列表介绍了受此变更影响的字段:

elegantTextHeight 屬性預設值為 true

对于以 Android 15(API 级别 35)为目标平台的应用,elegantTextHeight TextView 属性默认会变为 true,将默认使用的紧凑字体替换为一些具有较大垂直测量的脚本,使其更易于阅读。紧凑字体旨在防止布局中断;Android 13(API 级别 33)允许文本布局利用 fallbackLineSpacing 属性拉伸垂直高度,从而防止许多此类中断。

在 Android 15 中,系统中仍保留了紧凑字体,因此您的应用可以将 elegantTextHeight 设置为 false 以获得与之前相同的行为,但即将发布的版本不太可能支持此字体。因此,如果您的应用支持以下脚本:阿拉伯语、老挝语、缅甸语、泰米尔语、古吉拉特语、卡纳达语、马拉雅拉姆语、奥里亚语、泰卢固语或泰语,请将 elegantTextHeight 设置为 true 以测试您的应用。

针对以 Android 14(API 级别 34)及更低版本为目标平台的应用的 elegantTextHeight 行为。
以 Android 15 为目标平台的应用的 elegantTextHeight 行为。

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

In previous versions of Android, some cursive fonts or languages that have complex shaping might draw the letters in the previous or next character's area. In some cases, such letters were clipped at the beginning or ending position. Starting in Android 15, a TextView allocates width for drawing enough space for such letters and allows apps to request extra paddings to the left to prevent clipping.

Because this change affects how a TextView decides the width, TextView allocates more width by default if the app targets Android 15 (API level 35) or higher. You can enable or disable this behavior by calling the setUseBoundsForWidth API on TextView.

Because adding left padding might cause a misalignment for existing layouts, the padding is not added by default even for apps that target Android 15 or higher. However, you can add extra padding to preventing clipping by calling setShiftDrawingOffsetForStartOverhang.

The following examples show how these changes can improve text layout for some fonts and languages.

Standard layout for English text in a cursive font. Some of the letters are clipped. Here is the corresponding XML:

<TextView
    android:fontFamily="cursive"
    android:text="java" />
Layout for the same English text with additional width and padding. Here is the corresponding XML:

<TextView
    android:fontFamily="cursive"
    android:text="java"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />
Standard layout for Thai text. Some of the letters are clipped. Here is the corresponding XML:

<TextView
    android:text="คอมพิวเตอร์" />
Layout for the same Thai text with additional width and padding. Here is the corresponding XML:

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

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

In previous versions of Android, the text layout stretched the height of the text to meet the line height of the font that matched the current locale. For example, if the content was in Japanese, because the line height of the Japanese font is slightly larger than the one of a Latin font, the height of the text became slightly larger. However, despite these differences in line heights, the EditText element was sized uniformly, regardless of the locale being used, as illustrated in the following image:

Three boxes representing EditText elements that can contain text from English (en), Japanese (ja), and Burmese (my). The height of the EditText is the same, even though these languages have different line heights from each other.

For apps targeting Android 15 (API level 35), a minimum line height is now reserved for EditText to match the reference font for the specified Locale, as shown in the following image:

Three boxes representing EditText elements that can contain text from English (en), Japanese (ja), and Burmese (my). The height of the EditText now includes space to accommodate the default line height for these languages' fonts.

If needed, your app can restore the previous behavior by specifying the useLocalePreferredLineHeightForMinimum attribute to false, and your app can set custom minimum vertical metrics using the setMinimumFontMetrics API in Kotlin and Java.

相機和媒體

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

要求音訊焦點的限制

以 Android 15(API 级别 35)为目标平台的应用必须是顶部应用或正在运行前台服务,才能请求音频焦点。如果应用在未满足上述任一要求的情况下尝试请求焦点,调用将返回 AUDIOFOCUS_REQUEST_FAILED

如需详细了解音频焦点,请参阅管理音频焦点

更新非 SDK 限制

Android 15 包含更新后的受限非 SDK 接口列表(基于与 Android 开发者之间的协作以及最新的内部测试)。在限制使用非 SDK 接口之前,我们会尽可能确保有可用的公开替代方案。

如果您的应用并非以 Android 15 为目标平台,其中一些变更可能不会立即对您产生影响。不过,虽然您的应用可以访问一些非 SDK 接口(具体取决于应用的目标 API 级别),但如果您使用任何非 SDK 方法或字段,应用无法运行的风险始终会很高。

如果您不确定自己的应用是否使用了非 SDK 接口,则可以测试该应用,进行确认。如果您的应用依赖于非 SDK 接口,您应该开始计划迁移到 SDK 替代方案。不过,我们知道某些应用具有使用非 SDK 接口的有效用例。如果您无法为应用中的某项功能找到使用非 SDK 接口的替代方案,则应请求新的公共 API

如需详细了解此 Android 版本中的变更,请参阅 Android 15 中有关限制非 SDK 接口的更新。如需全面了解有关非 SDK 接口的详细信息,请参阅对非 SDK 接口的限制