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.
Habilidades do Android
Ver no GitHubGerenciar atualizações do AppWidget e a memória de bitmap
android skills add glance-appwidget-updates-and-memoryComo 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
Bitmapna memória eIconcom suporte a bitmap (Icon.TYPE_BITMAPeIcon.TYPE_ADAPTIVE_BITMAP) armazenados emRemoteViews.mBitmapCache(como chamadas parasetImageViewBitmap,Icon.createWithBitmap,Icon.createWithAdaptiveBitmapou Jetpack GlanceImageProvider(bitmap)). Cada instância exclusiva deBitmapouIconcom suporte a bitmap emmBitmapCacheé contada uma vez por hierarquiaRemoteViews. - As imagens com suporte de URI (
Icon.createWithContentUri,setImageViewUriouImageProvider(uri)do Glance) não são contabilizadas no limite de bytes de IPCRemoteViewsemsystem_server, mas o processo do host do widget decodifica o arquivocontent://referenciado em resolução máxima no próprio heap. Sempre grave uma imagem reduzida emcontext.cacheDirantes de expô-la por um URIFileProvider.
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:
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 deWindowManager.currentWindowMetrics.boundsem vez deresources.displayMetrics. Em dispositivos de várias resoluções e dobráveis,displayMetricspode informar dimensões de tela inativas. Estime o orçamento total de imagens do widget em6L * 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() }Reduza a resolução das imagens para as dimensões visíveis do widget e use
RGB_565:decodifique bitmaps com valoresBitmapFactory.Options.inSampleSizede potência de dois dimensionados para as dimensões máximas de exibição do widget (maxWidthDppormaxHeightDp) e useBitmap.Config.RGB_565(2bytes por pixel) em vez deARGB_8888(4bytes por pixel) para fotografias e miniaturas opacas.Decodificação de bitmap de elevação fora de
provideContentno Jetpack Glance:ao usarSizeMode.ResponsiveouSizeMode.Exact, o Glance invoca o lambdaprovideContentuma vez por bucket de tamanho. Decodifique cadaBitmapcompartilhado uma vez dentro deprovideGlanceantes de chamarprovideContentpara que todos os buckets de tamanho façam referência à mesma instância deBitmapemRemoteViews.mBitmapCache.Use chamadas
updateAppWidgetcompletas ao substituir imagens:em implementações clássicas deAppWidgetProvider, evite chamarAppWidgetManager.partiallyUpdateAppWidgetpara trocar visualizações deBitmapouIcon. As atualizações parciais mesclam novas ações na árvoreRemoteViewsexistente emsystem_serversem remover as ações de imagem armazenadas em cache anteriormente. Crie um layoutRemoteViewscompleto e chameupdateAppWidget.Forneça um layout substituto de erro:no Jetpack Glance, substitua
onCompositionErrorpara renderizar um substituto deRemoteViewssem 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
从 Android 17 开始,以 Android 17(API 级别 37)或更高版本为目标平台的应用会收到 android.os.MessageQueue 的全新无锁实现。新实现可提升性能并减少丢帧,但可能会破坏反映 MessageQueue 私有字段和方法的客户端。
如需了解详情(包括缓解措施),请参阅 MessageQueue 行为变更指南。
Os campos finais estáticos agora não podem ser modificados
在 Android 17 或更高版本上运行且以 Android 17(API 级别 37)或更高版本为目标平台的应用无法更改 static final 字段。如果应用尝试使用反射来更改 static final 字段,则会导致 IllegalAccessException。尝试通过 JNI API(例如 SetStaticLongField())修改其中一个字段会导致应用崩溃。
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
此功能引入了新的 AccessibilityEvent 和 TextAttribute API,以增强屏幕阅读器对 CJKV 语言输入的语音反馈。中日韩越输入法应用现在可以指示在文本撰写期间是否已选择文本转换候选字词。具有修改字段的应用可以在发送文本更改无障碍事件时指定文本更改类型。例如,应用可以指定文本更改发生在文本撰写期间,或者文本更改是由提交操作引起的。
这样做可让屏幕阅读器等无障碍服务根据文本修改的性质提供更精确的反馈。
应用采用量
IME 应用:在编辑字段中设置撰写文本时,IME 可以使用
TextAttribute.Builder.setTextSuggestionSelected()指示是否选择了特定转换候选。具有修改字段的应用:维护自定义
InputConnection的应用可以通过调用TextAttribute.isTextSuggestionSelected()来检索候选选择数据。然后,这些应用应在分派TYPE_VIEW_TEXT_CHANGED事件时调用AccessibilityEvent.setTextChangeTypes()。对于以 Android 17(API 级别 37)为目标平台且使用标准TextView的应用,此功能将默认启用。(也就是说,TextView将在向无障碍服务发送事件时,处理从 IME 检索数据和设置文本更改类型的工作)。无障碍服务:处理
TYPE_VIEW_TEXT_CHANGED事件的无障碍服务可以调用AccessibilityEvent.getTextChangeTypes()来识别修改的性质,并相应地调整其反馈策略。
Privacidade
O Android 17 inclui as mudanças abaixo para melhorar a privacidade do usuário.
ECH (Encrypted Client Hello) ativado
Android 17 引入了对加密客户端问候 (ECH) 的平台支持,这是一种 TLS 扩展,可通过在 TLS 握手中加密服务器名称指示 (SNI) 来增强用户隐私。这种加密有助于防止网络观察者轻易识别出应用连接到的特定网域。
对于以 Android 17(API 级别 37)或更高版本为目标平台的应用,ECH 用于 TLS 连接。只有在应用使用的网络库(例如 HttpEngine、WebView 或 OkHttp)集成了 ECH 支持,并且远程服务器也支持 ECH 协议时,ECH 才会处于活跃状态。如果无法协商 ECH,客户端会发送包含随机内容的 ECH 扩展程序(一种称为 ECH GREASE 的机制)。如需详细了解 ECH GREASE 的运作方式,请参阅 RFC 9849。
为了允许应用自定义此行为,Android 17 向网络安全配置文件添加了新的 <domainEncryption> 元素。开发者可以在 <base-config> 或 <domain-config> 标记中使用 <domainEncryption>,以全局或按网域选择 ECH 模式(例如 "enabled" 或 "disabled")。
如需了解详情,请参阅加密客户端问候文档。
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
如果应用以 Android 17(API 级别 37)或更高版本为目标平台,并且用户使用的是实体输入设备(例如外接键盘),则 Android 操作系统会将新的 show_passwords_physical 设置应用于密码字段中的所有字符。默认情况下,该设置会隐藏所有密码字符。
Android 系统会显示最后输入的密码字符,以帮助用户查看是否输错了密码。不过,对于较大的外接键盘,这种需求要小得多。此外,配备外接键盘的设备通常具有更大的显示屏,这会增加他人看到所输入密码的风险。
如果用户使用的是设备的触摸屏,系统会应用新的 show_passwords_touch 设置。
Proteção de OTP para mensagens SMS padrão
从 Android 17 开始,Android 将扩展其短信动态密码保护功能,使其适用于标准短信(包含动态密码但不使用 WebOTP 或短信检索器格式的短信)。对于大多数以 Android 17(API 级别 37)或更高版本为目标平台的应用,这些短信在收到 3 小时后才可供使用。此延迟旨在帮助防止动态密码被劫持。在这 3 小时的延迟期间,SMS_RECEIVED_ACTION 广播会被扣留,短信提供商数据库查询会被过滤。延迟后,这些应用便可收到短信。
某些应用(例如默认短信助理应用、已连接设备的配套应用等)不受此延迟的影响。所有依赖读取短信来提取动态密码的应用都应改用 SMS Retriever 或 SMS User Consent API,以确保功能正常运行。
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 legadaMODE_BACKGROUND_ACTIVITY_START_ALLOWED. Em vez disso, adote controles granulares, comoMODE_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
如果应用以 Android 17(API 级别 37)或更高版本为目标平台,则默认启用证书透明度 (CT)。(在 Android 16 中,CT 可用,但应用必须选择启用。)
DCL nativa mais segura: C
如果您的应用以 Android 17(API 级别 37)或更高版本为目标平台,Android 14 中针对 DEX 和 JAR 文件引入的更安全的动态代码加载 (DCL) 保护机制现在也适用于原生库。
使用 System.load() 加载的所有原生文件都必须标记为只读。
否则,系统会抛出 UnsatisfiedLinkError。
我们建议应用尽可能避免动态加载代码,因为这样做会大大增加应用因代码注入或代码篡改而遭到入侵的风险。
Restringir campos de PII na visualização de dados do CP2
对于以 Android 17(API 级别 37)及更高版本为目标平台的应用,Contacts Provider 2 (CP2) 会限制数据视图中包含个人身份信息 (PII) 的某些列。启用此变更后,系统会从数据视图中移除这些列,以加强用户隐私保护。 受限列包括:
使用 ContactsContract.Data 中这些列的应用可以改为通过与 RAW_CONTACT_ID 联接,从 ContactsContract.RawContacts 中提取这些列。
Aplicar verificações rigorosas de SQL no CP2
对于以 Android 17(API 级别 37)及更高版本为目标平台的应用,如果在没有 READ_CONTACTS 权限的情况下访问 ContactsContract.Data 表,Contacts Provider 2 (CP2) 会强制执行严格的 SQL 查询验证。
做出此项更改后,如果应用没有 READ_CONTACTS 权限,则在查询 ContactsContract.Data 表时会设置 StrictColumns 和 StrictGrammar 选项。如果查询使用的模式与这些模式不兼容,则会被拒绝并导致抛出异常。
Inteligência
O Android 17 inclui as seguintes mudanças na inteligência do sistema.
Descontinuação de setContentCaptureEnabled
在某些设备上,内容捕获功能默认处于启用状态,以便设备端 AI 功能分析屏幕内容,从而提供智能体验。
从 Android 17 开始,ContentCaptureManager.setContentCaptureEnabled(boolean) API 方法已被废弃。对于以 Android 17(API 级别 37)或更高版本为目标平台的应用,调用 setContentCaptureEnabled(false) 不再会停用内容捕获功能。
如果您的应用需要继续停用内容捕获功能或限制系统捕获屏幕内容,您必须改用 FLAG_SECURE 窗口布局参数。
如需停用内容捕获,请在窗口中设置 FLAG_SECURE 标志,如以下示例所示:
Kotlin
window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
)
Java
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
);
如需了解详情,请参阅 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)
我们在 Android 16 中引入了平台 API 变更,以便针对以 API 级别 36 或更高级别为目标平台的应用,忽略大屏设备(sw >= 600dp)上的屏幕方向、尺寸调整和宽高比限制。开发者可以选择在 SDK 36 中选择退出这些变更,但对于以 Android 17(API 级别 37)或更高版本为目标平台的应用,此选择退出选项将不再可用。
如需了解详情,请参阅系统会忽略对屏幕方向和可调整大小性的限制。
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.