Mudanças de comportamento: apps destinados ao Android 17 ou versões mais recentes

Como nas versões anteriores, o Android 17 inclui mudanças de comportamento que podem afetar seu app. As mudanças de comportamento abaixo se aplicam exclusivamente a apps destinados ao Android 17 ou versões mais recentes. Caso seu app seja direcionado ao Android 17 ou a versões mais recentes, faça modificações para oferecer suporte a esses comportamentos, quando aplicável.

Consulte também a lista de mudanças de comportamento que afetam todos os apps executados no Android 17, independente da targetSdkVersion do app.

Experiência do usuário e interface do sistema

O Android 17 inclui as mudanças a seguir, que têm como objetivo criar uma experiência do usuário mais consistente e intuitiva.

Widget de limite de memória

No Android 17 e versões mais recentes, o sistema aplica um limite de memória rigoroso às atualizações de RemoteViews para apps destinados ao Android 17 (nível 37 da API) ou mais recente. Quando um app transmite um objeto RemoteViews para AppWidgetManager.updateAppWidget, system_server calcula o consumo total de memória de todos os dados de imagem em cada bucket de orientação e tamanho no payload. Se a memória total exceder o limite do sistema (mMaxWidgetBitmapMemory), o sistema vai rejeitar a atualização e gerar um IllegalArgumentException:

java.lang.IllegalArgumentException: RemoteViews for widget update exceeds maximum bitmap memory usage (used: XXXXX, max: YYYYY)

Para apps que usam o nível 36 da API ou anterior, o sistema registra essa violação de memória como um aviso (Slog.w) sem gerar uma exceção.

Como o sistema calcula o limite de memória

O sistema define o orçamento de memória do bitmap do widget como 6 * width * height bytes (1.5 * 4 * width * height, equivalente a 1,5 vez o tamanho de um buffer ARGB_8888 em tela cheia) para a configuração de tela ativa. No nível 37 da API e em versões mais recentes, esse cálculo inclui:

  • Objetos Bitmap na memória e Icon com suporte a bitmap (Icon.TYPE_BITMAP e Icon.TYPE_ADAPTIVE_BITMAP) armazenados em RemoteViews.mBitmapCache (como chamadas para setImageViewBitmap, Icon.createWithBitmap, Icon.createWithAdaptiveBitmap ou Jetpack Glance ImageProvider(bitmap)). Cada instância exclusiva de Bitmap ou Icon com suporte a bitmap em mBitmapCache é contada uma vez por hierarquia RemoteViews.
  • As imagens com suporte de URI (Icon.createWithContentUri, setImageViewUri ou ImageProvider(uri) do Glance) não são contabilizadas no limite de bytes de IPC RemoteViews em system_server, mas o processo do host do widget decodifica o arquivo content:// referenciado em resolução máxima no próprio heap. Sempre grave uma imagem reduzida em context.cacheDir antes de expô-la por um URI FileProvider.

Etapas de mitigação

Para manter as atualizações do widget dentro do limite de memória em smartphones, tablets e dobráveis, faça o seguinte:

  1. Calcule o orçamento de memória de tempo de execução de WindowMetrics:no nível da API 30 e em versões mais recentes, leia os limites da janela ativa de WindowManager.currentWindowMetrics.bounds em vez de resources.displayMetrics. Em dispositivos de várias resoluções e dobráveis, displayMetrics pode informar dimensões de tela inativas. Estime o orçamento total de imagens do widget em 6L * bounds.width() * bounds.height(), conforme mostrado no exemplo a seguir:

    private const val FALLBACK_MAX_BYTES = 15_000_000L
    
    fun calculateWidgetMemoryCapBytes(context: Context): Long {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            val wm = context.getSystemService(WindowManager::class.java)
                ?: return FALLBACK_MAX_BYTES
            val bounds = wm.currentWindowMetrics.bounds
            return 6L * bounds.width().toLong() * bounds.height().toLong()
        }
        val dm = context.resources.displayMetrics
        return 6L * dm.widthPixels.toLong() * dm.heightPixels.toLong()
    }
    
  2. Reduza a resolução das imagens para as dimensões visíveis do widget e use RGB_565:decodifique bitmaps com valores BitmapFactory.Options.inSampleSize de potência de dois dimensionados para as dimensões máximas de exibição do widget (maxWidthDp por maxHeightDp) e use Bitmap.Config.RGB_565 (2 bytes por pixel) em vez de ARGB_8888 (4 bytes por pixel) para fotografias e miniaturas opacas.

  3. Decodificação de bitmap de elevação fora de provideContent no Jetpack Glance:ao usar SizeMode.Responsive ou SizeMode.Exact, o Glance invoca o lambda provideContent uma vez por bucket de tamanho. Decodifique cada Bitmap compartilhado uma vez dentro de provideGlance antes de chamar provideContent para que todos os buckets de tamanho façam referência à mesma instância de Bitmap em RemoteViews.mBitmapCache.

  4. Use chamadas updateAppWidget completas ao substituir imagens:em implementações clássicas de AppWidgetProvider, evite chamar AppWidgetManager.partiallyUpdateAppWidget para trocar visualizações de Bitmap ou Icon. As atualizações parciais mesclam novas ações na árvore RemoteViews existente em system_server sem remover as ações de imagem armazenadas em cache anteriormente. Crie um layout RemoteViews completo e chame updateAppWidget.

  5. Forneça um layout substituto de erro:no Jetpack Glance, substitua onCompositionError para renderizar um substituto de RemoteViews sem bitmap se uma atualização falhar.

Para inspecionar o uso da memória de bitmap serializada do widget em um dispositivo conectado, execute o seguinte:

adb shell dumpsys appwidget

Principal recurso

O Android 17 inclui as mudanças abaixo, que modificam ou ampliam vários recursos principais do sistema Android.

Nova implementação sem bloqueio de MessageQueue

A partir do Android 17, os apps destinados ao Android 17 (nível 37 da API) ou mais recente recebem uma nova implementação sem bloqueio de android.os.MessageQueue. A nova implementação melhora o desempenho e reduz os frames perdidos, mas pode causar falhas em clientes que refletem em campos e métodos particulares de MessageQueue.

Para mais informações, incluindo estratégias de mitigação, consulte as orientações sobre mudanças de comportamento da MessageQueue.

Os campos finais estáticos agora não podem ser modificados

Os apps executados no Android 17 ou versões mais recentes que segmentam o Android 17 (nível 37 da API) ou versões mais recentes não podem mudar os campos static final. Se um app tentar mudar um campo static final usando reflexão, isso vai causar um IllegalAccessException. A tentativa de modificar um desses campos com APIs JNI (como SetStaticLongField()) vai causar uma falha no app.

Acessibilidade

O Android 17 faz as mudanças abaixo para melhorar a acessibilidade.

Suporte de acessibilidade para digitação complexa em teclado físico com IME

Esse recurso apresenta novas APIs AccessibilityEvent e TextAttribute para melhorar a resposta falada do leitor de tela para entrada de idiomas CJKV. Os apps de IME CJKV agora podem sinalizar se um candidato à conversão de texto foi selecionado durante a composição do texto. Os apps com campos de edição podem especificar tipos de mudança de texto ao enviar eventos de acessibilidade de mudança de texto. Por exemplo, os apps podem especificar que uma mudança de texto ocorreu durante a composição de texto ou que uma mudança de texto resultou de uma confirmação. Isso permite que serviços de acessibilidade, como leitores de tela, forneçam feedback mais preciso com base na natureza da modificação do texto.

Adoção de apps

  • Apps de IME:ao definir o texto de composição em campos de edição, os IMEs podem usar TextAttribute.Builder.setTextSuggestionSelected() para indicar se um candidato de conversão específico foi selecionado.

  • Apps com campos de edição:apps que mantêm um InputConnection personalizado podem recuperar dados de seleção de candidatos chamando TextAttribute.isTextSuggestionSelected(). Esses apps precisam chamar AccessibilityEvent.setTextChangeTypes() ao enviar eventos TYPE_VIEW_TEXT_CHANGED. Os apps destinados ao Android 17 (nível 37 da API) que usam o TextView padrão terão esse recurso ativado por padrão. Ou seja, o TextView vai processar a recuperação de dados do IME e definir os tipos de mudança de texto ao enviar eventos para serviços de acessibilidade.

  • Serviços de acessibilidade:os serviços de acessibilidade que processam eventos TYPE_VIEW_TEXT_CHANGED podem chamar AccessibilityEvent.getTextChangeTypes() para identificar a natureza da modificação e ajustar as estratégias de feedback de acordo.

Privacidade

O Android 17 inclui as mudanças abaixo para melhorar a privacidade do usuário.

ECH (Encrypted Client Hello) ativado

O Android 17 apresenta suporte da plataforma para o Encrypted Client Hello (ECH), uma extensão do TLS que melhora a privacidade do usuário criptografando a indicação de nome do servidor (SNI, na sigla em inglês) no handshake de TLS. Essa criptografia ajuda a impedir que observadores de rede identifiquem facilmente o domínio específico ao qual o app está se conectando.

Para apps direcionados ao Android 17 (nível 37 da API) ou mais recentes, o ECH é usado para conexões TLS. O ECH só fica ativo se a biblioteca de rede usada pelo app (por exemplo, HttpEngine, WebView ou OkHttp) tiver suporte integrado ao ECH e o servidor remoto também for compatível com o protocolo ECH. Se o ECH não puder ser negociado, o cliente vai enviar uma extensão de ECH com conteúdo aleatório (um mecanismo chamado ECH GREASE). Consulte a RFC 9849 para mais detalhes sobre como o GREASE do ECH funciona.

Para permitir que os apps personalizem esse comportamento, o Android 17 adiciona um novo elemento <domainEncryption> ao arquivo de configuração de segurança de rede. Os desenvolvedores podem usar <domainEncryption> em tags <base-config> ou <domain-config> para selecionar um modo de ECH (por exemplo, "enabled" ou "disabled") de forma global ou por domínio.

Para mais informações, consulte a documentação sobre o Encrypted Client Hello.

Permissão de rede local necessária para apps destinados ao Android 17

O Android 17 apresenta a permissão de execução ACCESS_LOCAL_NETWORK para proteger os usuários contra o acesso não autorizado à rede local. Como isso se enquadra no grupo de permissões NEARBY_DEVICES, os usuários que já concederam outras permissões NEARBY_DEVICES não vão receber uma nova solicitação. Esse novo requisito impede que apps mal-intencionados usem o acesso irrestrito à rede local para rastreamento de usuários e técnicas de impressão digital. Ao declarar e solicitar essa permissão, seu app pode descobrir e se conectar a dispositivos na rede de área local (LAN), como dispositivos de casa inteligente ou receptores de transmissão.

Os apps destinados ao Android 17 (nível 37 da API) ou versões mais recentes agora têm duas maneiras de manter a comunicação com dispositivos LAN: adotar seletores de dispositivos mediados pelo sistema e que preservam a privacidade para pular a solicitação de permissão ou solicitar explicitamente essa nova permissão no momento da execução para manter a comunicação com a rede local.

Para mais informações, consulte a documentação sobre permissão de rede local.

Ocultar senhas de dispositivos físicos

Se um app for direcionado ao Android 17 (nível 37 da API) ou versões mais recentes e o usuário estiver usando um dispositivo de entrada físico (por exemplo, um teclado externo), o sistema operacional Android vai aplicar a nova configuração show_passwords_physical a todos os caracteres no campo de senha. Por padrão, essa configuração oculta todos os caracteres da senha.

O sistema Android mostra o último caractere digitado para ajudar o usuário a ver se ele digitou a senha incorretamente. No entanto, isso é muito menos necessário com teclados externos maiores. Além disso, os dispositivos com teclados externos geralmente têm telas maiores, o que aumenta o risco de alguém ver a senha digitada.

Se o usuário estiver usando a touch screen do dispositivo, o sistema vai aplicar a nova configuração show_passwords_touch.

Proteção de OTP para mensagens SMS padrão

A partir do Android 17, o Android está estendendo a proteção de OTP por SMS para mensagens SMS padrão (mensagens SMS que contêm uma OTP e não usam os formatos WebOTP ou SMS Retriever). Para a maioria dos apps direcionados ao Android 17 (nível 37 da API) ou versões mais recentes, essas mensagens SMS só ficam disponíveis três horas após o recebimento. Esse atraso ajuda a evitar o sequestro de OTPs. Durante esse atraso de três horas, a transmissão de SMS_RECEIVED_ACTION é retida e as consultas ao banco de dados do provedor de SMS são filtradas. A mensagem SMS fica disponível para esses apps após o atraso.

Alguns apps, como o app assistivo de SMS padrão, apps complementares de dispositivos conectados etc., estão isentos desse atraso. Todos os apps que dependem da leitura de mensagens SMS para extração de OTP precisam usar as APIs SMS Retriever ou SMS User Consent para garantir a funcionalidade contínua.

Segurança

O Android 17 traz as seguintes melhorias para a segurança de dispositivos e apps.

Segurança de atividades

No Android 17, a plataforma continua a transição para uma arquitetura "segura por padrão", introduzindo um conjunto de melhorias projetadas para mitigar exploits de alta gravidade, como phishing, sequestro de interação e ataques de deputado confuso. Essa atualização exige que os desenvolvedores aceitem explicitamente os novos padrões de segurança para manter a compatibilidade do app e a proteção do usuário.

Os principais impactos para os desenvolvedores incluem:

  • Reforço da BAL e melhoria da ativação:estamos refinando as restrições de inicialização de atividades em segundo plano (BAL, na sigla em inglês) ao estender as proteções para IntentSender. Os desenvolvedores precisam migrar da constante legada MODE_BACKGROUND_ACTIVITY_START_ALLOWED. Em vez disso, adote controles granulares, como MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE, que restringe as inicializações de atividades a cenários em que o app de ligação está visível, reduzindo significativamente a superfície de ataque.
  • Ferramentas de adoção:os desenvolvedores precisam usar o modo estrito e as verificações de lint atualizadas para identificar padrões legados e garantir a prontidão para os requisitos futuros do SDK de destino.

Ativar CT por padrão

Se um app for direcionado ao Android 17 (nível 37 da API) ou versões mais recentes, a transparência de certificados (CT, na sigla em inglês) será ativada por padrão. No Android 16, a CT está disponível, mas os apps precisavam ativar.

DCL nativa mais segura: C

Se o app for direcionado ao Android 17 (nível 37 da API) ou versões mais recentes, a proteção de carregamento dinâmico de código (DCL, na sigla em inglês) mais seguro, introduzida no Android 14 para arquivos DEX e JAR, agora se estende às bibliotecas nativas.

Todos os arquivos nativos carregados usando System.load() precisam ser marcados como somente leitura. Caso contrário, o sistema vai gerar UnsatisfiedLinkError.

Recomendamos que os apps evitem carregar código dinamicamente sempre que possível, porque isso aumenta muito o risco de comprometimento do app por injeção ou adulteração de código.

Restringir campos de PII na visualização de dados do CP2

Para apps destinados ao Android 17 (nível 37 da API) e versões mais recentes, o Provedor de Contatos 2 (CP2) restringe determinadas colunas que contêm informações de identificação pessoal (PII) da visualização de dados. Quando essa mudança é ativada, essas colunas são removidas da visualização de dados para melhorar a privacidade do usuário. As colunas restritas incluem:

Os apps que usam essas colunas de ContactsContract.Data podem extraí-las de ContactsContract.RawContacts, unindo-as a RAW_CONTACT_ID.

Aplicar verificações rigorosas de SQL no CP2

Para apps destinados ao Android 17 (nível 37 da API) e versões mais recentes, o Provedor de Contatos 2 (CP2) aplica uma validação rigorosa de consultas SQL quando a tabela ContactsContract.Data é acessada sem a permissão READ_CONTACTS.

Com essa mudança, se um app não tiver a permissão READ_CONTACTS, as opções StrictColumns e StrictGrammar serão definidas ao consultar a tabela ContactsContract.Data. Se uma consulta usar um padrão incompatível com eles, ela será rejeitada e causará uma exceção.

Inteligência

O Android 17 inclui as seguintes mudanças na inteligência do sistema.

Descontinuação de setContentCaptureEnabled

A Captura de Conteúdo é ativada por padrão em determinados dispositivos para permitir que os recursos de IA no dispositivo analisem o conteúdo da tela para experiências inteligentes.

A partir do Android 17, o método da API ContentCaptureManager.setContentCaptureEnabled(boolean) foi descontinuado. Para apps destinados ao Android 17 (nível 37 da API) ou mais recente, chamar setContentCaptureEnabled(false) não desativa mais a captura de conteúdo.

Se o app precisar continuar desativando a captura de conteúdo ou restringindo a captura de conteúdo da tela pelo sistema, faça a transição para o parâmetro de layout de janela FLAG_SECURE.

Para desativar a Captura de Conteúdo, defina a flag FLAG_SECURE na janela, conforme mostrado no exemplo a seguir:

Kotlin

window.setFlags(
    WindowManager.LayoutParams.FLAG_SECURE,
    WindowManager.LayoutParams.FLAG_SECURE
)

Java

getWindow().setFlags(
    WindowManager.LayoutParams.FLAG_SECURE,
    WindowManager.LayoutParams.FLAG_SECURE
);

Para mais detalhes, consulte a documentação de referência do WindowManager.LayoutParams.FLAG_SECURE.

Mídia

O Android 17 inclui as seguintes mudanças no comportamento de mídia.

Proteção de áudio em segundo plano

A partir do Android 17, o framework de áudio aplica restrições a interações de áudio em segundo plano, incluindo reprodução de áudio, solicitações de foco de áudio e APIs de mudança de volume para garantir que essas mudanças sejam iniciadas intencionalmente pelo usuário.

Algumas restrições de áudio se aplicam a todos os apps. No entanto, as restrições são mais rigorosas se um app for direcionado ao Android 17 (nível 37 da API). Se um desses apps interagir com áudio enquanto estiver em segundo plano, ele precisará ter um serviço em primeiro plano em execução. Além disso, o app precisa atender a um ou ambos os seguintes requisitos:

  • O serviço em primeiro plano precisa ter recursos de uso (WIU, na sigla em inglês).
  • O app precisa ter a permissão de alarme exato e interagir com streams de áudio USAGE_ALARM.

Para mais informações, incluindo estratégias de mitigação, consulte Proteção de áudio em segundo plano.

Formatos de dispositivo

O Android 17 inclui as mudanças a seguir para melhorar a experiência do usuário em vários tamanhos e formatos de dispositivos.

Mudanças na API Platform para ignorar restrições de orientação, redimensionamento e proporção em telas grandes (sw>=600 dp)

Introduzimos mudanças na API Platform no Android 16 para ignorar restrições de orientação, redimensionamento e proporção em telas grandes (sw >= 600 dp) para apps destinados ao nível 36 ou mais recente da API. Os desenvolvedores têm a opção de desativar essas mudanças com o SDK 36, mas essa desativação não vai estar mais disponível para apps destinados ao Android 17 (nível 37 da API) ou mais recente.

Para mais informações, consulte As restrições de orientação e redimensionamento são ignoradas.

Conectividade

O Android 17 apresenta a mudança abaixo para melhorar a consistência e se alinhar ao comportamento padrão do Java InputStream para soquetes RFCOMM Bluetooth.

Comportamento consistente de read() do BluetoothSocket para RFCOMM

Para apps destinados ao Android 17 (nível 37 da API), o método read() do InputStream recebido de um BluetoothSocket baseado em RFCOMM agora retorna -1 quando o soquete é fechado ou a conexão é interrompida.

Essa mudança torna o comportamento do soquete RFCOMM consistente com os soquetes LE CoC e se alinha à documentação padrão do InputStream.read(), que afirma que -1 é retornado quando o fim do stream é alcançado.

Os apps que dependem apenas da captura de uma IOException para sair de um loop de leitura podem ser afetados por essa mudança e precisam atualizar os loops de leitura do BluetoothSocket para verificar explicitamente se há um valor de retorno de -1. Isso garante que o loop seja encerrado corretamente quando o dispositivo remoto se desconectar ou o soquete for fechado. Para ver um exemplo da implementação recomendada, consulte o snippet de código no guia Transferir dados por Bluetooth.