Register now for Android Dev Summit 2019!

Recursos e APIs do Android Q

O Android Q apresenta novos recursos e funcionalidades incríveis para usuários e desenvolvedores. Este documento destaca as novidades para os desenvolvedores.

Para saber mais sobre as novas APIs, leia o Relatório de diferenças entre APIs (link em inglês) ou visite a Referência da API do Android. As novas APIs estão destacadas para facilitar a visualização. Confira também as mudanças de comportamento do Android Q (para apps voltados ao Q e para todos os apps), assim como as mudanças de privacidade, para conhecer as áreas em que as alterações de plataforma podem afetar seus apps.

Melhorias na segurança

O Android Q apresenta vários recursos de segurança, resumidos nas seções a seguir.

Caixas de diálogo de autenticação biométrica aprimoradas

O Android Q lança as seguintes melhorias para as caixas de diálogo de autenticação biométrica unificada adicionadas ao Android 9:

Especificar os requisitos de confirmação do usuário

Agora, é possível fornecer uma dica que instrua o sistema a não solicitar confirmação do usuário depois que ele se autenticar usando uma modalidade biométrica implícita. Por exemplo, é possível informar ao sistema que nenhuma confirmação adicional deve ser pedida após um usuário fazer a autenticação facial.

Por padrão, o sistema requer confirmação do usuário. Normalmente, os usuários querem confirmar ações confidenciais ou de alto risco (por exemplo, ao fazer uma compra). No entanto, se você tiver determinadas ações de baixo risco para seu app, poderá dar uma dica para não exigir a confirmação do usuário, passando false para o método setConfirmationRequired(). Como essa sinalização é passada como uma dica para o sistema, ele poderá ignorar o valor se o usuário tiver alterado as configurações do sistema para autenticação biométrica.

Um exemplo de autenticação facial sem confirmação do usuário.

Figura 1. Autenticação facial sem confirmação do usuário

Um exemplo de autenticação facial que requer a confirmação do usuário.

Figura 2. Autenticação facial que requer a confirmação do usuário

Compatibilidade com substituto aprimorada para credenciais de dispositivo

Agora é possível instruir o sistema a permitir que um usuário se autentique usando o PIN, o padrão ou a senha do dispositivo, caso não consiga se autenticar usando a entrada biométrica por algum motivo. Para ativar essa compatibilidade com substituto, use o método setDeviceCredentialAllowed().

Se seu app usa createConfirmDeviceCredentialIntent() atualmente para substituir as credenciais do dispositivo, mude para o novo método.

Verificar se o dispositivo tem a funcionalidade biométrica

Também é possível verificar se um dispositivo é compatível com a autenticação biométrica antes de invocar BiometricPrompt usando o método canAuthenticate() na classe BiometricManager.

Executar código DEX incorporado diretamente no APK

Agora, você pode dizer à plataforma para executar o código DEX incorporado diretamente no arquivo APK do seu app. Essa opção evita um ataque caso um invasor consiga adulterar o código compilado localmente no dispositivo.

Para ativar esse recurso, defina o valor do atributo android:useEmbeddedDex como true no elemento <application> do arquivo manifest do app. Também é necessário criar um APK que contenha código DEX não compactado que o ART possa acessar diretamente. Para isso, adicione as seguintes opções ao seu arquivo de configuração Gradle ou Bazel:

Gradle

aaptOptions {
       noCompress 'dex'
    }
    

Bazel

    android_binary(
       ...,
       nocompress_extensions = [“.dex”],
    )
    

Compatibilidade com TLS 1.3

A implementação de TLS da plataforma agora é compatível com o TLS 1.3. O TLS 1.3 (em inglês) é uma revisão importante do padrão TLS, que inclui benefícios de desempenho e segurança aprimorada. Nossos comparativos de mercado indicam que o TLS 1.3 estabelece conexões seguras até 40% mais rápido do que o TLS 1.2.

O TLS 1.3 é ativado por padrão para todas as conexões TLS. É possível conseguir um SSLContext que tenha o TLS 1.3 desativado chamando SSLContext.getInstance("TLSv1.2"). Você também pode ativar ou desativar versões de protocolo em cada conexão, chamando setEnabledProtocols() em um objeto apropriado.

Aqui estão alguns detalhes importantes sobre nossa implementação do TLS 1.3:

  • Os conjuntos de criptografia do TLS 1.3 não podem ser personalizados. Os conjuntos de criptografia do TLS 1.3 compatíveis são sempre ativados quando o TLS 1.3 está ativado, e qualquer tentativa de desativá-los por meio de uma chamada para setEnabledCipherSuites() (em inglês) é ignorada.
  • Quando o TLS 1.3 é negociado, os HandshakeCompletedListeners são chamados antes que sejam adicionadas sessões ao cache de sessão (que é o oposto do TLS 1.2 e das outras versões anteriores).
  • Instâncias SSLEngine emitirão um SSLProtocolException em algumas circunstâncias em que anteriormente teriam emitido um SSLHandshakeException.
  • O modo 0-RTT não é compatível.

API pública do Conscrypt

O provedor de segurança Conscrypt agora inclui uma API pública para a funcionalidade TLS. Antes os usuários podiam acessar essa funcionalidade por meio de reflexão. No entanto, devido a restrições ao chamar APIs não públicas adicionadas ao Android P, ela foi colocada na lista cinza no Android Q e será ainda mais restrita nas versões futuras.

Esta atualização adiciona uma coleção de classes em android.net.ssl que contém métodos estáticos para acessar a funcionalidade não disponível nas APIs javax.net.ssl genéricas. Os nomes dessas classes podem ser inferidos como o plural da classe javax.net.ssl associada. Por exemplo, o código que opera em instâncias javax.net.ssl.SSLSocket pode usar métodos da nova classe android.net.ssl.SSLSockets.

Recursos de conectividade

O Android Q inclui várias melhorias relacionadas a rede e conectividade.

API de conexão de rede Wi-Fi

O Android Q passa a ser compatível com conexões ponto a ponto. Esse recurso permite que seu app solicite ao usuário a alteração do ponto de acesso ao qual o dispositivo está conectado usando WifiNetworkSpecifier para descrever as propriedades de uma rede solicitada. A conexão ponto a ponto é usada para fins que não fornecem rede, por exemplo, a configuração de bootstrap para dispositivos secundários, como o hardware do Chromecast e do Google Home.

Quando for usar essa API, você usará este fluxo:

  1. Crie um especificador de rede Wi-Fi usando o WifiNetworkSpecifier.Builder.

  2. Defina um filtro de rede para corresponder às redes às quais você pretende se conectar, assim como as credenciais necessárias.

  3. Decida uma combinação de SSID, SSID pattern, BSSID e BSSID pattern para configurar o filtro de rede em cada solicitação, que estará sujeita a estes requisitos:

    • Cada solicitação precisa fornecer ao menos um entre SSID, SSID pattern, BSSID e BSSID pattern.
    • Cada solicitação pode definir apenas um entre SSID e SSID pattern.
    • Cada solicitação pode definir apenas um entre BSSID e BSSID pattern.
  4. Adicione os especificadores à solicitação de rede, assim como uma instância NetworkCallback para acompanhar o status da solicitação.

    Se o usuário aceitar a solicitação, e a conexão à rede for bem-sucedida, NetworkCallback.onAvailable() será invocado no objeto de callback. Se o usuário negar a solicitação ou se a conexão à rede não for bem-sucedida, NetworkCallback.onUnavailable() será invocado no objeto de callback.

As conexões ponto a ponto não exigem permissões de localização ou Wi-Fi. A solicitação para se conectar a um dispositivo de mesmo nível exibe uma caixa de diálogo no mesmo dispositivo, na qual o usuário pode aceitar a solicitação de conexão.

Ignorar a aprovação do usuário

Depois que o usuário aprova uma rede para se conectar em resposta a uma solicitação de um app específico, o dispositivo armazena a aprovação para o ponto de acesso. Se o app fizer uma solicitação específica para se conectar a esse ponto de acesso novamente, o dispositivo ignorará a fase de aprovação do usuário e se conectará automaticamente à rede. Se o usuário decidir esquecer a rede enquanto estiver conectado a uma rede solicitada pela API, a aprovação armazenada para a combinação de app e rede será removida, e qualquer solicitação futura desse app precisará ser aprovada pelo usuário novamente. Se o app fizer uma solicitação não específica (por exemplo, com um padrão SSID ou BSSID), o usuário precisará aprovar a solicitação.

Amostra de código

A amostra de código a seguir mostra como se conectar a uma rede aberta com um prefixo SSID de "teste" e um OUI BSSID de "10:03:23":

Kotlin

    val specifier = WifiNetworkSpecifier.Builder()
        .setSsidPattern(PatternMatcher("test", PatternMatcher.PATTERN_PREFIX))
        .setBssidPattern(MacAddress.fromString("10:03:23:00:00:00"), MacAddress.fromString("ff:ff:ff:00:00:00"))
        .build()

    val request = NetworkRequest.Builder()
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        .setNetworkSpecifier(specifier)
        .build()

    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

    val networkCallback = object : ConnectivityManager.NetworkCallback() {
        ...
        override fun onAvailable(network: Network?) {
            // do success processing here..
        }

        override fun onUnavailable() {
            // do failure processing here..
        }
        ...
    }
    connectivityManager.requestNetwork(request, networkCallback)
    ...
    // Release the request when done.
    connectivityManager.unregisterNetworkCallback(networkCallback)
    

Java

    final NetworkSpecifier specifier =
      new WifiNetworkSpecifier.Builder()
      .setSsidPattern(new PatternMatcher("test", PatterMatcher.PATTERN_PREFIX))
      .setBssidPattern(MacAddress.fromString("10:03:23:00:00:00"), MacAddress.fromString("ff:ff:ff:00:00:00"))
      .build();

    final NetworkRequest request =
      new NetworkRequest.Builder()
      .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
      .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
      .setNetworkSpecifier(specifier)
      .build();

    final ConnectivityManager connectivityManager = (ConnectivityManager)
      context.getSystemService(Context.CONNECTIVITY_SERVICE);

    final NetworkCallback networkCallback = new NetworkCallback() {
      ...
      @Override
      void onAvailable(...) {
          // do success processing here..
      }

      @Override
      void onUnavailable(...) {
          // do failure processing here..
      }
      ...
    };
    connectivityManager.requestNetwork(request, networkCallback);
    ...
    // Release the request when done.
    connectivityManager.unregisterNetworkCallback(networkCallback);
    

API de sugestão de rede Wi-Fi

O Android Q passa a permitir que seu app adicione credenciais de rede para que um dispositivo seja conectado automaticamente a um ponto de acesso Wi-Fi. Você pode sugerir a que rede se conectar, usando WifiNetworkSuggestion. A plataforma escolhe qual ponto de acesso será aceito com base na entrada do seu app e de outros.

A amostra de código a seguir mostra como fornecer credenciais para uma rede aberta, uma rede WPA2 e uma rede WPA3:

Kotlin

    val suggestion1 = WifiNetworkSuggestion.Builder()
            .setSsid("test111111")
            .setIsAppInteractionRequired() // Optional (Needs location permission)
            .build()

    val suggestion2 = WifiNetworkSuggestion.Builder()
            .setSsid("test222222")
            .setWpa2Passphrase("test123456")
            .setIsAppInteractionRequired() // Optional (Needs location permission)
            .build()

    val suggestion3 = WifiNetworkSuggestion.Builder()
            .setSsid("test333333")
            .setWpa3Passphrase("test6789")
            .setIsAppInteractionRequired() // Optional (Needs location permission)
            .build()

    val suggestionsList = listOf(suggestion1, suggestion2, suggestion3)

    val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager

    val status = wifiManager.addNetworkSuggestions(suggestionsList);
    if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
        // do error handling here
    }

    // Optional (Wait for post connection broadcast to one of your suggestions)
    val intentFilter = IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);

    val broadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            if (!intent.action.equals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
                return;
            }
            // do post connect processing here
        }
    };
    context.registerReceiver(broadcastReceiver, intentFilter);
    

Java

    final WifiNetworkSuggestion suggestion1 =
      new WifiNetworkSuggestion.Builder()
      .setSsid("test111111")
      .setIsAppInteractionRequired() // Optional (Needs location permission)
      .build()

    final WifiNetworkSuggestion suggestion2 =
      new WifiNetworkSuggestion.Builder()
      .setSsid("test222222")
      .setWpa2Passphrase("test123456")
      .setIsAppInteractionRequired() // Optional (Needs location permission)
      .build()

    final WifiNetworkSuggestion suggestion3 =
      new WifiNetworkSuggestion.Builder()
      .setSsid("test333333")
      .setWpa3Passphrase("test6789")
      .setIsAppInteractionRequired() // Optional (Needs location permission)
      .build()

    final List<wifinetworksuggestion> suggestionsList =
      new ArrayList<wifinetworksuggestion> {{
        add(suggestion1);
        add(suggestion2);
        add(suggestion3);
      }};

    final WifiManager wifiManager =
      (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

    final int status = wifiManager.addNetworkSuggestions(suggestionsList);
    if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
    // do error handling here…
    }

    // Optional (Wait for post connection broadcast to one of your suggestions)
    final IntentFilter intentFilter =
      new IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);

    final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
      @Override
      public void onReceive(Context context, Intent intent) {
        if (!intent.getAction().equals(
          WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
          return;
        }
        // do post connect processing here..
      }
    };
    context.registerReceiver(broadcastReceiver, intentFilter);
    

As sugestões do app precisam ser aprovadas pelo usuário para que a plataforma inicie uma conexão com elas. Essa aprovação é fornecida pelo usuário em resposta a uma notificação na primeira vez em que a plataforma encontrar uma rede correspondente a uma das sugestões do app nos resultados da verificação. Quando a plataforma se conecta a uma das sugestões de rede, as configurações mostram um texto que atribui a conexão de rede ao app que fez a sugestão.

Lidar com desconexões do usuário

Se o usuário usar o seletor de Wi-Fi para se desconectar explicitamente de uma das sugestões da rede quando estiver conectado a ela, essa rede será colocada na lista de proibições por 24 horas. Durante esse período, a rede em questão não será considerada para conexão automática, mesmo se o app remover e adicionar novamente a sugestão dessa rede.

Alterar o status de aprovação para o app

Quando um usuário recusa a notificação de sugestão de rede, a permissão CHANGE_WIFI_STATE é removida do app. O usuário pode conceder essa aprovação posteriormente acessando o menu de controle de Wi-Fi (Config. > Apps e notificações > Acesso especial a apps > Controle de Wi-Fi > Nome do app).

Melhorias nos modos Wi-Fi de alto desempenho e baixa latência

O Android Q permite que você forneça uma sugestão ao modem usado para minimizar a latência.

Essa versão estende a API de bloqueio de Wi-Fi para realmente ser compatível com o modo de alto desempenho e o modo de baixa latência. A economia de energia com Wi-Fi é desativada para os modos de alto desempenho e baixa latência, e a otimização da latência pode ser ativada no modo de baixa latência, dependendo do suporte do modem.

O modo de baixa latência é ativado apenas quando o app que está adquirindo o bloqueio está sendo executado em primeiro plano e a tela está ativada. Esse modo é especialmente útil para apps de jogos em tempo real para dispositivos móveis.

Pesquisas especializadas no resolvedor de DNS

O Android Q adiciona compatibilidade nativa com DNS sobre TLS e com buscas DNS especializadas. Anteriormente, o resolvedor de DNS da plataforma era compatível com resoluções tipo A, que resolviam um endereço IP em relação a um nome de domínio sem fornecer detalhes sobre os serviços oferecidos nesse IP. Com essa atualização, as pesquisas SRV e NAPTR também passam a ser compatíveis.

O Android Q fornece aos desenvolvedores tanto pesquisas de texto simples padrão quanto um modo DNS sobre TLS.

Wi-Fi Easy Connect

O Android Q permite que você use o Easy Connect para fornecer credenciais de Wi-Fi a um dispositivo de mesmo nível, como uma substituição da WPS, que ficou obsoleta. Os apps podem integrar o Easy Connect à própria configuração e ao fluxo de provisionamento usando o intent ACTION_PROCESS_WIFI_EASY_CONNECT_URI. Esse intent requer um URI. O app de chamada pode recuperar o URI por meio de vários métodos, incluindo a leitura de um código QR de um adesivo ou tela, ou a busca por anúncios NFC ou Bluetooth LE.

Quando o URI estiver disponível, você poderá fornecer as credenciais de Wi-Fi com o intent ACTION_PROCESS_WIFI_EASY_CONNECT_URI. Isso permite que o usuário selecione uma rede Wi-Fi para compartilhar e transferir com segurança as credenciais.

O Easy Connect não requer permissões de localização ou Wi-Fi.

API de conexão Wi-Fi Direct

As classes de API WifiP2pConfig e WifiP2pManager têm atualizações no Android Q para serem compatíveis com recursos de conexão rápida Wi-Fi Direct, usando informações predeterminadas. Essas informações são compartilhadas por um canal lateral, como Bluetooth ou NFC.

O exemplo de código a seguir mostra como criar um grupo usando informações predeterminadas:

Kotlin

    val manager = getSystemService(Context.WIFI_P2P_SERVICE) as WifiP2pManager
    val channel = manager.initialize(this, mainLooper, null)

    // prefer 5G band for this group
    val config = WifiP2pConfig.Builder()
        .setNetworkName("networkName")
        .setPassphrase("passphrase")
        .enablePersistentMode(false)
        .setGroupOperatingBand(WifiP2pConfig.GROUP_OWNER_BAND_5GHZ)
        .build()

    // create a non-persistent group on 5GHz
    manager.createGroup(channel, config, null)
    

Java

    WifiP2pManager manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
    Channel channel = manager.initialize(this, getMainLooper(), null);

    // prefer 5G band for this group
    WifiP2pConfig config = new WifiP2pConfig.Builder()
    .setNetworkName("networkName")
    .setPassphrase("passphrase")
    .enablePersistentMode(false)
    .setGroupOperatingBand(WifiP2pConfig.GROUP_OWNER_BAND_5GHZ)
    .build();

    // create a non-persistent group on 5GHz
    manager.createGroup(channel, config, null);
    

Para entrar em um grupo usando credenciais, substitua manager.createGroup() pelo seguinte:

Kotlin

    manager.connect(channel, config, null)
    

Java

    manager.connect(channel, config, null);
    

Canais Orientados à Conexão (CoC) Bluetooth LE

O Android Q permite que seu app use conexões CoC BLE para transferir grandes fluxos de dados entre dois dispositivos BLE. Essa interface abstrai o Bluetooth e a mecânica de conectividade para simplificar a implementação.

Recursos de telefonia

O Android Q inclui várias melhorias relacionadas à telefonia.

Melhorias na qualidade das chamadas

O Android Q adiciona a capacidade de coletar informações sobre a qualidade das chamadas de Subsistema multimídia IP (IMS, na sigla em inglês) em andamento, incluindo a qualidade de e para a rede, em dispositivos compatíveis com o recurso.

Filtro de chamadas e identificador de chamadas

O Android Q oferece ao seu app meios para identificar chamadas que não estão no catálogo de endereços do usuário como possíveis chamadas de spam, e para que as chamadas de spam sejam rejeitadas de modo silencioso em nome do usuário. As informações sobre essas chamadas são registradas como chamadas bloqueadas no registro de chamadas para fornecer maior transparência ao usuário quando são chamadas perdidas. O uso dessa nova API elimina o requisito de receber permissões READ_CALL_LOG do usuário para fornecer os recursos de filtro de chamadas e identificador de chamadas.

API de serviço de redirecionamento de chamadas

O Android Q altera a forma como os intents de chamadas são tratados. A transmissão NEW_OUTGOING_CALL foi suspensa e substituída pela API CallRedirectionService. A API CallRedirectionService fornece interfaces para você modificar chamadas de saída feitas pela plataforma Android. Por exemplo, apps de terceiros podem cancelar chamadas e redirecioná-las por VoIP.

Melhorias na criação de arquivos no armazenamento externo

Além de introduzir a mudança no comportamento de privacidade do armazenamento com escopo, o Android Q oferece mais flexibilidade ao gravar arquivos e apresenta recursos para ajudar a influenciar onde esses arquivos são salvos em um dispositivo de armazenamento externo.

Status pendente para novos arquivos de mídia

O Android Q introduz a sinalização IS_PENDING, que dá ao seu app acesso exclusivo a um arquivo de mídia enquanto ele é gravado no disco.

O snippet de código a seguir mostra como usar a sinalização IS_PENDING ao criar uma nova imagem no seu app:

Kotlin

    val values = ContentValues().apply {
        put(MediaStore.Images.Media.DISPLAY_NAME, "IMG1024.JPG")
        put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
        put(MediaStore.Images.Media.IS_PENDING, 1)
    }

    val resolver = context.getContentResolver()
    val collection = MediaStore.Images.Media
            .getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
    val item = resolver.insert(collection, values)

    resolver.openFileDescriptor(item, "w", null).use { pfd ->
        // Write data into the pending image.
    }

    // Now that we're finished, release the "pending" status, and allow other apps
    // to view the image.
    values.clear()
    values.put(MediaStore.Images.Media.IS_PENDING, 0)
    resolver.update(item, values, null, null)
    

Java

    ContentValues values = new ContentValues();
    values.put(MediaStore.Images.Media.DISPLAY_NAME, "IMG1024.JPG");
    values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
    values.put(MediaStore.Images.Media.IS_PENDING, 1);

    ContentResolver resolver = context.getContentResolver();
    Uri collection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
    Uri item = resolver.insert(collection, values);

    try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(item, "w", null)) {
        // Write data into the pending image.
    } catch (IOException e) {
        e.printStackTrace();
    }

    // Now that we're finished, release the "pending" status, and allow other apps
    // to view the image.
    values.clear();
    values.put(MediaStore.Images.Media.IS_PENDING, 0);
    resolver.update(item, values, null, null);
    

Influência no local de armazenamento

O Android Q apresenta vários recursos para ajudar a organizar os arquivos que seu app contribui para o armazenamento externo.

Dicas de diretório

Quando seu app contribui com mídia em um dispositivo com o Android Q, a mídia é organizada com base no tipo, por padrão. Por exemplo, novos arquivos de imagem são colocados em um diretório de imagens por padrão.

Se seu app conhece um local específico onde os arquivos devem ser armazenados, como Pictures/MyVacationPictures, você pode configurar MediaColumns.RELATIVE_PATH para que forneça ao sistema uma dica de onde armazenar os arquivos recém-gravados. Da mesma forma, você pode mover arquivos no disco durante uma chamada para update() alterando MediaColumns.RELATIVE_PATH ou MediaColumns.DISPLAY_NAME.

Seleção de dispositivo

No Android 9 (nível de API 28) e versões anteriores, todos os arquivos salvos em dispositivos de armazenamento externos aparecem sob um único volume, chamado external. Por outro lado, o Android Q fornece a cada dispositivo de armazenamento externo um nome de volume exclusivo. Esse novo sistema de nomenclatura ajuda você a organizar e indexar os conteúdos de maneira eficiente, além de fornecer controle sobre onde novos conteúdos são armazenados.

O principal dispositivo de armazenamento compartilhado é sempre chamado de VOLUME_EXTERNAL_PRIMARY. Você pode encontrar outros volumes chamando MediaStore.getExternalVolumeNames().

Para consultar, inserir, atualizar ou excluir um volume específico, passe o nome do volume a qualquer um dos métodos getContentUri() disponíveis na API MediaStore, como mostrado no snippet de código a seguir:

    // Publish an audio file onto a specific external storage device.
    val values = ContentValues().apply {
        put(MediaStore.Audio.Media.RELATIVE_PATH, "Music/My Album/My Song")
        put(MediaStore.Audio.Media.DISPLAY_NAME, "My Song.mp3")
    }

    // Assumes that the storage device of interest is the 2nd one
    // that your app recognizes.
    val volumeNames = MediaStore.getExternalVolumeNames(context)
    val selectedVolumeName = volumeNames[1]
    val collection = MediaStore.Audio.Media.getContentUri(selectedVolumeName)
    val item = resolver.insert(collection, values)
    

Mídia e gráficos

O Android Q apresenta os novos recursos e APIs de mídia e gráficos a seguir:

Captura de reprodução de áudio

O Android Q oferece aos apps a capacidade de capturar a reprodução de áudio de outros apps. Para mais informações, consulte Captura de reprodução.

API Native MIDI

A API Android Native MIDI (AMidi) oferece aos desenvolvedores de apps a capacidade de enviar e receber dados MIDI com código C/C++, promovendo uma integração maior com a lógica de controle/áudio C/C++ e minimizando a necessidade de JNI.

Para mais informações, consulte API Android Native MIDI.

Melhorias no MediaCodecInfo

Há novos métodos no MediaCodecInfo que revelam mais informações sobre um codec:

isSoftwareOnly()
Retorna true se o codec for executado apenas no software. Os codecs de software não garantem o desempenho da renderização.
isHardwareAccelerated()
Retorna true se um codec for acelerado pelo hardware.
isVendor()
Retorna true se o codec for fornecido pelo fornecedor do dispositivo ou false, se fornecido pela plataforma Android.
isAlias()
MediaCodecList pode conter entradas adicionais para o mesmo codec subjacente usando um nome de codec alternativo (alias). Esse método retorna true se o codec da entrada for um alias para outro codec.

Além disso, MediaCodec.getCanonicalName() retorna o nome do codec subjacente para codecs criados por meio de um alias.

Pontos de desempenho

Um ponto de desempenho representa a capacidade de um codec de renderizar vídeo em uma altura, largura e taxa de quadros específicas. Por exemplo, o ponto de desempenho UHD_60 representa um vídeo em Ultra HD (3.840 x 2.160 pixels) renderizado a 60 quadros por segundo.

O método MediaCodecInfo.VideoCapabilities.getSupportedPerformancePoints() retorna uma lista de entradas PerformancePoint que o codec pode renderizar ou capturar.

Você pode verificar se determinado PerformancePoint abrange outro ponto de desempenho chamando PerformancePoint.covers(PerformancePoint). Por exemplo, UHD_60.covers(UHD_50) retorna true.

Uma lista de pontos de desempenho é fornecida para todos os codecs acelerados por hardware. Ela pode ser uma lista vazia se o codec não atender ao ponto de desempenho padrão mais baixo.

Observação: os dispositivos que foram atualizados para o Android Q sem atualizar a imagem do fornecedor não terão dados de ponto de desempenho, porque esses dados vêm do HAL do fornecedor. Nesse caso, getSupportedPerformancePoints() retorna "null".

ANGLE

Com o lançamento do Android Q, os desenvolvedores e parceiros do Android têm a opção de execução com o ANGLE (em inglês), um projeto da organização do Chrome que sobrepõe o ES sobre o Vulkan, em vez de usar o driver de ES oferecido pelo fornecedor.

Para ver mais detalhes, consulte ANGLE.

API Thermal

Quando os dispositivos ficam muito quentes, eles podem limitar a CPU e/ou a GPU, e isso pode afetar apps e jogos de maneiras inesperadas. Os apps que usam gráficos complexos, computação pesada ou atividade de rede sustentada têm maior probabilidade de causar problemas, e esses podem variar entre dispositivos com base em frequências de chipset e núcleo, níveis de integração e também no empacotamento e formato do dispositivo.

Agora, no Android Q, os apps e jogos podem usar uma API Thermal para monitorar as alterações no dispositivo e tomar medidas para manter um uso de energia mais baixo para restaurar a temperatura normal. Os apps registram um listener no PowerManager, por meio do qual o sistema informa o status térmico contínuo, que varia de leve e moderado a grave, crítico, de emergência e de desligamento.

Quando o dispositivo relata estresse térmico, os apps e jogos podem ajudar, colocando em espera aleatória as atividades em andamento para reduzir o uso de energia de várias maneiras. Por exemplo, apps de streaming podem reduzir a resolução/taxa de bits ou o tráfego de rede, um app de câmera pode desativar o flash ou a melhoria intensiva de imagens, um jogo pode reduzir a frame rate ou o mosaico de polígono, um app de mídia pode reduzir o volume do alto-falante e um app de mapas desativar o GPS.

A API Thermal exige uma nova camada HAL de dispositivo. No momento, ela é compatível com dispositivos Pixel com Android Q, e estamos trabalhando com nossos parceiros fabricantes de dispositivos para oferecer maior compatibilidade ao ecossistema o mais rápido possível.

Câmera e imagens

O Android Q introduz os novos recursos de câmera e imagem a seguir:

Compatibilidade com câmera monocromática

O Android 9 (API de nível 28) lançou pela primeira vez o recurso de câmera monocromática. O Android Q inclui várias melhorias de compatibilidade com a câmera monocromática:

  • Compatibilidade com o novo formato de fluxo Y8 para melhorar a eficiência da memória.
  • Compatibilidade com captura em DNG bruto monocromático.
  • Introdução das enumerações MONO e NIR CFA para distinguir entre câmeras monocromáticas comuns e câmeras infravermelhas próximas.

É possível usar esse recurso para capturar uma imagem monocromática nativa. Um dispositivo lógico com várias câmeras pode usar uma câmera monocromática como uma subcâmera física para melhorar a qualidade de imagens com pouca luz.

Formato Profundidade dinâmica

A partir do Android Q, as câmeras podem armazenar os dados de profundidade da imagem em um arquivo separado, usando um novo esquema chamado Formato Profundidade dinâmica (DDF, na sigla em inglês). Os apps podem solicitar a imagem JPG e os metadados de profundidade, usando essas informações para aplicar o desfoque desejado no pós-processamento sem modificar os dados da imagem original.

Para ler a especificação do novo formato, consulte Formato Profundidade dinâmica (link em inglês).

Formato de arquivo de imagem de alta eficiência

O formato de arquivo de imagem de alta eficiência (HEIF, na sigla em inglês) é um formato padrão de imagem e vídeo que introduz uma codificação de qualidade superior e menor tamanho de arquivo se comparado a outros formatos de arquivo.

Para ver mais informações sobre esse formato de arquivo, consulte HEIC.

Melhorias na funcionalidade de várias câmeras

O Android Q melhora a fusão de várias câmeras em uma única câmera lógica, um recurso introduzido no Android 9 (API de nível 28). Foram adicionados à API Camera2:

API de serviços de acessibilidade

O Android Q apresenta os seguintes novos recursos e APIs de serviços de acessibilidade:

Sinalização de chave de entrada AccessibilityNodeInfo

No Android Q, o AccessibilityNodeInfo foi aprimorado com uma nova sinalização que indica se ele representa uma chave de entrada de texto. É possível acessar essa sinalização usando o método AccessibilityNodeInfo.isTextEntryKey().

Feedback falado da caixa de diálogo de acessibilidade

Quando um serviço de acessibilidade exigir que o usuário repita o atalho de acessibilidade para iniciar o serviço, a caixa de diálogo agora poderá ser acompanhada por um prompt de conversão de texto em voz, se o serviço solicitar.

Atalho de acessibilidade para teclados físicos

No Android Q, os usuários agora podem acionar o atalho de acessibilidade em um teclado físico pressionando Control + Alt + Z.

Melhoria do controlador de teclado virtual

No Android Q, os serviços de acessibilidade agora podem solicitar que o teclado virtual seja exibido mesmo quando o dispositivo detectar um teclado físico conectado. Os usuários podem modificar esse comportamento.

Tempos limite de acessibilidade definidos pelo usuário

O Android Q traz o método de API AccessibilityManager.getRecommendedTimeoutMillis(), que é compatível com tempos limite definidos pelo usuário para elementos de IU de acessibilidade interativos e não interativos. O valor de retorno é influenciado pelas preferências do usuário e pelas APIs de serviço de acessibilidade.

Melhorias no preenchimento automático

O Android Q contém as seguintes melhorias no serviço de preenchimento automático.

Agora é possível usar a sinalização FillRequest.FLAG_COMPATIBILITY_MODE_REQUEST para determinar se uma solicitação de preenchimento automático foi gerada por meio do modo de compatibilidade.

Salvar nome de usuário e senha simultaneamente

Agora é possível oferecer compatibilidade a casos em que um app usa várias atividades para exibir nome de usuário, senha e outros campos, por meio da sinalização SaveInfo.FLAG_DELAY_SAVE.

Interação do usuário com a IU de salvamento

Agora também é possível exibir e ocultar um campo de senha em uma caixa de diálogo de salvamento. Para isso, é preciso definir um listener de ação na caixa de diálogo e alterar a visibilidade da visualização remota de senha correspondente.

Compatibilidade com atualização de conjuntos de dados

O preenchimento automático agora pode atualizar as senhas existentes. Por exemplo, se um usuário já tiver armazenado uma senha e salvar uma nova, o preenchimento automático solicitará que o usuário atualize a senha existente em vez de salvar uma nova.

Melhorias de classificação de campo

O Android Q contém as seguintes melhorias para a API de classificação de campo.

Construtor UserData.Builder

O construtor UserData.Builder foi alterado para se alinhar melhor ao padrão Builder.

Permitir que um valor seja mapeado para vários tipos de códigos de categoria

Ao usar UserData.Builder no Android Q, será possível mapear um valor para vários tipos de códigos de categoria. Nas versões anteriores, uma exceção era gerada se um valor fosse adicionado mais de uma vez.

Compatibilidade aprimorada com números de cartão de crédito

A classificação de campo agora detecta números de quatro dígitos como os últimos quatro dígitos de um número de cartão de crédito.

Compatibilidade com a classificação de campo específico do app

O Android Q inclui FillResponse.setUserData(), que permite definir dados do usuário específicos do app por duração da sessão. Isso permite que o serviço de preenchimento automático detecte tipos de campos com conteúdo específico do app.

Controles da IU e do sistema

O Android Q traz as seguintes melhorias da interface do usuário:

Compatibilidade com limites do JVMTI PopFrame

O Android Q passa a ser compatível com o recurso can_pop_frames (em inglês) na implementação da JVMTI do Android. Durante a depuração, esse recurso permite que você execute novamente as funções após pausar em um ponto de interrupção e ajustar locais, globais ou a implementação de uma função. Para saber mais, consulte a página de referência do Pop Frame (em inglês) da Oracle.

API Surface control

O Android Q oferece uma API SurfaceControl para acesso de baixo nível ao compositor do sistema (SurfaceFlinger). Para a maioria dos usuários, o SurfaceView é a maneira correta de usar o compositor. A API SurfaceControl pode ser útil em certos casos, como:

  • Sincronização de várias superfícies
  • Incorporação de superfície de processo cruzado
  • Gerenciamento de ciclo de vida de nível inferior

A API SurfaceControl está disponível nas vinculações do SDK e do NDK. A implementação do NDK inclui uma API para troca manual de buffers com o compositor. Essa é uma alternativa para os usuários que se deparam com limitações do BufferQueue.

Detecção de renderizador inativo WebView

O Android Q introduz uma nova classe abstrata, WebViewRenderProcessClient, que os apps podem usar para detectar se um WebView deixou de responder. Para usar essa classe:

  1. Defina sua própria subclasse e implemente os onRenderProcessResponsive() e onRenderProcessUnresponsive() dela.
  2. Anexe uma instância do WebViewRenderProcessClient a um ou mais objetos WebView.
  3. Se o WebView parar de responder, o sistema chamará o método onRenderProcessUnresponsive() do cliente, passando WebView e WebViewRenderProcess. Se o WebView for de processo único, o parâmetro WebViewRenderProcess será nulo. Seu app pode tomar as medidas adequadas, como mostrar uma caixa de diálogo ao usuário perguntando se ele quer interromper o processo de renderização.

Se o WebView permanecer sem resposta, o sistema chamará onRenderProcessUnresponsive() periodicamente (uma vez a cada cinco segundos, no máximo), mas não tomará outra ação. Se o WebView parar de responder novamente, o sistema chamará onRenderProcessResponsive() uma vez.

Painéis de configurações

O Android Q apresenta os Painéis de configurações, uma API que permite aos apps mostrar as configurações para os usuários no contexto dos apps. Isso evita que os usuários precisem acessar as Configurações para alterar itens como NFC ou Dados móveis para usar o app.

Figura 1. O usuário tenta abrir uma página da Web enquanto o dispositivo não está conectado à rede. O Chrome exibe o painel de configurações de Conectividade com a Internet.

Figura 2. O usuário pode ativar o Wi-Fi e selecionar uma rede sem sair do app Chrome.

Por exemplo, suponha que um usuário abra um navegador da Web enquanto o dispositivo está no modo avião. Antes do Android Q, o app só podia exibir uma mensagem genérica solicitando ao usuário que abrisse as Configurações para restaurar a conexão. Com o Android Q, o app do navegador pode exibir um painel in-line mostrando as principais configurações de conectividade, como o modo avião, o Wi-Fi (incluindo redes próximas) e dados móveis. Com esse painel, os usuários podem restaurar a conectividade sem sair do app.

Para exibir um painel de configurações, dispare um intent com uma das novas ações do Settings.Panel:

Kotlin

    val panelIntent = Intent(Settings.Panel.settings_panel_type)
    startActivityForResult(panelIntent)
    

Java

    Intent panelIntent = new Intent(Settings.Panel.settings_panel_type);
    startActivityForResult(panelIntent);
    

settings_panel_type pode ser um dos seguintes:

ACTION_INTERNET_CONNECTIVITY
Mostra as configurações relacionadas à conectividade com a Internet, como o modo avião, Wi-Fi e dados móveis.
ACTION_WIFI:
Mostra as configurações de Wi-Fi, mas não mostra as outras configurações de conectividade. Isso é útil para apps que precisam de uma conexão Wi-Fi para fazer uploads ou downloads grandes.
ACTION_NFC
Mostra todas as configurações relacionadas à comunicação a curta distância (NFC, na sigla em inglês).
ACTION_VOLUME
Mostra as configurações de volume para todos os streams de áudio.

Estamos planejando lançar um wrapper AndroidX para essa funcionalidade. Quando chamado em dispositivos com Android 9 (API de nível 28) ou anterior, o wrapper abrirá a página mais adequada no app Configurações.

Melhorias de compartilhamento

O Android Q oferece várias melhorias para o compartilhamento. Para mais informações, consulte Melhorias de compartilhamento no Android Q.

Tema escuro

O Android Q oferece um novo tema escuro que se aplica tanto à IU do sistema Android quanto aos apps em execução no dispositivo. Para mais informações, consulte Tema escuro.

Tipos de serviços em primeiro plano

O Android Q introduz um novo atributo de manifest XML, foregroundServiceType, que pode ser incluído na definição de vários serviços específicos. É possível, embora raramente seja adequado, atribuir vários tipos de serviços em primeiro plano a um serviço específico.

A tabela a seguir mostra os diferentes tipos de serviços em primeiro plano e os serviços em que é apropriado declarar um tipo específico:

Tipo de serviço em primeiro plano Exemplo de caso de uso para um serviço que deve declarar esse tipo
connectedDevice Acompanhar um monitor wearable de atividades físicas
dataSync Fazer o download de arquivos de uma rede
location Continuar uma ação iniciada pelo usuário
mediaPlayback Tocar um livro de áudio, podcast ou música
mediaProjection Gravar um vídeo da tela do dispositivo durante um curto período de tempo
phoneCall Lidar com chamadas em curso

Kotlin

O Android Q inclui as seguintes atualizações para o desenvolvimento em Kotlin.

Anotações de valores nulos para APIs do libcore

O Android Q melhora a cobertura de anotações de valores nulos no SDK para as APIs do libcore. Essas anotações permitem que os desenvolvedores de apps que estão usando análise de valores nulos do Kotlin ou Java no Android Studio recebam informações de nulidade ao interagir com essas APIs.

Normalmente, violações de contratos de nulidade no Kotlin geram erros de compilação. Para garantir a compatibilidade com o código existente, as novas anotações são limitadas a @RecentlyNullable e @RecentlyNonNull. Isso significa que as violações de nulidade geram avisos, em vez de erros.

Além disso, todas as anotações @RecentlyNullable ou @RecentlyNonNull que foram adicionadas no Android 9 estão mudando para @Nullable e @NonNull, respectivamente. Isso significa que as violações de nulidade agora geram erros, em vez de avisos.

Para mais informações sobre alterações de anotações, consulte O SDK do Android Pie agora é mais compatível com Kotlin (em inglês) no blog Android Developers.

NDK

O Android Q inclui as alterações do NDK descritas a seguir.

Depuração aprimorada da propriedade do descritor de arquivo

O Android Q adiciona o fdsan, que ajuda a localizar e corrigir problemas de propriedade de descritor de arquivos com mais facilidade.

Bugs relacionados ao manuseio incorreto da propriedade do descritor de arquivo, que tendem a se manifestar como use-after-close e double-close, são análogos aos bugs de alocação de memória use-after-free e double-free, mas tendem a ser muito mais difíceis de diagnosticar e corrigir. O fdsan tenta detectar e/ou evitar o mau gerenciamento do descritor de arquivo aplicando a propriedade do descritor de arquivo.

Para mais informações sobre falhas relacionadas a esses problemas, consulte Erro detectado pelo fdsan (em inglês). Para mais informações sobre o fdsan, veja a página do Googlesource sobre fdsan (em inglês).

TLS ELF

Apps criados usando o NDK com uma API de nível 29, no mínimo, não precisam mais usar emutls, mas podem usar o TLS ELF. A compatibilidade com o vinculador dinâmico e estático foi adicionada para dar suporte ao novo método de manipulação de variáveis locais de thread.

Para apps criados para a API de nível 28 e anteriores, foram implementadas melhorias para que o libgcc/compiler-rt resolva alguns problemas de emutls.

Para mais informações, consulte Alterações no Android para desenvolvedores do NDK (em inglês).

Tempo de execução

O Android Q inclui a mudança no tempo de execução descrita a seguir.

Acionamento de coleta de lixo baseada em Mallinfo

Quando pequenos objetos Java de plataforma fazem referência a objetos grandes no heap C++, os objetos C++ podem ser frequentemente recuperados apenas quando o objeto Java é coletado e, por exemplo, finalizado. Nas versões anteriores, a plataforma estimava os tamanhos de muitos objetos C++ associados a objetos Java. Essa estimativa nem sempre era precisa e, ocasionalmente, resultava em um aumento significativo no uso de memória, já que a plataforma não coletava lixo quando deveria.

No Android Q, o coletor de lixo (GC, na sigla em inglês) rastreia o tamanho total do heap alocado pelo sistema malloc(), garantindo que grandes alocações malloc() sejam sempre incluídas nos cálculos de acionamento de GC. Os apps que intercalam um grande número de alocações de C++ com a execução de Java podem ter um aumento na frequência de coleta de lixo como consequência. Outros apps podem ter uma pequena redução.

Teste e depuração

O Android Q inclui as melhorias em testes e depuração descritas a seguir.

Melhorias na geração de traces do sistema no dispositivo

Agora é possível especificar limites para o tamanho e a duração de um trace ao gerar um trace do sistema no dispositivo. Quando você especifica um desses valores, o sistema gera um trace longo, copiando periodicamente o buffer correspondente no arquivo de destino enquanto o trace é gravado. O trace é concluído quando os limites de tamanho ou duração especificados são atingidos.

Utilize esses parâmetros adicionais para testar diferentes casos de uso que você testaria com um trace padrão. Por exemplo, você pode diagnosticar um bug de desempenho que só ocorre depois que o app é executado por um longo período. Nesse caso, você poderia gerar um trace longo durante um dia inteiro e, depois, analisar o programador de CPU, a atividade do disco, as linhas de execução do app e outros dados no relatório para ajudar a determinar a causa do bug.

Melhorias no TextClassifier

O Android Q oferece funcionalidade adicional de classificação de texto na interface TextClassifier.

Detecção de idioma

Agora, o TextClassifier apresenta o método detectLanguage(). Esse método funciona de forma semelhante aos métodos de classificação existentes, recebendo um objeto TextLanguage.Request e retornando um objeto TextLanguage.

O novo objeto TextLanguage consiste em uma lista de pares ordenados. Cada par tem uma localidade e um valor de confiabilidade correspondente para a amostra de texto solicitada.

Sugestões de ações de conversa

Agora, o TextClassifier apresenta o método suggestConversationActions(). Esse método funciona de forma semelhante aos métodos de classificação existentes, recebendo um objeto ConversationActions.Request e retornando um objeto ConversationActions.

O novo objeto ConversationActions consiste em uma lista de objetos ConversationAction. Cada objeto ConversationAction inclui uma possível ação sugerida e o valor de confiabilidade dela.

Respostas inteligentes/ações em notificações

O Android 9 introduziu a capacidade de exibir respostas sugeridas dentro de uma notificação. A partir do Android Q, as notificações também podem incluir sugestões de ações baseadas em intents. Além disso, o sistema agora pode gerar essas sugestões de modo automático. Os apps ainda podem fornecer as próprias sugestões ou recusar sugestões geradas pelo sistema.

A API usada para gerar essas respostas faz parte do TextClassifier e também foi diretamente exposta aos desenvolvedores no Android Q. Para mais informações, leia a seção sobre melhorias no TextClassifier.

Se o app fornecer sugestões próprias, a plataforma não gerará sugestões automáticas. Se você não quiser que as notificações do seu app exibam respostas ou ações sugeridas, desative as respostas e ações geradas pelo sistema usando setAllowGeneratedReplies() e setAllowSystemGeneratedContextualActions().