Recursos e APIs do Android 8.1

O Android 8.1 (API nível 27) apresenta uma variedade de novos recursos e funções para usuários e desenvolvedores. Este documento destaca as novidades para os desenvolvedores.

Android Oreo (versão Go)

O Android Go é nossa iniciativa para otimizar a experiência do Android para bilhões de pessoas que estão começando a acessar a Internet em todo o mundo. A partir do Android 8.1, estamos tornando o Android uma ótima plataforma para dispositivos básicos. Veja os recursos da configuração do Android Oreo (edição Go):

  • Otimizações de memória. Melhor uso da memória em toda a plataforma para garantir que os aplicativos possam ser executados com eficiência em dispositivos com 1 GB ou menos de RAM.
  • Opções de segmentação flexíveis. Novas constantes de recursos de hardware para permitir que você segmente a distribuição dos seus apps para dispositivos com memória RAM normal ou baixa por meio do Google Play.
  • Google Play.Embora todos os apps estejam disponíveis em dispositivos com o Android Oreo, o Google Play dará visibilidade a apps otimizados especificamente pelos desenvolvedores para oferecer uma ótima experiência a bilhões de pessoas seguindo as diretrizes de criação para bilhões.

Atualizamos as diretrizes de criação para bilhões com orientações adicionais sobre como otimizar aplicativos para dispositivos com o Android Oreo (edição Go). Para a maioria dos desenvolvedores, otimizar o APK existente ou usar o recurso de Múltiplos APKs do Google Play para destinar uma versão do APK para dispositivos com pouca memória RAM é a melhor maneira de se preparar para dispositivos Android Oreo (edição Go). Lembre-se de que tornar seu app mais leve e eficiente ajuda todo o público, independentemente do dispositivo.

API Neural Networks

A API Neural Networks oferece computação acelerada e inferência para frameworks de aprendizado de máquina no dispositivo, como o TensorFlow Lite (biblioteca de ML multiplataforma para dispositivos móveis do Google), Caffe2 e outros. Visite o repositório de código aberto TensorFlow Lite para downloads e documentos. O TensorFlow Lite funciona com a API Neural Networks para executar modelos como o MobileNets, o Inception v3 e o Smart Reply de maneira eficiente no seu dispositivo móvel.

Atualizações do framework de preenchimento automático

O Android 8.1 (nível de API 27) oferece vários aprimoramentos ao framework de preenchimento automático que você pode incorporar nos seus aplicativos.

A classe BaseAdapter agora inclui o método setAutofillOptions(), que permite fornecer representações de string dos valores em um adaptador. Isso é útil para controles giratórios que geram dinamicamente os valores nos próprios adaptadores. Por exemplo, você pode usar o método setAutofillOptions() para fornecer uma representação de string da lista de anos que os usuários podem escolher como parte de uma data de validade de cartão de crédito. Os serviços de preenchimento automático podem usar a representação de string para preencher apropriadamente as visualizações que precisam dos dados.

Além disso, a classe AutofillManager inclui o método notifyViewVisibilityChanged(View, int, boolean), que você pode chamar para notificar o framework sobre alterações na visibilidade de uma visualização em uma estrutura virtual. Há também uma sobrecarga do método para estruturas não virtuais. No entanto, frameworks não virtuais geralmente não exigem que você notifique explicitamente o framework, porque o método já é chamado pela classe View.

O Android 8.1 também oferece aos serviços de preenchimento automático maior capacidade de personalizar a economia da IU ao adicionar compatibilidade com CustomDescription and Validator em SaveInfo.

As descrições personalizadas são úteis para ajudar o serviço de preenchimento automático a esclarecer o que está sendo salvo. Por exemplo, quando a tela contém um cartão de crédito, ele pode exibir um logotipo do banco, os últimos quatro dígitos do número do cartão e a data de vencimento. Para saber mais, consulte a classe CustomDescription.

Objetos Validator são usados para evitar a exibição da IU de preenchimento automático quando a condição do validador não é cumprida. Para saber mais, consulte a classe Validator e as subclasses LuhnChecksumValidator e RegexValidator.

Notificações

O Android 8.1 inclui as seguintes alterações nas notificações:

  • Os aplicativos agora só podem emitir sons de notificação uma vez por segundo. Os sons de notificação que excedem essa taxa não são colocados na fila e são perdidos. Essa alteração não afeta outros aspectos do comportamento de notificação e as mensagens de notificação ainda são publicadas conforme o esperado.
  • NotificationListenerService e ConditionProviderService não são compatíveis com dispositivos com pouca memória RAM e que retornam true quando ActivityManager.isLowRamDevice() é chamado.

Atualização do EditText

A partir do nível 27 de API, o método EditText.getText() retorna um Editable. Anteriormente, ele retornava CharSequence. Essa alteração é compatível com versões anteriores porque o Editable implementa o CharSequence.

A interface Editable fornece funcionalidade adicional valiosa. Por exemplo, como o Editable também implementa a interface do Spannable, você pode aplicar marcação ao conteúdo dentro de uma instância do EditText.

Ações programáticas de navegação segura

Ao usar a implementação do WebView da API Safe Browsing, seu aplicativo pode detectar quando uma instância do WebView tenta navegar para um URL que o Google classificou como ameaça conhecida. Por padrão, o WebView mostra um intersticial que avisa os usuários sobre a ameaça conhecida. Essa tela dá aos usuários a opção de carregar o URL mesmo assim ou de retornar à página anterior segura.

No Android 8.1, é possível definir de forma programática como o aplicativo responde a uma ameaça conhecida:

  • Você pode controlar se seu aplicativo reporta as ameaças conhecidas para o Navegação segura.
  • Seu aplicativo pode executar uma ação específica automaticamente, como voltar para um local seguro, sempre que encontrar um URL que o Navegação segura tenha classificado como ameaça conhecida.

Observação: para uma proteção ideal contra ameaças conhecidas, aguarde até inicializar o Navegação segura antes de chamar o método loadUrl() de um objeto WebView.

O snippet de código a seguir mostra como você pode instruir as instâncias de WebView do seu aplicativo para que sempre voltem a um local seguro após encontrar uma ameaça conhecida:

AndroidManifest.xml

    <manifest>
        <application>
            ...
            <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
                       android:value="true" />
        </application>
    </manifest>

MyWebActivity.java

Kotlin

    private var superSafeWebView: WebView? = null
    private var safeBrowsingIsInitialized: Boolean = false

    // ...

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        superSafeWebView = WebView(this).apply {
            webViewClient = MyWebViewClient()
            safeBrowsingIsInitialized = false
            startSafeBrowsing(this@SafeBrowsingActivity, { success ->
                safeBrowsingIsInitialized = true
                if (!success) {
                    Log.e("MY_APP_TAG", "Unable to initialize Safe Browsing!")
                }
            })
        }
    }
    

Java

    private WebView superSafeWebView;
    private boolean safeBrowsingIsInitialized;

    // ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        superSafeWebView = new WebView(this);
        superSafeWebView.setWebViewClient(new MyWebViewClient());
        safeBrowsingIsInitialized = false;

        superSafeWebView.startSafeBrowsing(this, new ValueCallback<Boolean>() {
            @Override
            public void onReceiveValue(Boolean success) {
                safeBrowsingIsInitialized = true;
                if (!success) {
                    Log.e("MY_APP_TAG", "Unable to initialize Safe Browsing!");
                }
            }
        });
    }
    

MyWebViewClient.java

Kotlin

    class MyWebViewClient : WebViewClient() {
        // Automatically go "back to safety" when attempting to load a website that
        // Safe Browsing has identified as a known threat. An instance of WebView
        // calls this method only after Safe Browsing is initialized, so there's no
        // conditional logic needed here.
        override fun onSafeBrowsingHit(
                view: WebView,
                request: WebResourceRequest,
                threatType: Int,
                callback: SafeBrowsingResponse
        ) {
            // The "true" argument indicates that your app reports incidents like
            // this one to Safe Browsing.
            callback.backToSafety(true)
            Toast.makeText(view.context, "Unsafe web page blocked.", Toast.LENGTH_LONG).show()
        }
    }
    

Java

    public class MyWebViewClient extends WebViewClient {
        // Automatically go "back to safety" when attempting to load a website that
        // Safe Browsing has identified as a known threat. An instance of WebView
        // calls this method only after Safe Browsing is initialized, so there's no
        // conditional logic needed here.
        @Override
        public void onSafeBrowsingHit(WebView view, WebResourceRequest request,
                int threatType, SafeBrowsingResponse callback) {
            // The "true" argument indicates that your app reports incidents like
            // this one to Safe Browsing.
            callback.backToSafety(true);
            Toast.makeText(view.getContext(), "Unsafe web page blocked.",
                    Toast.LENGTH_LONG).show();
        }
    }
    

Extrator de miniaturas de vídeos

A classe MediaMetadataRetriever tem um novo método, getScaledFrameAtTime(), que localiza um quadro próximo a determinada posição de tempo e retorna um bitmap com a mesma proporção do quadro de origem, mas dimensionado para se ajustar a um retângulo de largura e altura especificadas. Isso é útil para gerar imagens em miniatura de vídeos.

Recomendamos usar esse método em vez de getFrameAtTime(), que pode desperdiçar memória retornando um bitmap com a mesma resolução do vídeo de origem. Por exemplo, um quadro de um vídeo 4K seria um bitmap de 16 MB, muito maior que o necessário para uma imagem em miniatura.

API de memória compartilhada

O Android 8.1 (API level 27) introduz uma nova API SharedMemory. Essa classe permite criar, mapear e gerenciar uma instância anônima do SharedMemory. Você pode definir a proteção de memória em um objeto SharedMemory para leitura e/ou gravação, e, como o objeto SharedMemory é Parcelable, você pode facilmente passá-lo para outro processo por meio da linguagem AIDL.

A API SharedMemory interopera com o recurso ASharedMemory no NDK. ASharedMemory fornece acesso a um descritor de arquivo, que pode então ser mapeado para leitura e gravação. É uma ótima maneira de compartilhar grandes quantidades de dados entre aplicativos ou entre vários processos em um único aplicativo.

API WallpaperColors

O Android 8.1 (API de nível 27) permite que seu plano de fundo interativo forneça informações de cor à IU do sistema. Faça isso criando um objeto WallpaperColors de um bitmap, um drawable ou usando três cores selecionadas manualmente. Você também pode recuperar essas informações de cor.

Para criar um objeto WallpaperColors, siga um destes procedimentos:

  • Para criar um objeto WallpaperColors usando três cores, crie uma instância da classe WallpaperColors passando a cor primária, a secundária e a terciária. A cor primária não pode ser nula.
  • Para criar um objeto WallpaperColors de um bitmap, chame o método fromBitmap() passando a origem do bitmap como parâmetro.
  • Para criar um objeto WallpaperColors a partir de um drawable, chame o método fromDrawable() passando a origem do drawable como parâmetro.

Para recuperar os detalhes das cores primária, secundária ou terciária do plano de fundo, chame os seguintes métodos:

Para notificar o sistema sobre quaisquer alterações significativas de cor no seu plano de fundo interativo, chame o método notifyColorsChanged(). Esse método aciona um evento de ciclo de vida onComputeColors(), em que você tem a oportunidade de fornecer um novo objeto WallpaperColors.

Para adicionar um listener para alterações de cor, chame o método addOnColorsChangedListener(). Também é possível chamar o método getWallpaperColors() para recuperar as cores primárias de um plano de fundo.

Atualizações de impressão digital

A classe FingerprintManager introduziu os seguintes códigos de erro:

  • FINGERPRINT_ERROR_LOCKOUT_PERMANENT: o usuário tentou desbloquear o dispositivo muitas vezes usando o leitor de impressão digital.
  • FINGERPRINT_ERROR_VENDOR: ocorreu um erro no leitor de impressão digital específico do fornecedor.

Atualizações de criptografia

Várias alterações de criptografia foram feitas no Android 8.1:

  • Novos algoritmos foram implementados no Conscrypt. A implementação do Conscrypt é usada preferencialmente sobre a implementação do Bouncy Castle existente. Veja os novos algoritmos:
    • AlgorithmParameters:GCM
    • KeyGenerator:AES
    • KeyGenerator:DESEDE
    • KeyGenerator:HMACMD5
    • KeyGenerator:HMACSHA1
    • KeyGenerator:HMACSHA224
    • KeyGenerator:HMACSHA256
    • KeyGenerator:HMACSHA384
    • KeyGenerator:HMACSHA512
    • SecretKeyFactory:DESEDE
    • Signature:NONEWITHECDSA
  • Cipher.getParameters().getParameterSpec(IvParameterSpec.class) não funciona mais para algoritmos que usam o GCM. Em vez disso, use getParameterSpec(GCMParameterSpec.class).
  • Muitas classes internas do Conscrypt associadas ao TLS foram refatoradas. Como os desenvolvedores às vezes acessam esses itens reflexivamente, os paliativos foram mantidos para compatibilidade com o uso anterior, mas alguns detalhes mudaram. Por exemplo, os sockets anteriormente eram do tipo OpenSSLSocketImpl, mas agora são do tipo ConscryptFileDescriptorSocket ou ConscryptEngineSocket, sendo que ambos estendem o OpenSSLSocketImpl.
  • Métodos SSLSession usados para gerar IllegalArgumentException quando uma referência nula é passada agora geram NullPointerException.
  • O RSA KeyFactory não permite mais a geração de chaves a partir de matrizes de bytes maiores que a chave codificada. Chamadas para generatePrivate() e generatePublic() que fornecem um KeySpec em que a estrutura de chave não preenche todo o buffer resultarão em uma InvalidKeySpecException.
  • Quando uma leitura de socket é interrompida pelo fechamento dele, o Conscrypt é usado para retornar -1 da leitura. A leitura agora gera SocketException.
  • O conjunto de certificados de CA raiz foi alterado, removendo principalmente um grande número de certificados obsoletos, mas também removendo os certificados raiz do WoSign e do StartCom. Para mais informações sobre essa decisão, consulte a postagem do blog de segurança do Google, Remoção definitiva da confiança nos certificados WoSign e StartCom (link em inglês).