Al igual que las versiones anteriores, Android 15 incluye cambios de comportamiento que podrían afectar a tu app. Los siguientes cambios se aplican exclusivamente a las apps orientadas a Android 15 o versiones posteriores. Si tu app está orientada a Android 15 o versiones posteriores, debes modificarla para que admita estos comportamientos correctamente, cuando corresponda.
Asegúrate de revisar también la lista de cambios de comportamiento que afectan a todas las apps que se ejecutan en Android 15, independientemente de la targetSdkVersion
de tu app.
Funcionalidad principal
Android 15 modifica o expande varias capacidades principales del sistema Android.
Cambios en los servicios en primer plano
Realizaremos los siguientes cambios en los servicios en primer plano con Android 15.
- Nuevo tipo de servicio en primer plano de procesamiento de contenido multimedia
- Restricciones sobre los receptores de emisión de
BOOT_COMPLETED
que inician servicios en primer plano
Comportamiento del tiempo de espera del servicio en primer plano de sincronización de datos
Android 15 对于以 Android 15 或更高版本为目标平台的应用,在 dataSync
中引入了新的超时行为。此行为也适用于新的 mediaProcessing
前台服务类型。
系统允许应用的 dataSync
服务在 24 小时内运行总共 6 小时,之后系统会调用正在运行的服务的 Service.onTimeout(int, int)
方法(在 Android 15 中引入)。此时,服务只有几秒钟的时间来调用 Service.stopSelf()
。当调用 Service.onTimeout()
时,该服务不再被视为前台服务。如果服务未调用 Service.stopSelf()
,则会发生故障,并显示以下错误消息:“A for 前台服务 (<fgs_type> does not stop in their timeout:
<component_name>)”。在 Beta 版 2 中,失败消息显示为 ANR,但在未来的 Beta 版中,此失败消息将抛出自定义异常。
为避免此行为变更出现问题,您可以执行以下一项或多项操作:
- 让您的服务实现新的
Service.onTimeout(int, int)
方法。当应用收到回调时,请确保在几秒钟内调用stopSelf()
。(如果您没有立即停止应用,系统会生成故障。) - 确保应用的
dataSync
服务在任何 24 小时内的运行时间总共不超过 6 小时(除非用户与应用互动,请重置计时器)。 - 仅因直接用户互动而启动
dataSync
前台服务;由于您的应用在服务启动时正处于前台,因此在它进入后台后,您的服务有整整六个小时的时间。 - 请使用替代 API,而不要使用
dataSync
前台服务。
如果应用的 dataSync
前台服务在过去 24 小时内运行了 6 小时,那么除非用户已将您的应用带到前台(这会重置计时器),否则您无法启动其他 dataSync
前台服务。如果您尝试启动另一个 dataSync
前台服务,系统会抛出 ForegroundServiceStartNotAllowedException
,并显示“时间限制已用完前台服务类型 dataSync 的时间限制”这样的错误消息。
Nuevo tipo de servicio en primer plano de procesamiento de contenido multimedia
Android 15 presenta un nuevo tipo de servicio en primer plano, mediaProcessing
. Este tipo de servicio es adecuado para operaciones como la transcodificación de archivos multimedia. Por ejemplo, una app de música podría descargar un archivo de audio y necesitar convertirlo a un formato diferente antes de reproducirlo. Puedes usar un servicio en primer plano mediaProcessing
para asegurarte de que la conversión continúe incluso mientras la app se encuentra en segundo plano.
El sistema permite que se ejecuten los servicios mediaProcessing
de una app durante un total de 6 horas en un período de 24 horas, después de lo cual llama al método Service.onTimeout(int, int)
del servicio en ejecución (presentado en Android 15). En este momento, el servicio tiene unos segundos para llamar a Service.stopSelf()
. Si el servicio no llama a Service.stopSelf()
, se producirá un error con este mensaje de error: "Un servicio en primer plano de <fgs_type> no se detuvo durante el tiempo de espera: <component_name>". En la versión beta 2, el mensaje de error se muestra como un error de ANR, pero, en una versión beta futura, este mensaje de error arrojará una excepción personalizada.
Para evitar recibir un error de ANR, puedes realizar una de las siguientes acciones:
- Haz que tu servicio implemente el nuevo método
Service.onTimeout(int, int)
. Cuando tu app reciba la devolución de llamada, asegúrate de llamar astopSelf()
en unos pocos segundos. (Si no detienes la app de inmediato, el sistema generará una falla). - Asegúrate de que los servicios de
mediaProcessing
de tu app no se ejecuten durante más de un total de 6 horas en cualquier período de 24 horas (a menos que el usuario interactúe con la app y restablezca el temporizador). - Solo inicia los servicios en primer plano
mediaProcessing
como resultado de la interacción directa del usuario. Como tu app se encuentra en primer plano cuando se inicia el servicio, este tiene las seis horas completas una vez que la app pasa a segundo plano. - En lugar de usar un servicio en primer plano de
mediaProcessing
, usa una API alternativa, como WorkManager.
Si los servicios en primer plano de mediaProcessing
de tu app se ejecutaron durante 6 horas durante las últimas 24, no podrás iniciar otro servicio en primer plano de mediaProcessing
a menos que el usuario haya llevado la app al primer plano (lo que restablece el temporizador). Si intentas iniciar otro servicio en primer plano mediaProcessing
, el sistema arrojará una ForegroundServiceStartNotAllowedException
con un mensaje de error, como “Ya se agotó el tiempo límite para el tipo de servicio en primer plano mediaProcessing”.
Para obtener más información sobre el tipo de servicio mediaProcessing
, consulta Cambios en los tipos de servicios en primer plano para Android 15: Procesamiento de contenido multimedia.
Restricciones en los receptores de emisión de BOOT_COMPLETED
que inician servicios en primer plano
Hay nuevas restricciones en los receptores de emisión de BOOT_COMPLETED
que inician servicios en primer plano. Los receptores BOOT_COMPLETED
no tienen permitido iniciar los siguientes tipos de servicios en primer plano:
dataSync
camera
mediaPlayback
phoneCall
mediaProjection
microphone
(esta restricción se aplica amicrophone
desde Android 14)
Si un receptor BOOT_COMPLETED
intenta iniciar cualquiera de esos tipos de servicios en primer plano, el sistema arrojará ForegroundServiceStartNotAllowedException
.
Restricciones para el inicio de servicios en primer plano mientras una app conserva el permiso SYSTEM_ALERT_WINDOW
以前,如果应用拥有 SYSTEM_ALERT_WINDOW
权限,那么即使该应用当前在后台运行,它也可以启动前台服务(如不受后台启动限制的豁免中所述)。
如果应用以 Android 15 为目标平台,此豁免范围现在会更严格。该应用现在需要具有 SYSTEM_ALERT_WINDOW
权限,并且还具有可见的叠加窗口。也就是说,在您启动前台服务之前,应用需要先启动 TYPE_APPLICATION_OVERLAY
窗口,并且该窗口必须处于可见状态。
如果您的应用尝试在不满足这些新要求的情况下从后台启动前台服务(并且没有其他某些豁免),系统会抛出 ForegroundServiceStartNotAllowedException
。
如果您的应用声明 SYSTEM_ALERT_WINDOW
权限并从后台启动前台服务,则可能会受到此项变更的影响。如果您的应用收到 ForegroundServiceStartNotAllowedException
,请检查应用的操作顺序,并确保应用在尝试从后台启动前台服务之前已具备有效的叠加窗口。您可以通过调用 View.getWindowVisibility()
检查叠加层窗口当前是否可见,也可以替换 View.onWindowVisibilityChanged()
,以便在可见性发生变化时收到通知。
Cambios en la capacidad de las apps para modificar el estado global del modo No interrumpir
Las apps orientadas a Android 15 ya no pueden cambiar el estado global ni la política de No interrumpir (No interrumpir) en un dispositivo (ya sea modificando la configuración del usuario o desactivando el modo No interrumpir). En cambio, las apps deben aportar un AutomaticZenRule
, que el sistema combina en una política global con el esquema existente más restrictivo de la política. Las llamadas a las APIs existentes que anteriormente afectaron el estado global (setInterruptionFilter
, setNotificationPolicy
) generan la creación o actualización de un AutomaticZenRule
implícito, que se activa y desactiva según el ciclo de llamadas de esas llamadas a la API.
Ten en cuenta que este cambio solo afecta el comportamiento observable si la app llama a setInterruptionFilter(INTERRUPTION_FILTER_ALL)
y espera que esa llamada desactive una AutomaticZenRule
que sus propietarios hayan activado.
Cambios en OpenJDK 17
Android 15 continúa la tarea de actualizar las bibliotecas principales de Android para alinearlas con las funciones de las versiones más recientes de LTS de OpenJDK.
Uno de estos cambios puede afectar la compatibilidad de las apps orientadas a Android 15:
Cambios en las APIs de formato de cadenas: La validación del índice de los argumentos, las marcas, el ancho y la precisión ahora son más estrictas cuando se usan las siguientes APIs de
String.format()
yFormatter.format()
:String.format(String, Object[])
String.format(Locale, String, Object[])
Formatter.format(String, Object[])
Formatter.format(Locale, String, Object[])
Por ejemplo, se arroja la siguiente excepción cuando se usa un índice de argumento 0 (
%0
en la cadena de formato):IllegalFormatArgumentIndexException: Illegal format argument index = 0
En este caso, el problema se puede solucionar con un índice de argumento 1 (
%1
en la cadena de formato).Cambios en el tipo de componente de
Arrays.asList(...).toArray()
: Cuando se usaArrays.asList(...).toArray()
, el tipo de componente del array resultante ahora es unObject
, no el tipo de los elementos del array subyacente. Por lo tanto, el siguiente código arroja unaClassCastException
:String[] elements = (String[]) Arrays.asList("one", "two").toArray();
En este caso, para preservar
String
como el tipo de componente en el array resultante, puedes usarCollection.toArray(Object[])
en su lugar:String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
Cambios en el manejo del código de idioma: Cuando se usa la API de
Locale
, los códigos de idioma para hebreo, indonesio y yidis ya no se convierten a sus formas obsoletas (hebreo:iw
, yiddish:ji
e indonesio:in
). Cuando se especifica el código de idioma de una de estas configuraciones regionales, usa los códigos de ISO 639-1 (hebreo:he
, yidis:yi
0 e indonesio}).id
Cambios en secuencias int aleatorias: Después de los cambios realizados en https://bugs.openjdk.org/browse/JDK-8301574, los siguientes métodos
Random.ints()
ahora muestran una secuencia de números diferente a la de los métodosRandom.nextInt()
:En general, este cambio no debería causar un comportamiento irreversible en la app, pero tu código no debería esperar que la secuencia generada a partir de los métodos
Random.ints()
coincida conRandom.nextInt()
.
Seguridad
Android 15 incluye cambios que promueven la seguridad del sistema para proteger a los usuarios y las apps de apps maliciosas.
Lanzamientos seguros de actividades en segundo plano
Android 15 通过添加变更来防止恶意后台应用将其他应用带到前台、提升其权限和滥用用户互动,从而保护用户免受恶意应用的侵害,并使用户能够更好地控制其设备。从 Android 10(API 级别 29)开始,后台 activity 启动已受到限制。
阻止与堆栈中顶部 UID 不匹配的应用启动 activity
恶意应用可以在同一任务内启动另一个应用的 activity,然后叠加在上面,制造出作为该应用的错觉。这种“任务劫持”攻击绕过了当前的后台启动限制,因为它都发生在同一可见任务内。为了降低这种风险,Android 15 添加了一个标志,用于阻止与堆栈上的顶级 UID 不匹配的应用启动 activity。如需选择启用应用的所有 activity,请更新应用的 AndroidManifest.xml
文件中的 allowCrossUidActivitySwitchFromBelow
属性:
<application android:allowCrossUidActivitySwitchFromBelow="false" >
如果满足以下所有条件,则新的安全措施就会生效:
- 执行启动的应用以 Android 15 为目标平台。
- 任务堆栈顶部的应用以 Android 15 为目标平台。
- 所有可见的活动均已启用新版保护措施
如果启用了安全措施,应用如果完成自己的任务,可能会返回主屏幕,而不是返回上一个可见的应用。
其他变更
除了 UID 匹配的限制之外,还包含以下其他更改:
- 将
PendingIntent
创建者更改为默认阻止后台 activity 启动。这有助于防止应用意外创建可能会被恶意操作者滥用的PendingIntent
。 - 请勿将应用置于前台,除非
PendingIntent
发送者允许该应用。此变更旨在防止恶意应用滥用在后台启动 activity 的功能。默认情况下,不允许应用将任务堆栈置于前台,除非创建者允许后台 activity 启动特权或发送者具有后台 activity 启动特权。 - 控制任务堆栈的顶层 activity 完成其任务的方式。如果顶层 activity 完成某项任务,Android 会返回到上次处于活动状态的任务。此外,如果非顶层 activity 完成其任务,Android 将返回主屏幕;它不会阻止此非顶部 activity 的完成。
- 防止将其他应用中的任意 activity 启动到您自己的任务中。这项变更会通过创建看似来自其他应用的活动,防止恶意应用向用户进行钓鱼式攻击。
- 阻止系统考虑将不可见窗口用于后台 activity 启动。这有助于防止恶意应用滥用后台 activity 启动来向用户显示不受欢迎或恶意内容。
Intents más seguros
Android 15 introduces new security measures to make intents safer and more robust. These changes are aimed at preventing potential vulnerabilities and misuse of intents that can be exploited by malicious apps. There are two main improvements to the security of intents in Android 15:
- Match target intent-filters: Intents that target specific components must accurately match the target's intent-filter specifications. If you send an intent to launch another app's activity, the target intent component needs to align with the receiving activity's declared intent-filters.
- Intents must have actions: Intents without an action will no longer match any intent-filters. This means that intents used to start activities or services must have a clearly defined action.
Kotlin
fun onCreate() { StrictMode.setVmPolicy(VmPolicy.Builder() .detectUnsafeIntentLaunch() .build() ) }
Java
public void onCreate() { StrictMode.setVmPolicy(new VmPolicy.Builder() .detectUnsafeIntentLaunch() .build()); }
IU del sistema y experiencia del usuario
Android 15 incluye algunos cambios destinados a crear una experiencia del usuario más intuitiva y coherente.
Cambios en la inserción de ventana
Hay dos cambios relacionados con las inserciones de ventana en Android 15: de borde a borde se aplica de forma predeterminada, y también hay cambios de configuración, como la configuración predeterminada de las barras del sistema.
Aplicación de borde a borde
Las apps son de borde a borde de forma predeterminada en dispositivos que ejecutan Android 15 si están orientadas a esta versión.
Este es un cambio rotundo que podría afectar de forma negativa la IU de tu app. Los cambios afectan las siguientes áreas de la IU:
- Barra de navegación del controlador de gestos
- Es transparente de forma predeterminada.
- El desplazamiento inferior está inhabilitado, por lo que el contenido se dibuja detrás de la barra de navegación del sistema, a menos que se apliquen inserciones.
setNavigationBarColor
yR.attr#navigationBarColor
dejaron de estar disponibles y no afectan la navegación por gestos.setNavigationBarContrastEnforced
yR.attr#navigationBarContrastEnforced
continúan sin tener efecto en la navegación por gestos.
- Navegación con 3 botones
- La opacidad se establece en un 80% de forma predeterminada y es posible que el color coincida con el fondo de la ventana.
- El desplazamiento inferior está inhabilitado para que el contenido se dibuje detrás de la barra de navegación del sistema, a menos que se apliquen inserciones.
setNavigationBarColor
yR.attr#navigationBarColor
están configurados para coincidir con el fondo de la ventana de forma predeterminada. El fondo de la ventana debe ser un elemento de diseño de color para que se aplique este valor predeterminado. Esta API dejó de estar disponible, pero sigue afectando la navegación con 3 botones.setNavigationBarContrastEnforced
yR.attr#navigationBarContrastEnforced
son verdaderos de forma predeterminada, lo que agrega un 80% de fondo opaco en la navegación con 3 botones.
- Barra de estado
- Es transparente de forma predeterminada.
- El desplazamiento superior está inhabilitado para que el contenido se dibuje detrás de la barra de estado, a menos que se apliquen las inserciones.
setStatusBarColor
yR.attr#statusBarColor
dejaron de estar disponibles y no tienen efecto en Android 15.setStatusBarContrastEnforced
yR.attr#statusBarContrastEnforced
dejaron de estar disponibles, pero aún tienen efecto en Android 15.
- Recorte de pantalla
- El
layoutInDisplayCutoutMode
de las ventanas no flotantes debe serLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
.SHORT_EDGES
,NEVER
yDEFAULT
se interpretan comoALWAYS
para que los usuarios no vean una barra negra causada por el corte de la pantalla y aparezcan de borde a borde.
- El
En el siguiente ejemplo, se muestra una app antes y después de orientarla a Android 15, y antes y después de aplicar las inserciones.
Qué debes verificar si tu app ya es de borde a borde
Si tu app ya es de borde a borde y aplica inserciones, no se verá afectada en la mayoría de los casos, excepto en las siguientes situaciones. Sin embargo, incluso si crees que no te verás afectado, te recomendamos que pruebes la app.
- Tienes una ventana no flotante, como un
Activity
que usaSHORT_EDGES
,NEVER
oDEFAULT
en lugar deLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
. Si tu app falla durante el inicio, es posible que se deba a la pantalla de presentación. Puedes actualizar la dependencia de la pantalla de presentación principal a 1.2.0-alpha01 o una versión posterior, o bien configurarwindow.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always
. - Es posible que haya pantallas con poco tráfico y una IU oculta. Verifica que estas pantallas menos visitadas no tengan una IU oculta. Estas son las pantallas con menor tráfico:
- Pantallas de integración o acceso
- Páginas de configuración
Qué debes verificar si tu app aún no es de borde a borde
Si tu app aún no es de borde a borde, es muy probable que este te afecte. Además de las situaciones de apps que ya son de borde a borde, debes tener en cuenta lo siguiente:
- Si tu app usa componentes de Material 3 (
androidx.compose.material3
) en Compose, comoTopAppBar
,BottomAppBar
yNavigationBar
, es probable que estos componentes no se vean afectados porque controlan las inserciones automáticamente. - Si tu app usa componentes de Material 2 (
androidx.compose.material
) en Compose, estos componentes no controlan las inserciones automáticamente. Sin embargo, puedes obtener acceso a las inserciones y aplicarlas manualmente. En androidx.compose.material 1.6.0 y versiones posteriores, usa el parámetrowindowInsets
para aplicar las inserciones manualmente paraBottomAppBar
,TopAppBar
,BottomNavigation
yNavigationRail
. Del mismo modo, usa el parámetrocontentWindowInsets
paraScaffold
. - Si tu app usa vistas y componentes de Material (
com.google.android.material
), la mayoría de los componentes de Material basados en vistas, comoBottomNavigationView
,BottomAppBar
,NavigationRailView
oNavigationView
, controlan las inserciones y no requieren trabajo adicional. Sin embargo, debes agregarandroid:fitsSystemWindows="true"
si usasAppBarLayout
. - En el caso de los elementos componibles personalizados, aplica las inserciones de forma manual como padding. Si tu contenido está dentro de un
Scaffold
, puedes consumir las inserciones con los valores de padding deScaffold
. De lo contrario, aplica padding mediante uno de losWindowInsets
. - Si la app usa vistas y
BottomSheet
,SideSheet
o contenedores personalizados, aplica padding conViewCompat.setOnApplyWindowInsetsListener
. ParaRecyclerView
, aplica padding con este objeto de escucha y también agregaclipToPadding="false"
.
Qué debes comprobar si tu app debe ofrecer protección en segundo plano personalizada
Si tu app debe ofrecer una protección en segundo plano personalizada para la navegación con 3 botones o la barra de estado, debes colocar un elemento componible o una vista detrás de la barra del sistema con WindowInsets.Type#tappableElement()
para obtener la altura de la barra de navegación con 3 botones o WindowInsets.Type#statusBars
.
Recursos adicionales de borde a borde
Consulta las guías de vistas de borde a borde y vista de borde a borde para obtener consideraciones adicionales sobre la aplicación de inserciones.
APIs obsoletas
Las siguientes APIs dejaron de estar disponibles:
R.attr#enforceStatusBarContrast
R.attr#navigationBarColor
R.attr#navigationBarDividerColor
R.attr#statusBarColor
Window#getNavigationBarColor
Window#getNavigationBarDividerColor
Window#getStatusBarColor
Window#isStatusBarContrastEnforced
Window#setDecorFitsSystemWindows
Window#setNavigationBarColor
Window#setNavigationBarDividerColor
Window#setStatusBarColor
Window#setStatusBarContrastEnforced
Configuración estable
Si tu app se orienta a Android 15 o versiones posteriores, Configuration
ya no excluye las barras del sistema. Si usas el tamaño de pantalla en la clase Configuration
para el cálculo del diseño, debes reemplazarlo por alternativas mejores, como ViewGroup
, WindowInsets
o WindowMetricsCalculator
, según tus necesidades.
Configuration
está disponible desde la API 1. Por lo general, se obtiene de Activity.onConfigurationChanged
. Proporciona información como la densidad, la orientación y los tamaños de las ventanas. Una característica importante sobre los tamaños de ventana que muestra Configuration
es que antes excluía las barras del sistema.
El tamaño de la configuración se suele usar para la selección de recursos, como /res/layout-h500dp
, y este sigue siendo un caso de uso válido. Sin embargo, siempre no se recomienda su uso para el cálculo del diseño. Si lo haces, debes dejar de hacerlo ahora. Debes reemplazar el uso de Configuration
por algo más adecuado según tu caso de uso.
Si la usas para calcular el diseño, utiliza un ViewGroup
apropiado, como CoordinatorLayout
o ConstraintLayout
. Si la usas para determinar la altura de la barra de navegación del sistema, utiliza WindowInsets
. Si deseas conocer el tamaño actual de la ventana de tu app, usa computeCurrentWindowMetrics
.
En la siguiente lista, se describen los campos afectados por este cambio:
- Los tamaños
Configuration.screenWidthDp
yscreenHeightDp
ya no excluyen las barras del sistema. Configuration.smallestScreenWidthDp
se ve afectado indirectamente por los cambios enscreenWidthDp
yscreenHeightDp
.Configuration.orientation
se ve afectada indirectamente por los cambios enscreenWidthDp
yscreenHeightDp
en dispositivos casi cuadrados.Display.getSize(Point)
se ve afectado indirectamente por los cambios enConfiguration
. Esta función dejó de estar disponible a partir del nivel de API 30.Display.getMetrics()
ya funciona de esta manera desde el nivel de API 33.
El atributo eleganteTextHeight se establece en verdadero de forma predeterminada.
En el caso de las apps orientadas a Android 15, el atributo TextView
elegantTextHeight
se convierte en true
de forma predeterminada, lo que reemplaza la fuente compacta de forma predeterminada con algunas secuencias de comandos que tienen métricas verticales grandes por una mucho más legible. La fuente compacta se introdujo para evitar diseños rotos. Android 13 (nivel de API 33) evita muchas de estas fallas permitiendo que el diseño de texto estire la altura vertical con el atributo fallbackLineSpacing
.
En Android 15, la fuente compacta aún permanece en el sistema, por lo que tu app puede establecer elegantTextHeight
en false
para obtener el mismo comportamiento que antes, pero es poco probable que se admita en próximas versiones. Por lo tanto, si tu app admite las siguientes secuencias de comandos: árabe, laosiano, Birmania, tamil, guyaratí, canarés, malabar, oriya, telugu o tailandés, configura elegantTextHeight
en true
para probar la app.
Cambios en el ancho de TextView para formas de letras complejas
在以前的 Android 版本中,一些采用复杂形状的草体字体或语言可能会在上一个或下一个字符区域中绘制字母。在某些情况下,此类字母会在开始或结束位置被截断。从 Android 15 开始,TextView
会分配宽度来为此类字母绘制足够的空间,并允许应用请求左侧添加额外的内边距以防止被裁剪。
由于此变更会影响 TextView
确定宽度的方式,因此如果应用以 Android 15 或更高版本为目标平台,TextView
会默认分配更多宽度。您可以通过对 TextView
调用 setUseBoundsForWidth
API 来启用或停用此行为。
由于添加左侧内边距可能会导致现有布局未对齐,因此默认情况下,系统不会添加内边距,即使对于以 Android 15 或更高版本为目标平台的应用也是如此。不过,您可以通过调用 setShiftDrawingOffsetForStartOverhang
添加额外的内边距以防止裁剪。
以下示例展示了这些更改如何改进某些字体和语言的文本布局。
Altura de línea predeterminada en función de la configuración regional para EditText
En las versiones anteriores de Android, el diseño de texto estiraba la altura del texto para cumplir con la altura de la línea de la fuente que coincidía con la configuración regional actual. Por ejemplo, si el contenido estaba en japonés, debido a que la altura de la línea de la fuente japonesa es ligeramente mayor que la de una fuente latina, la altura del texto se agrandó un poco más grande. Sin embargo, a pesar de estas diferencias en las alturas de las líneas, el tamaño del elemento EditText
se dimensionó de manera uniforme, independientemente de la configuración regional que se usara, como se ilustra en la siguiente imagen:
En el caso de las apps orientadas a Android 15, ahora se reserva una altura de línea mínima para que EditText
coincida con la fuente de referencia de la configuración regional especificada, como se muestra en la siguiente imagen:
Si es necesario, tu app puede restablecer el comportamiento anterior especificando el atributo useLocalePreferredLineHeightForMinimum
en false
, y tu app puede establecer métricas verticales mínimas personalizadas con la API de setMinimumFontMetrics
en Kotlin y Java.
Cámara y contenido multimedia
En Android 15, se realizan los siguientes cambios en el comportamiento de la cámara y el contenido multimedia para las apps orientadas a Android 15 o versiones posteriores.
Restricciones para solicitar foco de audio
Las apps orientadas a Android 15 deben ser la app principal o ejecutar un servicio en primer plano relacionado con el audio para solicitar el foco de audio. Si una app intenta solicitar el foco cuando no cumple con uno de estos requisitos, la llamada mostrará AUDIOFOCUS_REQUEST_FAILED
.
Un servicio en primer plano se considera relacionado con el audio si su tipo es mediaPlayback
, camera
, microphone
o phoneCall
.
Puedes obtener más información sobre el foco de audio en Cómo administrar el foco de audio.
Actualización de restricciones que no pertenecen al SDK
Android 15 incluye listas actualizadas de este tipo de interfaces que están basadas en la colaboración con desarrolladores de Android y las pruebas internas más recientes. Siempre que sea posible, nos aseguramos de que las alternativas públicas estén disponibles antes de restringir las interfaces que no pertenecen al SDK.
Si tu app no está orientada a Android 15, es posible que algunos de estos cambios no te afecten de inmediato. Sin embargo, aunque es posible que tu app acceda a algunas interfaces que no pertenecen al SDK según el nivel de API al que está orientada tu app, usar cualquier método o campo que no pertenece al SDK siempre implica un gran riesgo de error para tu app.
Si no sabes con certeza si tu app usa este tipo de interfaces, puedes probarla para averiguarlo. Si tu app depende de interfaces que no pertenecen al SDK, debes comenzar a planificar una migración hacia otras alternativas SDK. Sin embargo, sabemos que algunas apps tienen casos de uso válidos para usar interfaces que no pertenecen al SDK. Si no encuentras una alternativa para reemplazar el uso de una interfaz que no pertenece al SDK para una función de tu app, deberías solicitar una nueva API pública.
Para obtener más información sobre los cambios implementados en esta versión de Android, consulta Actualizaciones a las restricciones de interfaces que no pertenecen al SDK en Android 15. Para obtener más información sobre interfaces que no pertenecen al SDK en general, consulta Restricciones en interfaces que no pertenecen al SDK.