Assim como nas versões anteriores, o Android 15 inclui mudanças de comportamento que podem afetar seu app. As mudanças de comportamento a seguir se aplicam exclusivamente a apps destinados ao Android 15 ou versões mais recentes. 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 seu 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_COMPLETEDbroadcast receivers launching foreground services - Restrictions on starting foreground services while an app holds the
SYSTEM_ALERT_WINDOWpermission
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
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:
- Have your service implement the new
Service.onTimeout(int, int)method. When your app receives the callback, make sure to callstopSelf()within a few seconds. (If you don't stop the app right away, the system generates a failure.) - Make sure your app's
mediaProcessingservices 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). - Only start
mediaProcessingforeground 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. - Instead of using a
mediaProcessingforeground 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
Restrictions on BOOT_COMPLETED broadcast receivers launching foreground services
There are new restrictions on BOOT_COMPLETED broadcast receivers launching
foreground services. BOOT_COMPLETED receivers are not allowed to launch the
following types of foreground services:
dataSynccameramediaPlaybackphoneCallmediaProjectionmicrophone(this restriction has been in place formicrophonesince Android 14)
If a BOOT_COMPLETED receiver tries to launch any of those types of foreground
services, the system throws ForegroundServiceStartNotAllowedException.
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). Run the following adb command:
adb shell am compat enable FGS_BOOT_COMPLETED_RESTRICTIONS your-package-name
To send a BOOT_COMPLETED broadcast without restarting the device,
run the following adb command:
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 em quando os apps podem modificar o estado global do modo Não perturbe
Os apps direcionados ao Android 15 (nível 35 da API) e mais recentes não podem mais mudar o
estado global ou a política de Não perturbe (DND, na sigla em inglês) em um dispositivo, seja modificando
as configurações do usuário ou desativando o modo DND. Em vez disso, os apps precisam contribuir com um
AutomaticZenRule, que o sistema combina em uma política global com o
esquema de política mais restritiva. As chamadas para APIs que
afetam o estado global (setInterruptionFilter,
setNotificationPolicy) resultam na criação ou atualização de um
AutomaticZenRule implícito, que é ativado e desativado dependendo do ciclo de chamadas
dessas chamadas de API.
Essa mudança só afeta o comportamento observável se o app estiver chamando
setInterruptionFilter(INTERRUPTION_FILTER_ALL) e esperar que essa chamada desative uma AutomaticZenRule que foi ativada anteriormente pelos proprietários.
Mudanças na API OpenJDK
O Android 15 continua o trabalho de atualizar 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 strings: a validação de índice de argumento, flags, largura e precisão agora é mais rigorosa 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 exceção a seguir é gerada quando um índice de argumento 0 é usado (
%0na string de formato):IllegalFormatArgumentIndexException: Illegal format argument index = 0Nesse caso, o problema pode ser corrigido usando um índice de argumento 1 (
%1na 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 é umObject, não o tipo dos elementos da matriz subjacente. Portanto, o código a seguir gera umClassCastException:String[] elements = (String[]) Arrays.asList("one", "two").toArray();Nesse caso, para preservar
Stringcomo 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:jie 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:yie indonésio:id).Mudanças nas sequências de números inteiros aleatórios: seguindo as mudanças feitas em https://bugs.openjdk.org/browse/JDK-8301574, os seguintes métodos
Random.ints()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 prejudique o app, mas seu 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 do build do app para usar
o Android 15 (nível da API 35):
Conflito com as funções de extensão
MutableList.removeFirst()eMutableList.removeLast()emkotlin-stdlibO tipo
Listem Java é mapeado para o tipoMutableListem Kotlin. Como as APIsList.removeFirst()eList.removeLast()foram introduzidas no Android 15 (nível 35 da API), o compilador Kotlin resolve chamadas de função, por exemplo,list.removeFirst(), estaticamente para as novas APIsListem vez das funções de extensão emkotlin-stdlib.Se um app for recompilado com
compileSdkdefinido como35eminSdkdefinido como34ou inferior, e depois o app for executado no Android 14 e versões anteriores, um erro de tempo de execução será gerado:java.lang.NoSuchMethodError: No virtual method removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;A opção
NewApido lint no Plug-in do Android para Gradle pode detectar esses novos usos da API../gradlew lintMainActivity.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 tempo 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, em Kotlin. Se você estiver usando o Android Studio Ladybug | 2024.1.3 ou mais recente, ele também vai oferecer uma opção de correção rápida para esses erros.Considere remover
@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 atuais, por exemplo,
ListeDeque. Esses novos métodos podem não ser compatíveis com os métodos de mesmo nome e tipos de argumentos em outras interfaces e classes. No caso de uma colisão de assinatura de método com incompatibilidade, o compiladorjavacgera um erro de tempo de build. Exemplo:Exemplo de erro 1:
javac MyList.javaMyList.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.javaMyList.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.javaMyList.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 com 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.
Versões TLS restritas
Android 15 限制了对 TLS 版本 1.0 和 1.1 的使用。这些版本之前已在 Android 中被弃用,但现在不允许面向 Android 15 的应用使用。
Início de atividades em segundo plano seguras
Android 15 做出了一些变更,可防止恶意后台应用将其他应用置于前台、提升自身权限并滥用用户互动,从而保护用户免受恶意应用的侵害,并让用户更好地控制自己的设备。自 Android 10(API 级别 29)起,后台 activity 启动受到限制。
其他更改
- 将
PendingIntent创建者更改为默认阻止后台活动启动。这有助于防止应用意外创建可能被恶意行为者滥用的PendingIntent。 - 除非
PendingIntent发送方允许,否则请勿将应用转至前台。此变更旨在防止恶意应用滥用在后台启动 activity 的功能。默认情况下,除非创建者允许后台 activity 启动权限或发送者具有后台 activity 启动权限,否则不允许应用将任务堆栈带到前台。 - 控制任务堆栈的顶层 activity 如何完成其任务。如果顶部 activity 完成了一项任务,Android 将返回到上次处于活跃状态的任务。此外,如果非顶部 activity 完成其任务,Android 会返回到主屏幕;它不会阻止此非顶部 activity 完成。
- 防止从其他应用启动任意 activity 进入您自己的任务。此变更可防止恶意应用通过创建看似来自其他应用的 activity 来对用户进行钓鱼式攻击。
- 阻止将非可见窗口纳入后台 activity 启动的考虑范围。这有助于防止恶意应用滥用后台活动启动来向用户显示不必要或恶意的内容。
Intents mais seguras
Agora, o Android 15 tem o StrictMode para intents.
Para conferir registros detalhados sobre violações de uso do Intent, use o seguinte método:
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 visam criar uma experiência do usuário mais consistente e intuitiva.
Mudanças no encarte da janela
There are two changes related to window insets in Android 15: edge-to-edge is enforced by default, and there are also configuration changes, such as the default configuration of system bars.
Aplicação de ponta a ponta
Os apps são de ponta a ponta por padrão em dispositivos com Android 15 se o app for destinado ao Android 15 (nível 35 da API).
Essa é uma mudança incompatível que pode afetar negativamente a interface do seu app. As mudanças afetam as seguintes áreas da interface:
- Barra de navegação com alça de gesto
- Transparente por padrão.
- O deslocamento inferior está desativado, então o conteúdo é desenhado por trás da barra de navegação do sistema, a menos que insets sejam aplicados.
setNavigationBarColoreR.attr#navigationBarColorestão descontinuados e não afetam a navegação por gestos.setNavigationBarContrastEnforcedeR.attr#navigationBarContrastEnforcedcontinuam 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 seja mostrado por trás da barra de navegação do sistema, a menos que margens das janelas sejam aplicadas.
setNavigationBarColoreR.attr#navigationBarColorsão definidos para corresponder ao plano de fundo da janela por padrão. O plano de fundo da janela precisa ser um drawable de cor para que esse padrão seja aplicado. Essa API está descontinuada, mas continua afetando a navegação com três botões.setNavigationBarContrastEnforcedeR.attr#navigationBarContrastEnforcedsão verdadeiros por padrão, o que adiciona um plano de fundo 80% opaco na navegação com três botões.
- Barra de status
- Transparente por padrão.
- O deslocamento superior é desativado, então o conteúdo é mostrado por trás da barra de status, a menos que margens das janelas sejam aplicadas.
setStatusBarColoreR.attr#statusBarColorforam descontinuados e não têm efeito no Android 15.setStatusBarContrastEnforcedeR.attr#statusBarContrastEnforcedforam descontinuados, mas ainda têm um efeito no Android 15.
- Corte da tela
- O
layoutInDisplayCutoutModede janelas não flutuantes precisa serLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS.SHORT_EDGES,NEVEReDEFAULTsão interpretados comoALWAYSpara 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 ser direcionado ao Android 15 (nível 35 da API) e antes e depois de aplicar encartes. Este exemplo não é abrangente e pode aparecer de maneira diferente no Android Auto.
O que verificar se o app já é de ponta a ponta
Se o app já for de ponta a ponta e aplicar encartes, você não será muito afetado, exceto nos seguintes cenários. No entanto, mesmo que você não acredite que seu app foi afetado, recomendamos que você o teste.
- Você tem uma janela não flutuante, como um
Activityque usaSHORT_EDGES,NEVERouDEFAULTem vez deLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS. Se o app falhar na inicialização, isso pode ser devido à tela de apresentação. Você pode fazer upgrade da dependência core splashscreen para 1.2.0-alpha01 ou uma versão mais recente ou definirwindow.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always. - Pode haver telas com menos tráfego e interface obstruída. Verifique se essas telas menos visitadas não têm uma interface obstruída. As telas com menos tráfego incluem:
- Telas de onboarding ou login
- Páginas de configurações
O que verificar se o app ainda não é de ponta a ponta
Se o app ainda não estiver de ponta a ponta, é provável que você seja afetado. Além dos cenários para apps que já são de ponta a ponta, considere o seguinte:
- Se o app usar componentes do Material 3 (
androidx.compose.material3) no Compose, comoTopAppBar,BottomAppBareNavigationBar, é provável que esses componentes não sejam 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 acessar os encartes e aplicá-los manualmente. No androidx.compose.material 1.6.0 e versões mais recentes, use o parâmetrowindowInsetspara aplicar os encartes manualmente emBottomAppBar,TopAppBar,BottomNavigationeNavigationRail. Da mesma forma, use o parâmetrocontentWindowInsetsparaScaffold. - Se o app usa views e componentes do Material Design
(
com.google.android.material), a maioria dos componentes do Material baseados em views, comoBottomNavigationView,BottomAppBar,NavigationRailViewouNavigationView, processa encartes e não exige mais trabalho. No entanto, você precisará 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, use os valores de padding Scaffoldpara consumir encartes. Caso contrário, aplique o padding usando um dosWindowInsets. - Se o app estiver usando visualizações e
BottomSheet,SideSheetou 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 de segundo plano personalizada
Se o app precisar oferecer proteção de plano de fundo personalizada para a navegação com três botões ou
a barra de status, ele deverá colocar um elemento combinável ou uma visualização atrás da barra de sistema
usando WindowInsets.Type#tappableElement() para receber a altura da barra de navegação
com três botões ou WindowInsets.Type#statusBars.
Outros recursos de ponta a ponta
Consulte os guias Visualizações de ponta a ponta e Compose de ponta a ponta para mais considerações sobre a aplicação de encartes.
APIs obsoletas
As APIs a seguir estão descontinuadas, mas não desativadas:
R.attr#enforceStatusBarContrastR.attr#navigationBarColor(para navegação com três botões, com alfa de 80%)Window#isStatusBarContrastEnforcedWindow#setNavigationBarColor(para navegação com três botões, com alfa de 80%)Window#setStatusBarContrastEnforced
As APIs a seguir estão desativadas:
R.attr#navigationBarColor(para navegação por gestos)R.attr#navigationBarDividerColorR.attr#statusBarColorWindow#setDecorFitsSystemWindowsWindow#getNavigationBarColorWindow#getNavigationBarDividerColorWindow#getStatusBarColorWindow#setNavigationBarColor(para navegação por gestos)Window#setNavigationBarDividerColorWindow#setStatusBarColor
Configuração estável
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:
Configuration.screenWidthDpandscreenHeightDpsizes no longer exclude the system bars.Configuration.smallestScreenWidthDpis indirectly affected by changes toscreenWidthDpandscreenHeightDp.Configuration.orientationis indirectly affected by changes toscreenWidthDpandscreenHeightDpon close-to-square devices.Display.getSize(Point)is indirectly affected by the changes inConfiguration. This was deprecated beginning in API level 30.Display.getMetrics()has already worked like this since API level 33.
O atributo "elegantTextHeight" tem como padrão o valor "true".
对于以 Android 15(API 级别 35)为目标平台的应用,elegantTextHeight TextView 属性默认会变为 true,将默认使用的紧凑字体替换为一些具有较大垂直测量的脚本,使其更易于阅读。紧凑字体旨在防止布局中断;Android 13(API 级别 33)允许文本布局利用 fallbackLineSpacing 属性拉伸垂直高度,从而防止许多此类中断。
在 Android 15 中,系统中仍保留了紧凑字体,因此您的应用可以将 elegantTextHeight 设置为 false 以获得与之前相同的行为,但即将发布的版本不太可能支持此字体。因此,如果您的应用支持以下脚本:阿拉伯语、老挝语、缅甸语、泰米尔语、古吉拉特语、卡纳达语、马拉雅拉姆语、奥里亚语、泰卢固语或泰语,请将 elegantTextHeight 设置为 true 以测试您的应用。
elegantTextHeight 行为。
elegantTextHeight 行为。A largura da TextView muda para formas de letras complexas
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.
<TextView android:fontFamily="cursive" android:text="java" />
<TextView android:fontFamily="cursive" android:text="java" android:useBoundsForWidth="true" android:shiftDrawingOffsetForStartOverhang="true" />
<TextView android:text="คอมพิวเตอร์" />
<TextView android:text="คอมพิวเตอร์" android:useBoundsForWidth="true" android:shiftDrawingOffsetForStartOverhang="true" />
Altura da linha padrão compatível com localidade para EditText
在较低版本的 Android 中,文本布局会拉伸文本的高度,以满足与当前语言区域匹配的字体的行高。例如,如果内容是日语,由于日语字体的行高略高于拉丁字体,因此文本的高度会略高。不过,尽管行高存在这些差异,但无论使用的是哪种语言区域,EditText 元素的大小都是统一的,如下图所示:
EditText 元素。EditText 的高度相同,即使这些语言的行高各不相同。对于以 Android 15(API 级别 35)为目标平台的应用,现在为 EditText 预留了最小行高,以匹配指定语言区域的参考字体,如下图所示:
EditText 元素。EditText 的高度现在包含足够的空间来容纳这些语言字体的默认行高。如有需要,您的应用可以将 useLocalePreferredLineHeightForMinimum 属性指定为 false,以恢复之前的行为;您的应用还可以在 Kotlin 和 Java 中使用 setMinimumFontMetrics API 设置自定义最小垂直指标。
Câmera e mídia
O Android 15 faz as seguintes mudanças no comportamento de câmera e mídia para apps direcionados ao Android 15 ou versões mais recentes.
Restrições ao solicitar a seleção de áudio
以 Android 15(API 级别 35)为目标平台的应用必须是顶部应用或正在运行前台服务,才能请求音频焦点。如果应用在未满足上述任一要求的情况下尝试请求焦点,调用将返回 AUDIOFOCUS_REQUEST_FAILED。
如需详细了解音频焦点,请参阅管理音频焦点。
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 com desenvolvedores 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 seu app acesse algumas interfaces não SDK dependendo do nível desejado da API 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 souber se seu app usa interfaces não SDK, poderá testá-lo para descobrir. Se ele 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 não SDK. Se você não encontrar uma alternativa para deixar de usar uma interface não SDK em um recurso no seu app, solicite uma nova API pública.
To learn more about the changes in this release of Android, see Updates to non-SDK interface restrictions in Android 15. To learn more about non-SDK interfaces generally, see Restrictions on non-SDK interfaces.