Android 4.3 APIs

API de nível: 18

Android 4.3 (JELLY_BEAN_MR2) é uma atualização da versão Jelly Bean que oferece novos recursos para usuários e apps desenvolvedores de aplicativos. Este documento fornece uma introdução aos principais novas APIs.

Como desenvolvedor de aplicativos, você deve fazer o download da imagem do sistema do Android 4.3 e da plataforma do SDK no SDK Manager assim que possível. Se você não tiver um dispositivo com o Android 4.3 para testar o app, use a imagem do sistema do Android 4.3 para testar o app no Android Emulator. Em seguida, crie seus apps na plataforma do Android 4.3 para começar a usar as APIs mais recentes.

Atualização do nível da API

Para otimizar seu aplicativo para dispositivos com o Android 4.3, defina o targetSdkVersion como "18", instale em uma imagem do sistema Android 4.3, testá-lo e publicar uma atualização com essa alteração.

É possível usar APIs no Android 4.3 e, ao mesmo tempo, oferecer compatibilidade com versões anteriores adicionando ao código que verificam o nível da API do sistema antes da execução APIs não compatíveis com seu minSdkVersion. Para saber mais sobre como manter a compatibilidade com versões anteriores, leia Compatibilidade com diferentes Versões da Plataforma.

Várias APIs também estão disponíveis na Biblioteca de Suporte do Android, permitindo a implementação de novos recursos em versões mais antigas da plataforma.

Para saber mais sobre como os níveis de API funcionam, leia O que é o nível da API?

Mudanças de comportamento importantes

Caso tenha publicado um aplicativo para Android anteriormente, saiba que ele pode ser afetado pelas mudanças no Android 4.3.

Se o app usa intents implícitas...

O app pode apresentar um comportamento incorreto em um ambiente de perfil restrito.

Os usuários em um ambiente de perfil restrito podem não têm todos os apps Android padrão disponíveis. Por exemplo, um perfil restrito pode ter o navegador da Web e o app de câmera desativados. Portanto, o app não pode fazer suposições sobre quais apps estão disponíveis, porque, se você chamar startActivity() sem verificar se um app está disponível para processar a Intent, o app poderá falhar em um perfil restrito.

Ao usar uma intent implícita, sempre verifique se um app está disponível para processar a intent chamando resolveActivity() ou queryIntentActivities(). Exemplo:

Kotlin

val intent = Intent(Intent.ACTION_SEND)
...
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent)
} else {
    Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show()
}

Java

Intent intent = new Intent(Intent.ACTION_SEND);
...
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
} else {
    Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show();
}

Se o app depende de contas...

Seu app pode ter um comportamento inadequado em um ambiente de perfil restrito.

Os usuários em um ambiente de perfil restrito não têm acesso a contas de usuário por padrão. Se o app depender de uma Account, ele poderá falhar ou se comportar inesperadamente quando usado em um perfil restrito.

Se você quiser impedir que perfis restritos usem seu app totalmente porque seu app depende de informações sensíveis da conta, especifique o atributo android:requiredAccountType no <application> do manifesto .

Se você quiser permitir que perfis restritos continuem usando seu app mesmo que eles não possam criar as próprias contas, e você poderá desativar os recursos do aplicativo que exigem uma conta ou permitir que perfis restritos acessem as contas criadas pelo usuário principal. Para mais informações, consulte a seção abaixo sobre Como oferecer suporte a contas em um perfil restrito.

Se o app usa a VideoView...

Seu vídeo pode aparecer menor no Android 4.3.

Em versões anteriores do Android, o widget VideoView estava incorreto calculou o valor de "wrap_content" para layout_height e layout_width para ser igual a "match_parent". Portanto, embora o uso de "wrap_content" para a altura ou largura tenha fornecido o layout de vídeo desejado anteriormente, Isso pode resultar em um vídeo muito menor no Android 4.3 e em versões mais recentes. Para corrigir o problema, substitua "wrap_content" por "match_parent" e verifique se o vídeo aparece como esperado no Android 4.3 e em versões mais antigas.

Perfis restritos

Em tablets Android, os usuários agora podem criar perfis restritos com base no usuário principal. Quando os usuários criam um perfil restrito, eles podem ativar restrições, como quais apps são disponíveis para o perfil. Um novo conjunto de APIs no Android 4.3 também permite desenvolver as configurações de restrição para os apps que você desenvolve. Por exemplo, usando as novas APIs, é possível permitir que os usuários controlem o tipo de conteúdo disponível no app quando ele é executado em um ambiente de perfil restrito.

A interface para que os usuários controlem as restrições que você criou é gerenciada pelo Aplicativo de configurações. Para que as configurações de restrição do app apareçam para o usuário, faça o seguinte: é necessário declarar as restrições fornecidas pelo app criando uma BroadcastReceiver que recebe a intent ACTION_GET_RESTRICTION_ENTRIES. O sistema invoca essa intent para consultar todos os apps para as restrições disponíveis e, em seguida, cria a interface para permitir que o usuário principal gerenciar restrições para cada perfil restrito.

No método onReceive() de seu BroadcastReceiver, você precisa criar um RestrictionEntry para cada restrição fornecida pelo app. Cada RestrictionEntry define um título de restrição, uma descrição e uma das seguintes tipos de dados:

  • TYPE_BOOLEAN para uma restrição que seja verdadeira ou falsa.
  • TYPE_CHOICE para uma restrição com várias opções mutuamente exclusivas (botões de opção).
  • TYPE_MULTI_SELECT para uma restrição que tem várias opções que não são mutuamente exclusivas (opções de caixa de seleção).

Em seguida, coloque todos os objetos RestrictionEntry em um ArrayList e coloque-o no resultado do broadcast receiver como o valor do extra EXTRA_RESTRICTIONS_LIST.

O sistema cria a interface para as restrições do seu app no app Configurações e salva cada uma delas. restrição com a chave exclusiva que você forneceu para cada RestrictionEntry objeto. Quando o usuário abrir seu app, você poderá consultar as restrições atuais chamando getApplicationRestrictions(). Isso retorna um Bundle contendo os pares de chave-valor para cada restrição. definidos com os objetos RestrictionEntry.

Se você deseja fornecer restrições mais específicas que não podem ser tratadas por booleanos, uma única escolha e valores de múltipla escolha, você pode criar uma atividade em que o usuário pode especificar e permitem que os usuários abram essa atividade nas configurações de restrição. No broadcast receiver, inclua o extra EXTRA_RESTRICTIONS_INTENT no resultado Bundle. Esse extra precisa especificar um Intent que indique a classe Activity a ser iniciada. Use o método putParcelable() para transmitir EXTRA_RESTRICTIONS_INTENT com a intent. Quando o usuário principal insere sua atividade para definir restrições personalizadas, seu atividade deve, então, retornar um resultado contendo os valores de restrição em um extra usando a chave EXTRA_RESTRICTIONS_LIST ou EXTRA_RESTRICTIONS_BUNDLE, dependendo se você especificou objetos RestrictionEntry ou pares de chave-valor, respectivamente.

Suporte a contas em um perfil restrito

Qualquer conta adicionada ao usuário principal está disponível para um perfil restrito, mas o não podem ser acessadas pelas APIs AccountManager por padrão. Se você tentar adicionar uma conta com AccountManager em um perfil restrito, vai receber um resultado de falha. Devido a essas restrições, você tem o seguinte três opções:

  • Permitir o acesso às contas do proprietário em um perfil restrito.

    Para ter acesso a uma conta de um perfil restrito, adicione o atributo android:restrictedAccountType à tag <application>:

    <application ...
        android:restrictedAccountType="com.example.account.type" >

    Atenção: ativar esse atributo dá ao app acesso às contas do usuário principal de perfis restritos. Portanto, permita isso somente se as informações exibidas pelo app não revelarem informações de identificação pessoal (PII) consideradas sensíveis. As configurações do sistema vão informar ao usuário que o app concede perfis restritos às contas dele, então isso precisa ficar claro para ele. que o acesso à conta seja importante para a funcionalidade do seu app. Se possível, você também deve Fornecer controles de restrição adequados para o usuário principal que definam o nível de acesso à conta é permitido no seu app.

  • Desativar determinadas funcionalidades quando não for possível modificar contas.

    Se você quiser usar contas, mas não precisar delas para a funcionalidade principal do app, verifique a disponibilidade de contas e desative os recursos quando não estiverem disponíveis. Primeiro, verifique se já existe uma conta disponível. Caso contrário, consulte se é possível criar uma nova conta chamando getUserRestrictions() e verifique o extra DISALLOW_MODIFY_ACCOUNTS no resultado. Se for true, desative qualquer funcionalidade do app que exija acesso às contas. Exemplo:

    Kotlin

    val um = context.getSystemService(Context.USER_SERVICE) as UserManager
    val restrictions: Bundle = um.userRestrictions
    if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
        // cannot add accounts, disable some functionality
    }

    Java

    UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
    Bundle restrictions = um.getUserRestrictions();
    if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
        // cannot add accounts, disable some functionality
    }

    Observação:nessa situação, você não deve declarar novos atributos no arquivo de manifesto.

  • Desative o app quando não for possível acessar contas particulares.

    Se for importante que o app não esteja disponível para perfis restritos porque seu app depende das informações pessoais sensíveis da conta e porque perfis restritos no momento não é possível adicionar novas contas), adicione O atributo android:requiredAccountType para a tag <application>:

    <application ...
        android:requiredAccountType="com.example.account.type" >

    Por exemplo, o aplicativo Gmail usa esse atributo para desativar-se em perfis restritos, porque o e-mail pessoal do proprietário não deve estar disponível para perfis restritos.

  • Redes sem fio e conectividade

    Bluetooth de baixa energia (Smart Ready)

    O Android agora oferece suporte ao Bluetooth Low Energy (LE) com novas APIs no android.bluetooth. Com as novas APIs, você pode criar apps Android que se comunicam com Bluetooth de baixa energia periféricos como monitores de frequência cardíaca e pedômetros.

    Como o Bluetooth LE é um recurso de hardware que não está disponível em todos dispositivos Android, declare um arquivo de manifesto como <uses-feature>. para "android.hardware.bluetooth_le":

    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />

    Se você já conhece as APIs clássicas de Bluetooth do Android, observe que usar o As APIs Bluetooth LE têm algumas diferenças. O mais importante é que agora há uma classe BluetoothManager que você precisa usar para algumas operações de alto nível, como adquirir um BluetoothAdapter, receber uma lista de dispositivos conectados e verificar o estado de um dispositivo. Por exemplo, veja como acessar BluetoothAdapter:

    Kotlin

    val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
    bluetoothAdapter = bluetoothManager.adapter

    Java

    final BluetoothManager bluetoothManager =
            (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    bluetoothAdapter = bluetoothManager.getAdapter();

    Para descobrir periféricos Bluetooth LE, chame startLeScan() no BluetoothAdapter, transmitindo uma implementação. da interface BluetoothAdapter.LeScanCallback. Quando o Bluetooth detecta um periférico Bluetooth LE, a implementação do BluetoothAdapter.LeScanCallback recebe uma chamada para o onLeScan(). Isso fornece um objeto BluetoothDevice que representa a dispositivo detectado, o valor RSSI do dispositivo e uma matriz de bytes contendo o código registro de anúncio.

    Se você quiser procurar apenas tipos específicos de periféricos, chame startLeScan() e inclua uma matriz de objetos UUID que especificam os serviços GATT compatíveis com seu app.

    Observação: só é possível verificar dispositivos Bluetooth LE ou dispositivos Bluetooth clássico usando APIs anteriores. Não é possível procurar LE e Classic ao mesmo tempo dispositivos Bluetooth ao mesmo tempo.

    Para se conectar a um periférico Bluetooth LE, chame connectGatt() no objeto BluetoothDevice correspondente, transmitindo uma implementação de BluetoothGattCallback. Sua implementação de BluetoothGattCallback recebe callbacks sobre o estado de conectividade com o dispositivo e outros eventos. É durante a onConnectionStateChange() para que você possa começar a se comunicar com o dispositivo se o método transmitir STATE_CONNECTED como o novo estado.

    O acesso a recursos de Bluetooth em um dispositivo também exige que o app solicite determinadas permissões do usuário do Bluetooth. Para mais informações, consulte o guia da API Bluetooth de baixa energia.

    Modo somente busca por Wi-Fi

    Ao tentar identificar a localização do usuário, o Android pode usar o Wi-Fi para determinar localização verificando os pontos de acesso próximos. No entanto, os usuários geralmente mantêm o Wi-Fi desativado para economizar bateria, resultando em dados de localização menos precisos. O Android agora inclui um modo de somente busca que permite que o Wi-Fi do dispositivo faça a varredura de pontos de acesso para ajudar a obter a localização sem se conectar a um ponto de acesso, reduzindo bastante o uso da bateria.

    Se você quiser adquirir a localização do usuário, mas o Wi-Fi estiver desativado, peça para o usuário ativar o modo de somente busca de Wi-Fi chamando startActivity() com a ação ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE.

    Configuração de Wi-Fi

    As novas APIs WifiEnterpriseConfig permitem que serviços voltados para empresas automatizar a configuração de Wi-Fi para dispositivos gerenciados.

    Resposta rápida para ligações recebidas

    Desde o Android 4.0, um recurso chamado "Resposta rápida" permite que os usuários respondam a chamadas com uma mensagem de texto imediata sem precisar atender a chamada ou desbloquear o dispositivo. Até agora, essas mensagens rápidas eram sempre processadas pelo aplicativo de mensagens padrão. Agora qualquer app pode declarar a capacidade de processar essas mensagens criando um Service. com um filtro de intent para ACTION_RESPOND_VIA_MESSAGE.

    Quando o usuário responde a uma chamada com uma resposta rápida, o app Telefone envia a intent ACTION_RESPOND_VIA_MESSAGE com um URI descrevendo o destinatário (o autor da chamada) e o extra EXTRA_TEXT com a mensagem que o usuário quer enviar. Quando o serviço recebe a intent, ele deve entregar a mensagem e parar imediatamente (seu app não deve mostrar uma atividade).

    Para receber essa intent, é necessário declarar a permissão SEND_RESPOND_VIA_MESSAGE.

    Multimídia

    Melhorias no MediaExtractor e no MediaCodec

    Agora, o Android facilita a criação de players de streaming dinâmico adaptativo por HTTP (DASH) de acordo com o padrão ISO/IEC 23009-1, usando APIs existentes em MediaCodec e MediaExtractor. O framework subjacente a essas APIs foi atualizado para oferecer suporte análise de arquivos MP4 fragmentados, mas seu app ainda é responsável pela análise dos metadados de MPD e transmitindo os streams individuais para MediaExtractor.

    Se você quiser usar o DASH com conteúdo criptografado, observe que o método getSampleCryptoInfo() retorna os metadados MediaCodec.CryptoInfo que descrevem a estrutura de cada amostra de mídia criptografada. Além disso, o método getPsshInfo() foi adicionado a MediaExtractor para que você possa acessar os metadados PSSH da mídia DASH. Esse método retorna um mapa de objetos UUID para bytes, com o UUID especificando o esquema de criptografia e os bytes sendo os dados específicos a esse esquema.

    DRM de mídia

    A nova classe MediaDrm oferece uma solução modular para o gerenciamento de direitos digitais (DRM) com seu conteúdo de mídia, separando as preocupações de DRM da reprodução de mídia. Para essa separação de API permite que você reproduza conteúdo criptografado pelo Widevine sem ter que usar o formato de mídia Widevine. Essa solução de DRM também oferece suporte à criptografia comum DASH para que você pode usar vários esquemas de DRM com conteúdo de streaming.

    É possível usar MediaDrm para receber mensagens opacas de solicitação de chave e processar mensagens de resposta de chave do servidor para aquisição e provisionamento de licença. Seu app é responsável por processar a comunicação de rede com os servidores. A classe MediaDrm oferece apenas a capacidade de gerar e processar as mensagens.

    As APIs MediaDrm devem ser usadas em conjunto com as APIs MediaCodec introduzidas no Android 4.1 (nível 16 da API), incluindo MediaCodec para codificar e decodificar seu conteúdo, MediaCrypto para lidar com conteúdo criptografado e MediaExtractor para extrair e aplicar o multiplexador do seu conteúdo.

    Primeiro, você precisa construir MediaExtractor e objetos MediaCodec. É possível acessar o arquivo de identificação UUID, normalmente de metadados no conteúdo, e usados para criar um instância de um objeto MediaDrm com o construtor.

    Codificação de vídeo de uma Surface

    O Android 4.1 (nível 16 da API) adicionou a classe MediaCodec para codificação e decodificação de baixo nível do conteúdo de mídia. Ao codificar vídeos, o Android 4.1 exigia que você fornecesse à mídia uma matriz ByteBuffer, mas o Android 4.3 agora permite usar uma Surface como entrada para um codificador. Por exemplo, isso permite codificar a entrada de um arquivo de vídeo existente ou usando frames gerados pelo OpenGL ES.

    Para usar um Surface como entrada para o codificador, primeiro chame configure() para o MediaCodec. Em seguida, chame createInputSurface() para receber o Surface em que é possível transmitir a mídia.

    Por exemplo, é possível usar o Surface fornecido como a janela de um contexto OpenGL transmitindo-o para eglCreateWindowSurface(). Em seguida, ao renderizar a superfície, chame eglSwapBuffers() para transmitir o frame ao MediaCodec.

    Para iniciar a codificação, chame start() no MediaCodec. Quando terminar, chame signalEndOfInputStream() para encerrar a codificação e chame release() no Surface.

    Muxing de mídia

    A nova classe MediaMuxer permite a multiplexação entre um stream de áudio e um stream de vídeo. Essas APIs servem como contraparte da MediaExtractor adicionada no Android 4.2 para desmultiplexação (demuxing) de mídia.

    Os formatos de saída compatíveis são definidos em MediaMuxer.OutputFormat. Atualmente, o MP4 é o único formato de saída aceito, e MediaMuxer aceita apenas um stream de áudio e/ou um stream de vídeo por vez.

    O MediaMuxer foi desenvolvido principalmente para funcionar com o MediaCodec para processar o vídeo usando MediaCodec e salvar o a saída de um arquivo MP4 pelo MediaMuxer. Você também pode usar MediaMuxer em combinação com MediaExtractor para realizar a edição de mídia sem precisar codificar ou decodificar.

    Progresso da reprodução e arraste do marcador de mídia para RemoteControlClient

    No Android 4.0 (nível 14 da API), o RemoteControlClient foi adicionado para ativar os controles de reprodução de mídia de clientes de controle remoto, como os controles disponíveis na tela de bloqueio. O Android 4.3 agora permite que esses controles mostrem a posição de reprodução e os controles para avançar rapidamente a reprodução. Se você tiver ativado o controle remoto para seu app de mídia com as APIs RemoteControlClient, será possível permitir a reprodução de áudios com a implementação de duas novas interfaces.

    Primeiro, é preciso ativar a sinalização FLAG_KEY_MEDIA_POSITION_UPDATE transmitindo-a para setTransportControlsFlags().

    Em seguida, implemente as duas novas interfaces a seguir:

    RemoteControlClient.OnGetPlaybackPositionListener
    Isso inclui o callback onGetPlaybackPosition(), que solicita a posição atual da mídia quando o controle remoto precisa atualizar o progresso na interface.
    RemoteControlClient.OnPlaybackPositionUpdateListener
    Isso inclui o callback onPlaybackPositionUpdate(), que informa ao app o novo código de tempo da mídia quando o usuário avança a reprodução com a interface do controle remoto.

    Depois de atualizar a reprodução com a nova posição, chame setPlaybackState() para indicar a novo estado, posição e velocidade da reprodução.

    Com essas interfaces definidas, é possível defini-las para o RemoteControlClient chamando setOnGetPlaybackPositionListener() e setPlaybackPositionUpdateListener(), respectivamente.

    Gráficos

    Suporte ao OpenGL ES 3.0

    O Android 4.3 adiciona interfaces Java e suporte nativo para OpenGL ES 3.0. As principais novas funcionalidades oferecidas no OpenGL ES 3.0 incluem:

    • Aceleração de efeitos visuais avançados
    • Compactação de textura ETC2/EAC de alta qualidade como recurso padrão
    • Uma nova versão da linguagem de sombreamento GLSL ES com suporte a ponto flutuante de 32 bits e inteiro
    • Renderização de textura avançada
    • Padronização mais ampla do tamanho da textura e formatos do buffer de renderização

    A interface Java para OpenGL ES 3.0 no Android é fornecida com GLES30. Ao usar o OpenGL ES 3.0, declare-o no arquivo de manifesto com a <uses-feature> e o atributo android:glEsVersion. Exemplo:

    <manifest>
        <uses-feature android:glEsVersion="0x00030000" />
        ...
    </manifest>

    E lembre-se de especificar o contexto do OpenGL ES chamando setEGLContextClientVersion(), transmitindo 3 como a versão.

    Para mais informações sobre como usar o OpenGL ES, incluindo como verificar a versão do OpenGL ES compatível do dispositivo no tempo de execução, consulte o guia da API OpenGL ES.

    Mipmapping para drawables

    Usar um mipmap como fonte do bitmap ou drawable é uma maneira simples de fornecer uma imagem de qualidade e várias escalas de imagem, o que pode ser particularmente útil se você espera que a imagem seja dimensionada durante uma animação.

    O Android 4.2 (API de nível 17) adicionou suporte a mipmaps no Bitmap classe: o Android troca as imagens mip na sua Bitmap quando você forneceu uma origem de mipmap e ativou setHasMipMap(). Agora, no Android 4.3, você também pode ativar mipmaps para um objeto BitmapDrawable, fornecendo um recurso de mipmap e definindo o atributo android:mipMap em um arquivo de recurso de bitmap ou chamando hasMipMap().

    Interface do usuário

    Ver sobreposições

    A nova classe ViewOverlay fornece uma camada transparente sobre a um View em que você pode adicionar conteúdo visual e que não afeta da hierarquia de layouts. Você pode receber um ViewOverlay para qualquer View chamando getOverlay(). A sobreposição sempre tem o mesmo tamanho e posição da visualização de host (a visualização em que ela foi criada), permitindo que você adicione conteúdo que aparece na frente da visualização de host, mas que não pode estender os limites dela.

    O uso de um ViewOverlay é particularmente útil quando você quer criar animações, como deslizar uma visualização para fora do contêiner ou mover itens pela tela sem afetar a hierarquia da visualização. No entanto, como a área utilizável de uma sobreposição é restringida à mesma área da visualização do host, se você quiser animar uma visualização que se move para fora da posição no layout, use uma sobreposição de uma visualização mãe que tenha os limites de layout desejados.

    Ao criar uma sobreposição para uma visualização de widget, como Button, é possível adicionar objetos Drawable à sobreposição chamando add(Drawable). Se você chamar getOverlay() para uma visualização de layout, como RelativeLayout, o objeto retornado será um ViewGroupOverlay. O A classe ViewGroupOverlay é uma subclasse. de ViewOverlay, que também permite adicionar View objetos chamando add(View).

    Observação:todos os drawables e visualizações adicionados a uma sobreposição. são apenas visuais. Eles não podem receber eventos de foco ou de entrada.

    Por exemplo, o código a seguir anima uma visualização deslizando para a direita posicionando a visualização na sobreposição da visualização principal e uma animação de translação nessa visualização:

    Kotlin

    val view: View? = findViewById(R.id.view_to_remove)
    val container: ViewGroup? = view?.parent as ViewGroup
    
    container?.apply {
        overlay.add(view)
        ObjectAnimator.ofFloat(view, "translationX", right.toFloat())
                .start()
    }

    Java

    View view = findViewById(R.id.view_to_remove);
    ViewGroup container = (ViewGroup) view.getParent();
    container.getOverlay().add(view);
    ObjectAnimator anim = ObjectAnimator.ofFloat(view, "translationX", container.getRight());
    anim.start();

    Layout com limites ópticos

    Para visualizações que contêm imagens de plano de fundo Nine-Patch, agora você pode especificar que elas precisam fiquem alinhadas com as visualizações vizinhas com base no limites da imagem de plano de fundo, que o "clipe" limites da visualização.

    Por exemplo, as figuras 1 e 2 mostram o mesmo layout, mas a versão na figura 1 está usando limites de clipe (o comportamento padrão), enquanto a figura 2 está usando limites ópticos. Como o As imagens Nine-Patch usadas para o botão e o Porta-retratos incluem padding nas extremidades, eles parecem não se alinhar entre si ou com o texto ao usar limites de corte.

    Observação: as capturas de tela nas figuras 1 e 2 têm a opção limites de layout" de desenvolvedor ativada. Para cada visualização, as linhas vermelhas indicam os limites ópticos, as linhas azuis indicam os limites do clipe e as linhas rosa indicam as margens.

    Figura 1. Layout que usa limites de corte (padrão).

    Figura 2. Layout usando limites ópticos.

    Para alinhar as visualizações com base nos limites ópticos, defina o atributo android:layoutMode como "opticalBounds" em um dos layouts pai. Exemplo:

    <LinearLayout android:layoutMode="opticalBounds" ... >

    Figura 3. Visualização ampliada do botão Nine-Patch do Holo com limites ópticos.

    Para que isso funcione, as imagens nine-patch aplicadas ao plano de fundo das visualizações precisam especificar os limites ópticos usando linhas vermelhas na parte de baixo e à direita do arquivo nine-patch (como mostrado na Figura 3). As linhas vermelhas indicam a região que deve ser subtraída da os limites de corte, deixando os limites ópticos da imagem.

    Quando você ativa os limites ópticos para uma ViewGroup no layout, todos as visualizações descendentes herdam o modo de layout dos limites ópticos, a menos que você o modifique para um grupo definindo android:layoutMode como "clipBounds". Todos os elementos de layout também respeitam limites ópticos das visualizações filhas, adaptando os próprios limites com base nos limites ópticos da as visualizações dentro deles. No entanto, os elementos de layout (subclasses de ViewGroup) atualmente não oferecem suporte a limites ópticos para imagens de nove retângulos aplicadas ao próprio plano de fundo.

    Se você criar uma visualização personalizada criando uma subclasse de View, ViewGroup ou qualquer subclasse, a visualização vai herdar esses comportamentos de vinculação óptica.

    Observação: todos os widgets com suporte do tema Holo foram atualizados com limites ópticos, incluindo Button, Spinner, EditText e outros. Para aproveitar os benefícios imediatamente, defina o atributo android:layoutMode como "opticalBounds" se o app aplicar um tema Holo (Theme.Holo, Theme.Holo.Light etc.).

    Para especificar limites ópticos para suas imagens Nine-Patch com a ferramenta Draw 9-patch, mantenha a tecla Control pressionada quando clicando nos pixels da borda.

    Animação para valores de retângulo

    Agora você pode animar entre dois valores Rect com o novo RectEvaluator. Essa nova classe é uma implementação de TypeEvaluator que pode ser transmitida para ValueAnimator.setEvaluator().

    Anexar janela e focar o listener

    Anteriormente, se você quisesse detectar quando a visualização fosse anexada/desanexada à janela ou quando o foco dela mudasse, era necessário substituir a classe View para implementar onAttachedToWindow() e onDetachedFromWindow() ou onWindowFocusChanged(), respectivamente.

    Agora, para receber eventos de anexação e remoção, implemente ViewTreeObserver.OnWindowAttachListener e defina-o em uma visualização com addOnWindowAttachListener(). E, para receber eventos de foco, você pode implementar ViewTreeObserver.OnWindowFocusChangeListener e defini-lo em uma visualização com addOnWindowFocusChangeListener().

    Suporte a overscan de TV

    Para garantir que seu app preencha toda a tela de todas as TVs, ative o overscan para o layout do seu app. O modo de overscan é determinado pela sinalização FLAG_LAYOUT_IN_OVERSCAN, que pode ser ativada com temas de plataforma como Theme_DeviceDefault_NoActionBar_Overscan ou ativando o windowOverscan em um tema personalizado.

    Orientação da tela

    O atributo screenOrientation da tag <activity> agora aceita outros valores para respeitar a preferência do usuário de rotação automática:

    "userLandscape"
    Tem o mesmo comportamento de "sensorLandscape", exceto se o usuário desativar a rotação automática. Nesse caso, ele será bloqueado na orientação normal de paisagem e não será invertido.
    "userPortrait"
    Tem o mesmo comportamento de "sensorPortrait", exceto se o usuário desativar a rotação automática. Nesse caso, ele será bloqueado na orientação normal de retrato e não será invertido.
    "fullUser"
    Tem o mesmo comportamento de "fullSensor" e permite a rotação nas quatro direções, exceto se o usuário desativar a rotação automática, que será bloqueada na orientação preferida do usuário.

    Além disso, agora você também pode declarar "locked" para bloquear a orientação do app na orientação atual da tela.

    Animações de rotação

    O novo campo rotationAnimation em WindowManager permite selecionar uma das três animações que você quer usar quando o sistema alternar as orientações da tela. As três animações são:

    Observação: essas animações só estão disponíveis se você tiver definido a atividade para usar o modo "tela cheia", que pode ser ativado com temas como Theme.Holo.NoActionBar.Fullscreen.

    Por exemplo, veja como ativar o "crossfade" animação:

    Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        val params: WindowManager.LayoutParams = window.attributes
        params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE
        window.attributes = params
        ...
    }

    Java

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        WindowManager.LayoutParams params = getWindow().getAttributes();
        params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
        getWindow().setAttributes(params);
        ...
    }

    Entrada do usuário

    Novos tipos de sensor

    O novo sensor TYPE_GAME_ROTATION_VECTOR permite detectar as rotações do dispositivo sem se preocupar com interferências magnéticas. Ao contrário do sensor TYPE_ROTATION_VECTOR, o TYPE_GAME_ROTATION_VECTOR não é baseado no norte magnético.

    Os novos sensores TYPE_GYROSCOPE_UNCALIBRATED e TYPE_MAGNETIC_FIELD_UNCALIBRATED fornecem dados brutos do sensor sem consideração para estimativas de viés. Ou seja, os sensores TYPE_GYROSCOPE e TYPE_MAGNETIC_FIELD fornecem dados que consideram a distorção estimada da deriva da giroscópio e do ferro duro no dispositivo, respectivamente. Já as novas versões "não calibradas" desses sensores fornecem os dados brutos do sensor e oferecem os valores de viés estimados separadamente. Esses sensores permitem forneça sua própria calibração personalizada para os dados do sensor melhorando o viés estimado com dados externos.

    Listener de notificações

    O Android 4.3 adiciona uma nova classe de serviço, NotificationListenerService, que permite que o app receba informações sobre novas notificações à medida que são postadas pelo sistema.

    Se o app usa as APIs do serviço de acessibilidade para acessar as notificações do sistema, atualize-o para usar essas APIs.

    Provedor de contatos

    Consultar "contactables"

    A nova consulta do Provedor de contatos, Contactables.CONTENT_URI, fornece uma maneira eficiente de obter uma Cursor que contenha todos os endereços de e-mail e números de telefone pertencentes a todos os contatos que correspondam à consulta especificada.

    Consultar deltas de contatos

    Novas APIs foram adicionadas ao Provedor de contatos para permitir que você consulte de forma eficiente as alterações recentes nos dados de contatos. Antes, o app podia ser notificado quando algo nos dados de contatos mudava, mas você não saberia exatamente o que mudou e precisaria recuperar todos os contatos e então acessar cada um deles para descobrir a mudança.

    Para acompanhar as alterações em inserções e atualizações, agora é possível incluir o parâmetro CONTACT_LAST_UPDATED_TIMESTAMP com sua seleção para consultar apenas os contatos que mudaram desde a última vez que você consultou o provedor.

    Para rastrear quais contatos foram excluídos, a nova tabela ContactsContract.DeletedContacts fornece um registro dos contatos que foram excluídos, mas cada contato excluído é mantido nessa tabela por um tempo limitado. Assim como no método CONTACT_LAST_UPDATED_TIMESTAMP, é possível usar o novo parâmetro de seleção, CONTACT_DELETED_TIMESTAMP, para verificar quais contatos foram excluídos desde a última consulta com o provedor. A tabela também contém a constante DAYS_KEPT_MILLISECONDS, que contém o número de dias (em milissegundos) em que o registro será mantido.

    Além disso, o Provedor de contatos agora transmite a ação CONTACTS_DATABASE_CREATED quando o usuário limpa o armazenamento de contatos no menu de configurações do sistema, recria o banco de dados do Provedor de contatos. O objetivo é sinalizar aos apps que eles precisam descartar todas as informações de contato armazenadas e recarregar com uma nova consulta.

    Para conferir um exemplo de código que usa essas APIs para verificar mudanças nos contatos, consulte o exemplo ApiDemos disponível no download SDK Samples.

    Localização

    Compatibilidade aprimorada com texto bidirecional

    As versões anteriores do Android são compatíveis com idiomas e layout da direita para a esquerda (RTL). mas às vezes não lidam corretamente com texto de direção mista. O Android 4.3 adiciona as APIs BidiFormatter, que ajudam a formatar corretamente o texto com conteúdo de direção oposta sem distorcer nenhuma parte dele.

    Por exemplo, quando você quer criar uma frase com uma variável de string, como "Você quis dizer 15 Bay Street, Laurel, CA?", normalmente você transmite um recurso de string localizado e a variável para String.format():

    Kotlin

    val suggestion = String.format(resources.getString(R.string.did_you_mean), address)

    Java

    Resources res = getResources();
    String suggestion = String.format(res.getString(R.string.did_you_mean), address);

    No entanto, se a localidade for hebraico, a string formatada será exibida assim:

    האם התכוונת ל 15 Bay Street, Laurel, CA?

    Está errado, porque "15" deve ser a esquerda da "Bay Street". A solução é usar BidiFormatter e o método unicodeWrap(). Por exemplo, o código acima se torna:

    Kotlin

    val bidiFormatter = BidiFormatter.getInstance()
    val suggestion = String.format(
            resources.getString(R.string.did_you_mean),
            bidiFormatter.unicodeWrap(address)
    )

    Java

    Resources res = getResources();
    BidiFormatter bidiFormatter = BidiFormatter.getInstance();
    String suggestion = String.format(res.getString(R.string.did_you_mean),
            bidiFormatter.unicodeWrap(address));

    Por padrão, unicodeWrap() usa a heurística de estimativa de direcionalidade de primeira forte, que pode dar errado se o primeiro indicador de direção do texto não representar a direção adequada para o conteúdo como um todo. Se necessário, você pode especificar uma heurística diferente transmitindo uma das constantes TextDirectionHeuristic de TextDirectionHeuristics. para unicodeWrap().

    Observação:essas novas APIs também estão disponíveis para versões anteriores do Android por meio do Suporte do Android Biblioteca, com a classe BidiFormatter e APIs relacionadas.

    Serviços de acessibilidade

    Gerenciar eventos de teclas

    Agora, uma AccessibilityService pode receber um callback para eventos de entrada de tecla com o método de callback onKeyEvent(). Isso permite que seu serviço de acessibilidade processe a entrada de dispositivos de entrada baseados em teclas, como um teclado, e traduza esses eventos em ações especiais que antes só eram possíveis com entrada por toque ou o botão direcional do dispositivo.

    Selecionar texto e copiar/colar

    O AccessibilityNodeInfo agora fornece APIs que permitem uma AccessibilityService para selecionar, recortar, copiar e colar em um nó.

    Para especificar a seleção de texto a ser cortado ou copiado, o serviço de acessibilidade pode usar a nova ação, ACTION_SET_SELECTION, transmitindo a posição inicial e final da seleção com ACTION_ARGUMENT_SELECTION_START_INT e ACTION_ARGUMENT_SELECTION_END_INT. Como alternativa, você pode selecionar texto manipulando a posição do cursor usando a ação atual, ACTION_NEXT_AT_MOVEMENT_GRANULARITY, (anteriormente apenas para mover a posição do cursor) e adicionando o argumento ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN.

    Você pode recortar ou copiar com ACTION_CUT, ACTION_COPY e depois colar com ACTION_PASTE

    Observação: essas novas APIs também estão disponíveis para versões anteriores do Android pela Biblioteca de Suporte do Android, com a classe AccessibilityNodeInfoCompat.

    Declarar recursos de acessibilidade

    A partir do Android 4.3, um serviço de acessibilidade precisa declarar os recursos de acessibilidade no arquivo de metadados para usar determinados recursos de acessibilidade. Se o capability não for solicitado no arquivo de metadados, o recurso não será executado. Para declarar os capabilities de acessibilidade do serviço, use atributos XML que correspondam às várias constantes "capability" na classe AccessibilityServiceInfo.

    Por exemplo, se um serviço não solicitar o recurso flagRequestFilterKeyEvents, ele não receberá eventos principais.

    Teste e depuração

    Testes automatizados da interface

    A nova classe UiAutomation oferece APIs que permitem simular ações do usuário para automação de testes. Ao usar as APIs AccessibilityService da plataforma, as APIs UiAutomation permitem inspecionar o conteúdo da tela e injetar eventos arbitrários de teclado e toque.

    Para acessar uma instância de UiAutomation, chame Instrumentation.getUiAutomation(). Para Para que isso funcione, é necessário fornecer a opção -w com o comando instrument. ao executar InstrumentationTestCase no adb shell.

    Com a instância UiAutomation, é possível executar eventos arbitrários para testar seu app chamando executeAndWaitForEvent(), transmitindo um Runnable para ele executar, um tempo limite para a operação e uma implementação da interface UiAutomation.AccessibilityEventFilter. Você vai receber uma chamada na implementação do UiAutomation.AccessibilityEventFilter. que permite filtrar os eventos do seu interesse e determinar o sucesso ou a falha de um determinado caso de teste.

    Para observar todos os eventos durante um teste, crie uma implementação de UiAutomation.OnAccessibilityEventListener e transmita-a para setOnAccessibilityEventListener(). A interface do listener recebe uma chamada para onAccessibilityEvent() sempre que ocorre um evento, receber um objeto AccessibilityEvent que descreve o evento.

    As APIs UiAutomation expõem várias outras operações em um nível muito baixo para incentivar o desenvolvimento de ferramentas de teste de interface, como uiautomator. Por exemplo, UiAutomation também pode:

    • Injetar eventos de entrada
    • Mudar a orientação da tela
    • Fazer capturas de tela

    E, o mais importante para ferramentas de teste de interface, as APIs UiAutomation funcionam entre os limites do aplicativo, ao contrário dos Instrumentation.

    Eventos do Systrace para apps

    O Android 4.3 adiciona a classe Trace com dois métodos estáticos, beginSection() e endSection(), que permitem definir blocos de código a serem incluídos com o relatório do Systrace. Ao criar seções de código rastreáveis no seu aplicativo, os registros do Systrace fornecem uma abordagem análise de onde ocorre a lentidão no aplicativo.

    Para saber mais sobre como usar a ferramenta Systrace, leia Análise de tela e desempenho com o Systrace.

    Segurança

    Repositório de chaves privadas do Android para apps

    O Android agora oferece um provedor de segurança Java personalizado na facilidade KeyStore, chamado Android Key Store, que permite gerar e salvar chaves privadas que podem ser vistas e usadas apenas pelo seu app. Para carregar o Android Key Store, transmita "AndroidKeyStore" para KeyStore.getInstance().

    Para gerenciar as credenciais privadas do app na loja de chaves do Android, gere uma nova chave com KeyPairGenerator com KeyPairGeneratorSpec. Primeiro, receba uma instância de KeyPairGenerator chamando getInstance(). Em seguida, chame initialize(), transmitindo uma instância de KeyPairGeneratorSpec, que pode ser obtida usando KeyPairGeneratorSpec.Builder. Por fim, acesse KeyPair chamando generateKeyPair().

    Armazenamento de credenciais de hardware

    O Android também oferece suporte a armazenamento com suporte de hardware para suas credenciais KeyChain, oferecendo mais segurança ao deixar as chaves indisponíveis para extração. Ou seja, uma vez estão em um repositório de chaves protegido por hardware (Secure Element, TPM ou TrustZone), elas podem ser usadas para operações criptográficas, mas não é possível exportar o material da chave privada. Até mesmo o kernel do SO não pode acessar o material da chave. Embora nem todos os dispositivos Android ofereçam suporte ao armazenamento em hardware, você pode verificar no momento da execução se o armazenamento com suporte a hardware está disponível chamando KeyChain.IsBoundKeyAlgorithm().

    Declarações do manifesto

    Recursos necessários declaráveis

    Os valores a seguir agora são compatíveis com o elemento <uses-feature>, de forma que é possível garantir que o app seja instalado somente em dispositivos que ofereçam os recursos necessários.

    FEATURE_APP_WIDGETS
    Declara que o app fornece um widget e precisa ser instalado apenas em dispositivos que incluem uma tela inicial ou local semelhante em que os usuários podem incorporar widgets. Exemplo:
    <uses-feature android:name="android.software.app_widgets" android:required="true" />
    FEATURE_HOME_SCREEN
    Declara que o app se comporta como uma substituição da tela inicial e só pode ser instalado em compatíveis com apps de tela inicial de terceiros. Exemplo:
    <uses-feature android:name="android.software.home_screen" android:required="true" />
    FEATURE_INPUT_METHODS
    Declara que o app oferece um método de entrada personalizado (um teclado criado com InputMethodService) e precisa ser instalado apenas em dispositivos que ofereçam suporte a métodos de entrada de terceiros. Exemplo:
    <uses-feature android:name="android.software.input_methods" android:required="true" />
    FEATURE_BLUETOOTH_LE
    Declara que o app usa APIs Bluetooth de baixa energia e precisa ser instalado apenas em dispositivos que podem se comunicar com outros dispositivos por Bluetooth de baixa energia. Exemplo:
    <uses-feature android:name="android.software.bluetooth_le" android:required="true" />

    Permissões do usuário

    Os valores a seguir agora são compatíveis com o <uses-permission> para declarar as permissões necessárias para que o app acesse determinadas APIs.

    BIND_NOTIFICATION_LISTENER_SERVICE
    Obrigatório para usar as novas APIs NotificationListenerService.
    SEND_RESPOND_VIA_MESSAGE
    Necessário para receber o ACTION_RESPOND_VIA_MESSAGE intenção.

    Para conferir uma visualização detalhada de todas as alterações de API no Android 4.3, consulte o Relatório de diferenças de API.