Como nas versões anteriores, o Android 15 inclui mudanças de comportamento que podem afetar seu app. As seguintes mudanças de comportamento se aplicam exclusivamente a apps destinados ao Android 15 ou mais recente. Caso seu app seja direcionado ao Android 15 ou a versões mais recentes, faça modificações para oferecer suporte a esses comportamentos de forma adequada, quando aplicável.
Consulte também a lista de mudanças de comportamento que afetam todos os apps
executados no Android 15, independente da targetSdkVersion
do app.
Principal recurso
O Android 15 modifica ou expande vários recursos principais do sistema Android.
Mudanças nos serviços em primeiro plano
We are making the following changes to foreground services with Android 15.
- Data sync foreground service timeout behavior
- New media processing foreground service type
- Restrictions on
BOOT_COMPLETED
broadcast receivers launching foreground services - Restrictions on starting foreground services while an app holds the
SYSTEM_ALERT_WINDOW
permission
Data sync foreground service timeout behavior
对于以 Android 15(API 级别 35)或更高版本为目标平台的应用,Android 15 为 dataSync
引入了新的超时行为。此行为也适用于新的 mediaProcessing
前台服务类型。
系统允许应用的 dataSync
服务在 24 小时内共运行 6 小时,之后系统会调用正在运行的服务的 Service.onTimeout(int, int)
方法(在 Android 15 中引入)。此时,服务有几秒钟的时间来调用 Service.stopSelf()
。调用 Service.onTimeout()
后,该服务将不再被视为前台服务。如果服务未调用 Service.stopSelf()
,系统会抛出内部异常。系统会在 Logcat 中记录此异常,并显示以下消息:
Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type dataSync did not stop within its timeout: [component name]"
为避免此行为变更出现问题,您可以执行以下一项或多项操作:
- 让您的服务实现新的
Service.onTimeout(int, int)
方法。当应用收到回调时,请务必在几秒钟内调用stopSelf()
。(如果您不立即停止应用,系统会生成故障。) - 确保应用的
dataSync
服务在任何 24 小时内总运行时间不超过 6 小时(除非用户与应用互动,重置计时器)。 - 仅在有直接用户互动时启动
dataSync
前台服务;由于服务启动时应用位于前台,因此您的服务在应用进入后台后有完整的 6 小时时间。 - 请使用替代 API,而不是使用
dataSync
前台服务。
如果您的应用的 dataSync
前台服务在过去 24 小时内运行了 6 小时,则您无法启动其他 dataSync
前台服务,除非用户已将您的应用切换到前台(这会重置计时器)。如果您尝试启动其他 dataSync
前台服务,系统会抛出 ForegroundServiceStartNotAllowedException
,并显示类似“前台服务类型 dataSync 的时间限制已用尽”的错误消息。
测试
如需测试应用的行为,即使您的应用并非以 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 data_sync_fgs_timeout_duration duration-in-milliseconds
New media processing foreground service type
O Android 15 apresenta um novo tipo de serviço em primeiro plano, mediaProcessing
. Esse
tipo de serviço é adequado para operações como transcodificação de arquivos de mídia. Por
exemplo, um app de mídia pode fazer o download de um arquivo de áudio e precisar convertê-lo para um
formato diferente antes de reproduzi-lo. Você pode usar um serviço em primeiro plano
mediaProcessing
para garantir que a conversão continue mesmo quando o app estiver em
segundo plano.
O sistema permite que os serviços mediaProcessing
de um app sejam executados por um total de 6
horas em um período de 24 horas. Depois disso, o sistema chama o método
Service.onTimeout(int, int)
do serviço em execução (introduzido no Android
15). Nesse momento, o serviço tem alguns segundos para chamar
Service.stopSelf()
. Se o serviço não
chamar Service.stopSelf()
, o sistema vai gerar uma exceção interna. A
exceção é registrada no Logcat com a seguinte mensagem:
Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type mediaProcessing did not stop within its timeout: [component name]"
Para evitar a exceção, siga um destes procedimentos:
- Faça com que o serviço implemente o novo método
Service.onTimeout(int, int)
. Quando o app receber o callback, chamestopSelf()
dentro de alguns segundos. Se você não interromper o app imediatamente, o sistema vai gerar uma falha. - Verifique se os serviços
mediaProcessing
do app não são executados por mais de um total de seis horas em qualquer período de 24 horas, a menos que o usuário interaja com o app, redefinindo o timer. - Só inicie serviços em primeiro plano
mediaProcessing
como resultado da interação direta do usuário. Como o app está em primeiro plano quando o serviço é iniciado, ele tem seis horas completas após o app ir para o segundo plano. - Em vez de usar um serviço em primeiro plano
mediaProcessing
, use uma API alternativa, como o WorkManager.
Se os serviços em primeiro plano mediaProcessing
do app tiverem sido executados por 6 horas nas
últimas 24 horas, não será possível iniciar outro serviço em primeiro plano mediaProcessing
a menos que
o usuário tenha trazido o app para o primeiro plano (o que redefine o timer). Se você
tentar iniciar outro serviço mediaProcessing
em primeiro plano, o sistema vai gerar
ForegroundServiceStartNotAllowedException
com uma mensagem de erro como "O limite de tempo já se esgotou para o tipo de serviço em primeiro plano
mediaProcessing".
Para mais informações sobre o tipo de serviço mediaProcessing
, consulte Mudanças nos
tipos de serviço em primeiro plano do Android 15: processamento de mídia.
Teste
Para testar o comportamento do app, ative os timeouts de processamento de mídia, mesmo que
o app não seja direcionado ao Android 15 (desde que esteja sendo executado em um
dispositivo Android 15). Para ativar os tempos limite, execute o seguinte comando adb
:
adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name
Você também pode ajustar o período de tempo limite para facilitar o teste do comportamento
do app quando o limite for atingido. Para definir um novo período de tempo limite, execute o
seguinte comando adb
:
adb shell device_config put activity_manager media_processing_fgs_timeout_duration duration-in-milliseconds
Restrictions on BOOT_COMPLETED
broadcast receivers launching foreground services
在启动 BOOT_COMPLETED
广播接收器方面存在新限制
前台服务。BOOT_COMPLETED
接收器不能启动
以下类型的前台服务:
dataSync
camera
mediaPlayback
phoneCall
mediaProjection
microphone
(自 Android 14 起,microphone
就受到此限制)
如果 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
Restrictions on starting foreground services while an app holds the SYSTEM_ALERT_WINDOW
permission
Anteriormente, se um app tivesse a permissão SYSTEM_ALERT_WINDOW
, ele poderia iniciar
um serviço em primeiro plano mesmo que estivesse em segundo plano (conforme
discutido em isenção de restrições de início em segundo plano).
Se um app for destinado ao Android 15, essa isenção será mais restrita. Agora o app precisa
ter a permissão SYSTEM_ALERT_WINDOW
e também ter uma janela de sobreposição
visível. Ou seja, o app precisa primeiro abrir uma
janela TYPE_APPLICATION_OVERLAY
e a janela
precisa estar visível antes de iniciar um serviço em primeiro plano.
Se o app tentar iniciar um serviço em primeiro plano em segundo plano sem
atender a esses novos requisitos (e não tiver outra isenção), o
sistema vai gerar uma ForegroundServiceStartNotAllowedException
.
Se o app declarar a permissão SYSTEM_ALERT_WINDOW
e iniciar serviços em primeiro plano em segundo plano, ele poderá ser afetado por essa
mudança. Se o app receber uma ForegroundServiceStartNotAllowedException
, verifique
a ordem das operações e verifique se ele já tem uma janela de sobreposição
ativa antes de tentar iniciar um serviço em primeiro plano em segundo
plano. Você pode conferir se a janela de sobreposição está visível
chamando View.getWindowVisibility()
ou
substituir View.onWindowVisibilityChanged()
para receber uma notificação sempre que a visibilidade mudar.
Teste
Para testar o comportamento do app, ative essas novas restrições mesmo que ele
não seja direcionado ao Android 15, desde que esteja sendo executado em um dispositivo
Android 15. Para ativar essas novas restrições na inicialização de serviços em primeiro plano
em segundo plano, execute este comando adb
:
adb shell am compat enable FGS_SAW_RESTRICTIONS your-package-name
Mudanças na hora em que os apps podem modificar o estado global do modo "Não perturbe"
以 Android 15 为目标平台的应用无法再更改设备上的全局状态或勿扰 (DND) 政策(通过修改用户设置或关闭 DND 模式)。相反,应用必须提供一个 AutomaticZenRule
,系统会将后者合并到一个具有现有最严格的政策胜出方案的全局政策中。调用之前影响全局状态的现有 API(setInterruptionFilter
、setNotificationPolicy
)会导致创建或更新隐式 AutomaticZenRule
,该 AutomaticZenRule
根据这些 API 调用的调用周期而开启或关闭。
请注意,只有在应用调用 setInterruptionFilter(INTERRUPTION_FILTER_ALL)
且预期调用会停用之前由其所有者激活的 AutomaticZenRule
时,此变更才会影响可观察的行为。
Mudanças na API OpenJDK
O Android 15 continua atualizando as principais bibliotecas do Android para se alinhar aos recursos das versões mais recentes do LTS do OpenJDK.
Algumas dessas mudanças podem afetar a compatibilidade de apps destinados ao Android 15 (nível 35 da API):
Mudanças nas APIs de formatação de string: a validação de índice de argumentos, flags, largura e precisão agora é mais rígida ao usar as seguintes APIs
String.format()
eFormatter.format()
:String.format(String, Object[])
String.format(Locale, String, Object[])
Formatter.format(String, Object[])
Formatter.format(Locale, String, Object[])
Por exemplo, a seguinte exceção é gerada quando um índice de argumento de 0 é usado (
%0
na string de formato):IllegalFormatArgumentIndexException: Illegal format argument index = 0
Nesse caso, o problema pode ser corrigido usando um índice de argumento de 1 (
%1
na string de formato).Mudanças no tipo de componente de
Arrays.asList(...).toArray()
: ao usarArrays.asList(...).toArray()
, o tipo de componente da matriz resultante agora éObject
, e não o tipo dos elementos da matriz subjacente. Portanto, o código a seguir gera umaClassCastException
:String[] elements = (String[]) Arrays.asList("one", "two").toArray();
Para este caso, para preservar
String
como o tipo de componente na matriz resultante, useCollection.toArray(Object[])
:String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
Mudanças no processamento de códigos de idioma: ao usar a API
Locale
, os códigos de idioma para hebraico, iídiche e indonésio não são mais convertidos para as formas obsoletas (hebraico:iw
, iídiche:ji
e indonésio:in
). Ao especificar o código de idioma para uma dessas localidades, use os códigos do ISO 639-1 (hebraico:he
, iídiche:yi
e indonésio:id
).Mudanças em sequências aleatórias de int: seguindo as mudanças feitas em https://bugs.openjdk.org/browse/JDK-8301574, os métodos
Random.ints()
abaixo agora retornam uma sequência de números diferente dos métodosRandom.nextInt()
:Em geral, essa mudança não deve resultar em um comportamento que quebre o app, mas o código não deve esperar que a sequência gerada pelos métodos
Random.ints()
corresponda aRandom.nextInt()
.
A nova API SequencedCollection
pode afetar a compatibilidade do app
depois que você atualizar compileSdk
na configuração de build do app para usar
o Android 15 (nível 35 da API):
Colisão com funções de extensão
MutableList.removeFirst()
eMutableList.removeLast()
emkotlin-stdlib
O tipo
List
em Java é mapeado para o tipoMutableList
em Kotlin. Como as APIsList.removeFirst()
eList.removeLast()
foram introduzidas no Android 15 (nível 35 da API), o compilador do Kotlin resolve chamadas de função, por exemplo,list.removeFirst()
, de forma estática para as novas APIsList
em vez das funções de extensão emkotlin-stdlib
.Se um app for recompilado com
compileSdk
definido como35
eminSdk
definido como34
ou inferior, e depois for executado no Android 14 e versões anteriores, um erro de execução será gerado:java.lang.NoSuchMethodError: No virtual method removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;
A opção de lint
NewApi
atual no Plug-in do Android para Gradle pode detectar esses novos usos da API../gradlew lint
MainActivity.kt:41: Error: Call requires API level 35 (current min is 34): java.util.List#removeFirst [NewApi] list.removeFirst()Para corrigir a exceção de execução e os erros de lint, as chamadas de função
removeFirst()
eremoveLast()
podem ser substituídas porremoveAt(0)
eremoveAt(list.lastIndex)
, respectivamente, no Kotlin. Se você estiver usando o Android Studio Ladybug | 2024.1.3 ou mais recente, ele também oferece uma opção de correção rápida para esses erros.Remova
@SuppressLint("NewApi")
elintOptions { disable 'NewApi' }
se a opção de lint tiver sido desativada.Colisão com outros métodos em Java
Novos métodos foram adicionados aos tipos existentes, por exemplo,
List
eDeque
. Esses novos métodos podem não ser compatíveis com os métodos com o mesmo nome e tipos de argumento em outras interfaces e classes. No caso de uma colisão de assinatura de método com incompatibilidade, o compiladorjavac
vai gerar um erro no tempo de build. Por exemplo:Exemplo de erro 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 ListExemplo de erro 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 errorExemplo de erro 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 errorPara corrigir esses erros de build, a classe que implementa essas interfaces precisa substituir o método por um tipo de retorno compatível. Exemplo:
@Override public Object getFirst() { return List.super.getFirst(); }
Segurança
O Android 15 inclui mudanças que promovem a segurança do sistema para ajudar a proteger apps e usuários contra apps maliciosos.
Inicia atividades seguras em segundo plano
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 来向用户显示不需要或恶意的内容。
Intents mais seguras
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()); }
Experiência do usuário e interface do sistema
O Android 15 inclui algumas mudanças que têm como objetivo criar uma experiência do usuário mais consistente e intuitiva.
Mudanças no encarte da janela
Há duas mudanças relacionadas a encartes de janela no Android 15: de ponta a ponta é aplicada por padrão, e também há mudanças de configuração, como a configuração padrão das barras do sistema.
Aplicação de ponta a ponta
Os apps são exibidos de borda a borda por padrão em dispositivos com o Android 15 se o app for direcionado para o Android 15 (nível 35 da API).
Essa é uma mudança importante que pode afetar negativamente a interface do seu app. As mudanças afetam as seguintes áreas da interface:
- Barra de navegação do identificador de gestos
- Transparente por padrão.
- O deslocamento inferior está desativado para que o conteúdo seja mostrado por trás da barra de navegação do sistema, a menos que os insets sejam aplicados.
setNavigationBarColor
eR.attr#navigationBarColor
foram descontinuados e não afetam a navegação por gestos.setNavigationBarContrastEnforced
eR.attr#navigationBarContrastEnforced
continuam sem efeito na navegação por gestos.
- Navegação com três botões
- Opacidade definida como 80% por padrão, com a cor possivelmente correspondendo ao plano de fundo da janela.
- Deslocamento inferior desativado para que o conteúdo fique atrás da barra de navegação do sistema, a menos que encartes sejam aplicados.
setNavigationBarColor
eR.attr#navigationBarColor
são definidos para corresponder ao plano de fundo da janela por padrão. O segundo plano da janela precisa ser um drawable de cor para que esse padrão seja aplicado. Essa API foi descontinuada, mas continua afetando a navegação com três botões.setNavigationBarContrastEnforced
eR.attr#navigationBarContrastEnforced
são verdadeiros por padrão, o que adiciona um plano de fundo opaco de 80% à navegação com três botões.
- Barra de status
- Transparente por padrão.
- O deslocamento superior está desativado para que o conteúdo seja renderizado atrás da barra de status, a menos que os encartes sejam aplicados.
setStatusBarColor
eR.attr#statusBarColor
foram descontinuados e não têm efeito no Android 15.setStatusBarContrastEnforced
eR.attr#statusBarContrastEnforced
foram descontinuados, mas ainda têm efeito no Android 15.
- Recorte da tela
- O
layoutInDisplayCutoutMode
de janelas não flutuantes precisa serLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
.SHORT_EDGES
,NEVER
eDEFAULT
são interpretados comoALWAYS
para que os usuários não vejam uma barra preta causada pelo corte da tela e apareçam de ponta a ponta.
- O
O exemplo a seguir mostra um app antes e depois de segmentar o Android 15 (nível 35 da API) e antes e depois de aplicar insets.
O que verificar se o app já está de ponta a ponta
Se o app já ocupa toda a tela de ponta a ponta e aplica insets, ele não será afetado, exceto nos seguintes cenários. No entanto, mesmo que você ache que não foi afetado, recomendamos testar o app.
- Você tem uma janela não flutuante, como uma
Activity
que usaSHORT_EDGES
,NEVER
ouDEFAULT
em vez deLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
. Se o app falha na inicialização, isso pode ser devido à tela de apresentação. É possível fazer upgrade da dependência da tela de apresentação principal para 1.2.0-alpha01 ou uma versão mais recente ou definirwindow.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always
. - Talvez haja telas com menos tráfego e uma interface obstruída. Verifique se essas
telas menos visitadas não têm uma interface obstruída. Telas com menos tráfego incluem:
- Telas de integração ou de login
- Páginas de configurações
O que verificar se o app ainda não ocupa toda a tela
Se o app ainda não ocupa toda a tela, é provável que você seja afetado. Além dos cenários para apps que já ocupam toda a tela, considere o seguinte:
- Se o app usar componentes do Material 3 (
androidx.compose.material3
) no Compose, comoTopAppBar
,BottomAppBar
eNavigationBar
, esses componentes provavelmente não serão afetados porque processam encartes automaticamente. - Se o app estiver usando componentes do Material 2 (
androidx.compose.material
) no Compose, eles não vão processar encartes automaticamente. No entanto, você pode conseguir acesso aos encartes e aplicá-los manualmente. Na androidx.compose.material 1.6.0 e versões mais recentes, use o parâmetrowindowInsets
para aplicar os encartes manualmente paraBottomAppBar
,TopAppBar
,BottomNavigation
eNavigationRail
. Da mesma forma, use o parâmetrocontentWindowInsets
paraScaffold
. - Caso o app use visualizações e componentes do Material
(
com.google.android.material
), a maioria dos componentes do Material baseados em visualizações, comoBottomNavigationView
,BottomAppBar
,NavigationRailView
ouNavigationView
, processa encartes e não exige trabalho extra. No entanto, é necessário adicionarandroid:fitsSystemWindows="true"
se estiver usandoAppBarLayout
. - Para elementos combináveis personalizados, aplique os encartes manualmente como padding. Se o
conteúdo estiver em um
Scaffold
, será possível consumir encartes usando os valores de preenchimento deScaffold
. Caso contrário, aplique o padding usando uma dasWindowInsets
. - Se o app estiver usando visualizações e
BottomSheet
,SideSheet
ou contêineres personalizados, aplique padding usandoViewCompat.setOnApplyWindowInsetsListener
. ParaRecyclerView
, aplique padding usando esse listener e também adicioneclipToPadding="false"
.
O que verificar se o app precisa oferecer proteção personalizada em segundo plano
Se o app precisar oferecer proteção em segundo plano personalizada para a navegação de três botões ou
a barra de status, ele precisará colocar um elemento combinável ou uma visualização atrás da barra do sistema
usando WindowInsets.Type#tappableElement()
para conseguir a altura da barra de navegação
de três botões ou WindowInsets.Type#statusBars
.
Outros recursos de ponta a ponta
Consulte os guias Visualizações de borda a borda e Composição de borda a borda para mais considerações sobre como aplicar insets.
APIs descontinuadas
As APIs a seguir foram descontinuadas, mas não foram desativadas:
R.attr#enforceStatusBarContrast
R.attr#navigationBarColor
(para navegação com três botões, com 80% alfa)Window#isStatusBarContrastEnforced
Window#setNavigationBarColor
(para navegação com três botões, com 80% Alfa)Window#setStatusBarContrastEnforced
As APIs a seguir foram descontinuadas e desativadas:
R.attr#navigationBarColor
(para navegação por gestos)R.attr#navigationBarDividerColor
R.attr#statusBarColor
Window#setDecorFitsSystemWindows
Window#getNavigationBarColor
Window#getNavigationBarDividerColor
Window#getStatusBarColor
Window#setNavigationBarColor
(para a navegação por gestos)Window#setNavigationBarDividerColor
Window#setStatusBarColor
Configuração estável
如果您的应用以 Android 15(API 级别 35)或更高版本为目标平台,Configuration
不再排除系统栏。如果您使用 Configuration
类中的屏幕尺寸进行布局计算,应根据需要将其替换为合适的 ViewGroup
、WindowInsets
或 WindowMetricsCalculator
等更好的替代方案。
Configuration
从 API 1 开始提供。它通常从 Activity.onConfigurationChanged
中获取。它提供窗口密度、屏幕方向和尺寸等信息。从 Configuration
返回的窗口大小的一个重要特征是,它之前会排除系统栏。
配置大小通常用于资源选择(例如 /res/layout-h500dp
),这仍然是一个有效的用例。不过,我们一直不建议将其用于布局计算。如果确实如此,您应暂时放弃。您应根据自己的用例,将 Configuration
的使用替换为更合适的用法。
如果您使用它来计算布局,请使用适当的 ViewGroup
,例如 CoordinatorLayout
或 ConstraintLayout
。如果您使用它来确定系统侧边栏的高度,请使用 WindowInsets
。如果您想知道应用窗口的当前大小,请使用 computeCurrentWindowMetrics
。
以下列表介绍了受此变更影响的字段:
Configuration.screenWidthDp
和screenHeightDp
尺寸不再排除系统栏。Configuration.smallestScreenWidthDp
会间接受到对screenWidthDp
和screenHeightDp
的更改的影响。- 在接近方形的设备上,
Configuration.orientation
会间接受到对screenWidthDp
和screenHeightDp
所做的更改的影响。 Display.getSize(Point)
会间接受到Configuration
中更改的影响。从 API 级别 30 开始,此方法已被弃用。- 从 API 级别 33 开始,
Display.getMetrics()
就已经这样运作了。
O atributo "elegantTextHeight" tem o padrão definido como "true".
对于以 Android 15 为目标平台的应用,elegantTextHeight
TextView
属性默认变为 true
,将默认使用的紧凑字体替换为一些具有较大垂直指标的脚本,并且这种字体更易于阅读。紧凑字体的引入是为了防止破坏布局;Android 13(API 级别 33)允许文本布局利用 fallbackLineSpacing
属性拉伸垂直高度,以防止许多此类破坏。
在 Android 15 中,紧凑字体仍保留在系统中,因此您的应用可以将 elegantTextHeight
设置为 false
,以获得与之前相同的行为,但即将在未来版本中提供支持。因此,如果您的应用支持以下文字:阿拉伯语、老挝语、缅甸、泰米尔语、古吉拉特语、卡纳达语、马拉雅拉姆语、奥里亚语、泰卢固语或泰语,请将 elegantTextHeight
设置为 true
,以测试应用。
A largura do TextView muda para formas de letras complexas
在以前的 Android 版本中,某些具有复杂形状的手写字体或语言可能会在上一个或下一个字符的区域绘制字母。在某些情况下,此类字母会在开头或结尾处被剪裁。从 Android 15 开始,TextView
会分配宽度,以便为此类字母绘制足够的空间,并允许应用请求向左额外添加内边距以防止剪裁。
由于此更改会影响 TextView
确定宽度的方式,因此如果应用以 Android 15(API 级别 35)或更高版本为目标平台,TextView
会默认分配更多宽度。您可以通过对 TextView
调用 setUseBoundsForWidth
API 来启用或停用此行为。
由于添加左内边距可能会导致现有布局未对齐,因此默认情况下不会添加内边距,即使以 Android 15 或更高版本为目标平台的应用也是如此。不过,您可以通过调用 setShiftDrawingOffsetForStartOverhang
添加额外的内边距以防止剪裁。
以下示例展示了这些更改如何改进某些字体和语言的文本布局。
Altura de linha padrão compatível com a localidade para EditText
在以前的 Android 版本中,文本布局拉伸了文本的高度,使其适应与当前语言区域匹配的字体的行高。例如,如果内容是日语,由于日语字体的行高比拉丁字体的行高略大,因此文本的高度就略大了。不过,尽管行高存在这些差异,但无论使用何种语言区域,EditText
元素的大小都是一致的,如下图所示:
对于以 Android 15 为目标平台的应用,系统现在会为 EditText
预留最小行高,以匹配指定语言区域的参考字体,如下图所示:
如果需要,您的应用可以通过将 useLocalePreferredLineHeightForMinimum
属性设置为 false
来恢复之前的行为,并且可以通过 Kotlin 和 Java 中的 setMinimumFontMetrics
API 设置自定义最小行业指标。
Câmera e mídia
O Android 15 faz as seguintes mudanças no comportamento da câmera e da mídia para apps destinados ao Android 15 ou mais recente.
Restrições ao solicitar foco de áudio
Os apps direcionados ao Android 15 precisam ser o principal ou executar um
serviço em primeiro plano para solicitar a seleção de áudio. Se um app
tentar solicitar a seleção quando não atender a um desses requisitos, a
chamada retornará AUDIOFOCUS_REQUEST_FAILED
.
Saiba mais sobre a seleção de áudio em Gerenciar seleção de áudio.
Atualização das restrições não SDK
O Android 15 inclui listas atualizadas de interfaces não SDK restritas com base na colaboração de desenvolvedores do Android e nos testes internos mais recentes. Antes de restringirmos interfaces não SDK, sempre que possível, garantimos que haja alternativas públicas disponíveis.
Caso seu app não seja destinado ao Android 15, é possível que algumas dessas mudanças não afetem você imediatamente. No entanto, embora seja possível que o app acesse algumas interfaces não SDK dependendo do nível da API de destino do app, o uso de qualquer método ou campo não SDK sempre apresenta um alto risco de corromper o app.
Se você não sabe se o app usa interfaces não SDK, teste-o para descobrir. Se o app depende de interfaces não SDK, comece a planejar uma migração para alternativas SDK. No entanto, entendemos que alguns apps têm casos de uso válidos para interfaces que não são do SDK. Se você não encontrar uma alternativa para deixar de usar uma interface fora do SDK em um recurso no app, solicite uma nova API pública.
Para saber mais sobre as mudanças dessa versão do Android, consulte Atualizações para restrições de interfaces não SDK no Android 15. Para saber mais sobre interfaces não SDK em geral, consulte Restrições para interfaces não SDK.