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 baixar a imagem do sistema Android 4.3 e a plataforma do SDK do SDK Manager como assim que possível. Se você não tiver um dispositivo com Android 4.3 no qual testar seu aplicativo, use o sistema Android 4.3 para testar seu app no Android Emulator. Em seguida, crie seus aplicativos na plataforma Android 4.3 para começar a usar a 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.

Também há várias APIs disponíveis na Biblioteca de Suporte do Android que permitem implementar novos recursos em versões mais antigas da plataforma.

Para mais informações sobre como os níveis de API funcionam, leia O que é a API Nível?

Mudanças de comportamento importantes

Se você já publicou um aplicativo para Android, esteja ciente de que ele pode afetadas por mudanças no Android 4.3.

Se o app usa intents implícitas...

Seu app pode ter um comportamento inadequado 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 Navegador da Web e app de câmera desativados. Portanto, seu app não deve fazer suposições sobre quais aplicativos são disponível, porque se você chamar startActivity() sem Verificar se um app está disponível para processar Intent seu app pode 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á apresentar falhas ou se comportar. inesperadamente quando usado em um perfil restrito.

Se você quiser impedir que perfis restritos usem seu app inteiramente 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 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 parecer 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" com "match_parent" e verifique se seu vídeo aparece conforme esperado em Android 4.3 e 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, ao usar as novas APIs, você pode permitem que os usuários controlem o tipo de conteúdo disponível no aplicativo quando ele for 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 é verdadeiro ou falso.
  • TYPE_CHOICE para uma restrição que tem múltiplas escolhas mutuamente exclusivas (opções de botões de opção);
  • TYPE_MULTI_SELECT para uma restrição que tem múltiplas opções que não são mutuamente exclusivas (opções de caixa de seleção);

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

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 o 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. Em seu broadcast receiver, inclua o extra EXTRA_RESTRICTIONS_INTENT no resultado Bundle. Esse extra precisa especificar um objeto Intent. indicando que a classe Activity será iniciada (use o 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 retornar um resultado que contenha 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 enquanto estiver em uma conta perfil, você 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: a ativação desse atributo fornece acesso do app às contas do usuário principal a partir de perfis restritos. Você deve permitir isso somente se as informações exibidas pelo aplicativo não revelarem informações de identificação pessoal (PII) considerados 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.

  • Desative algumas funcionalidades quando não for possível modificar contas.

    Se você quiser usar contas sem precisar delas para a conta principal do app. poderá verificar a disponibilidade da conta e desativar os recursos quando eles não estiverem disponíveis. Primeiro, verifique se já existe uma conta disponível. Caso contrário, consulte É 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 a 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 de baixa energia (LE) com novas APIs em android.bluetooth. Com as novas APIs, você pode criar aplicativos Android que se comunicam por 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 existe uma classe BluetoothManager que você precisa usar para algumas operações de alto nível. como conseguir um BluetoothAdapter ou uma lista de objetos 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 procurar dispositivos com Bluetooth LE ou procurar por dispositivos Bluetooth clássicos 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, transmitindo uma implementação do BluetoothGattCallback Sua implementação de BluetoothGattCallback recebe callbacks relacionados à 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 aplicativo solicite determinadas Permissões de usuário do Bluetooth. Para ver mais informações, consulte o guia da API Bluetooth Low Energy.

    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 muitas vezes mantêm o Wi-Fi desativado para economizar bateria, resultando em dados de localização menos precisos. O Android agora inclui modo de somente busca, que permite ao Wi-Fi do dispositivo procurar pontos de acesso para ajudar a obter a localização sem conectar-se a um ponto de acesso, reduzindo significativamente o uso da bateria.

    Se você quiser saber a localização do usuário, mas o Wi-Fi estiver desativado, solicite a o usuário ative o modo somente busca por 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 chamadas 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 MediaCodec

    O Android agora facilita a criação de modelos adaptativos dinâmicos Players de streaming por HTTP (DASH) de acordo com a norma 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 mídia criptografada. amostra. Além disso, o método getPsshInfo() foi adicionado a MediaExtractor para acessar os metadados PSSH da sua 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 fornece uma solução modular para direitos digitais. de mídia (DRM, na sigla em inglês) com seu conteúdo de mídia, separando as preocupações com o DRM da reprodução de mídia. Para essa separação de API permite reproduzir 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 extrair mensagens e processos de solicitação de chave opacos mensagens de resposta-chave do servidor para aquisição e provisionamento de licenças. Seu app é responsável por lidar com a comunicação da rede com os servidores, a classe MediaDrm fornece apenas a capacidade de gerar e processar as mensagens.

    As APIs MediaDrm devem ser usadas em conjunto com o APIs MediaCodec que foram introduzidas no Android 4.1 (nível 16 da API), incluindo MediaCodec para codificar e decodificar o 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 sistema 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 um Surface

    O Android 4.1 (API de nível 16) adicionou a classe MediaCodec para codificação e decodificação do conteúdo de mídia. Ao codificar vídeos, o Android 4.1 exigia que você fornecesse a mídia com uma matriz ByteBuffer, mas o Android 4.3 agora permite que você use um Surface como a 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, você pode usar o Surface fornecido como a janela para um OpenGL o contexto ao transmiti-lo 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 chamar release() 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, MP4 é o único formato de saída compatível e MediaMuxer atualmente somente 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. Também é possível usar MediaMuxer em combinação com MediaExtractor para realizar edição de mídia sem a necessidade de codificar ou decodificar.

    Progresso da reprodução e refinamento para RemoteControlClient

    No Android 4.0 (API de nível 14), o RemoteControlClient foi adicionado a ativar controles de reprodução de mídia a partir de clientes de controle remoto, como os controles disponíveis no tela de bloqueio. O Android 4.3 agora fornece a capacidade de tais controladores exibirem a reprodução posição e controles para arrastar a reprodução. Se você ativou o controle remoto para app de música com as APIs RemoteControlClient, será possível permitir a reprodução o refinamento implementando 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 sua mídia quando o controle remoto precisar 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çar na reprodução com o interface de 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, você pode configurá-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. Nova funcionalidade principal fornecidos no OpenGL ES 3.0 inclui:

    • 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 números inteiros e a pontos flutuantes de 32 bits
    • Renderização avançada de texturas
    • 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 compatibilidade Versão do OpenGL ES no momento da execução, consulte o guia da API do OpenGL ES.

    Mipmapping para drawables

    Usar um mipmap como origem para seu bitmap ou drawable é uma maneira simples de fornecer uma de alta qualidade e várias escalas de imagem, o que pode ser especialmente útil se você espera que seus imagem a ser 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, também é possível ativar mipmaps para um objeto BitmapDrawable, fornecendo um recurso de mipmap e defina o atributo android:mipMap em um arquivo de recurso de bitmap ou chame 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 que sua visualização host (a visualização a partir da qual foi criada), permitindo que você adicione conteúdo que aparece na frente da visualização do host, mas que não pode estender os limites da visualização do host.

    Usar 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 de visualizações. No entanto, como a área utilizável de uma sobreposição é restrita à mesma área que a visualização do host, se quiser animar uma visualização se movendo para fora sua posição no layout, você deve usar uma sobreposição de uma visualização pai que tenha a posição desejada limites de layout.

    Ao criar uma sobreposição para uma visualização de widget, como uma Button, você pode adicionar objetos Drawable à sobreposição chamando add(Drawable) Se você chamar getOverlay() para uma visualização de layout, como RelativeLayout, o objeto retornado é um ViewGroupOverlay. A 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 é usando limites de corte (o comportamento padrão), enquanto a figura 2 usa 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 quando são usados 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, linhas vermelhas indicam a óptica limites, as linhas azuis indicam os limites de corte e rosa indica as margens.

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

    Figura 2. Layout que usa 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 suas visualizações precisam especificar limites ópticos usando linhas vermelhas na parte inferior e à direita do arquivo Nine-Patch (conforme 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 em 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, elementos de layout (subclasses de ViewGroup) No momento, não são compatíveis com limites ópticos para imagens Nine-Patch aplicadas ao próprio plano de fundo.

    Se você criar uma visualização personalizada ao subclassificar View, ViewGroup ou qualquer subclasse dela, ela herdará esses comportamentos vinculados ópticos.

    Observação:todos os widgets compatíveis com o tema Holo foram atualizados. com limites ópticos, incluindo Button, Spinner, EditText e outros. Assim, você pode se beneficiar imediatamente ao definir Atributo android:layoutMode a "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 você pode transmitir para ValueAnimator.setEvaluator().

    Anexar janela e focar o listener

    Anteriormente, se você quisesse detectar quando sua visualização fosse anexada/desanexada da janela ou quando o foco 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, você pode implementar ViewTreeObserver.OnWindowAttachListener e defini-lo 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 <activity> screenOrientation da tag agora suporta outros valores para respeitar a preferência do usuário por rotação automática:

    "userLandscape"
    Se comporta da mesma forma que "sensorLandscape", exceto se o usuário desativar o giro automático ela fica na orientação de paisagem normal e não é virada.
    "userPortrait"
    Se comporta da mesma forma que "sensorPortrait", exceto se o usuário desativar o giro automático ela fica na orientação de retrato normal e não é virada.
    "fullUser"
    Comporta-se da mesma forma que "fullSensor" e permite rotação nas quatro direções, exceto se o usuário desativar o giro automático, ele travará na orientação preferida do usuário.

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

    Animações de rotação

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

    Observação:essas animações só estarão disponíveis se você tiver configurado sua atividade para usar a opção "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 se baseia 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 TYPE_GYROSCOPE e TYPE_MAGNETIC_FIELD atuais os sensores fornecem dados que consideram a tendência estimada de deslocamento em giroscópio e ferro duro no dispositivo, respectivamente. Enquanto o novo modelo dessas versões oferecem os dados brutos do sensor e oferecer separadamente os valores de viés estimados. 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 aplicativo receba informações sobre novas notificações à medida que são postadas pelo sistema.

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

    Provedor de contatos

    Consulta por "contatos para contato"

    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 rastrear 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 somente os contatos que mudaram desde a última consulta com 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 através do menu de configurações do sistema, recriando efetivamente o Banco de dados do Provedor de Contatos. É destinado a sinalizar aos apps que eles precisam remover todos os contatos informações armazenadas e recarregue-as com uma nova consulta.

    Para obter exemplos de código que usam essas APIs para verificar alterações nos contatos, consulte o ApiDemos disponível no download de Amostras de SDK.

    Localização

    Suporte aprimorado para 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 direção oposta. conteúdo sem confundir nenhuma parte dele.

    Por exemplo, quando você deseja criar uma sentença com uma variável de string, como “Você quis dizer 15 Bay Street, Laurel, CA?", você normalmente passa 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, o unicodeWrap() usa o a primeira heurística de estimativa de direcionalidade forte, que pode errar se a primeira para a direção do texto não representa a direção apropriada 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

    Um AccessibilityService agora pode receber um callback para eventos de entrada de tecla com o método de callback onKeyEvent(). Isso permite que o serviço de acessibilidade manipule entradas para dispositivos de entrada baseados em teclas, como um teclado, e traduz esses eventos em ações especiais que antes eram possíveis apenas com a 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 do texto a ser cortado ou copiado, o serviço de acessibilidade pode usar o novo ação, ACTION_SET_SELECTION, transmitindo e 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 o modelo ação, ACTION_NEXT_AT_MOVEMENT_GRANULARITY (anteriormente apenas para mover a posição do cursor) e adicionar 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 por meio do Suporte do Android Biblioteca, com AccessibilityNodeInfoCompat .

    Declarar recursos de acessibilidade

    A partir do Android 4.3, os serviços de acessibilidade precisam declarar os recursos de acessibilidade no arquivo de metadados para usar determinados recursos de acessibilidade. Se o recurso não for solicitado no arquivo de metadados, o recurso será um ambiente autônomo. Para declarar as propriedades recursos de acessibilidade, você deve usar atributos XML que correspondam aos vários "capacidade" constantes no AccessibilityServiceInfo .

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

    Teste e depuração

    Teste automatizado da interface

    A nova classe UiAutomation fornece APIs que permitem simular usuários e ações voltadas à automação de testes. Usando as APIs AccessibilityService da plataforma, o UiAutomation As APIs 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 a transmita 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: A 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 app.

    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 KeyStore chamada Android Key Store, que permite gerar e salvar chaves privadas que só pode ser visto e usado pelo seu app. Para carregar o Android Key Store, transmita "AndroidKeyStore" para KeyStore.getInstance().

    Para gerenciar as credenciais privadas do seu app no Android Key Store, 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 você pode usar KeyPairGeneratorSpec.Builder Por fim, receba o KeyPair chamando generateKeyPair().

    Armazenamento de credenciais de hardware

    O Android agora também oferece suporte ao armazenamento em hardware para seu KeyChain com credenciais mais seguras, o que proporciona mais segurança ao tornar 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 sejam compatíveis com o armazenamento você pode verificar durante a execução se o armazenamento com suporte de hardware está disponível chamando KeyChain.IsBoundKeyAlgorithm():

    Declarações do manifesto

    Recursos necessários declaráveis

    Os seguintes valores agora são compatíveis com <uses-feature> para que você possa garantir que seu aplicativo seja instalado somente em dispositivos que fornecem os recursos de que seu app precisa.

    FEATURE_APP_WIDGETS
    Declara que o app fornece um widget de app e só pode ser instalado em dispositivos que incluir uma tela inicial ou local semelhante em que os usuários possam incorporar widgets de apps. 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 seu app oferece um método de entrada personalizado (um teclado criado com InputMethodService) e que só pode ser instalado em dispositivos que: dão 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 seu app usa APIs Bluetooth Low Energy e só pode ser instalado em dispositivos capazes de 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 seguintes valores agora são compatíveis com <uses-permission> para declarar permissões que seu aplicativo exige para acessar 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 obter uma visão detalhada de todas as mudanças de API no Android 4.3, consulte a Relatório de diferenças da API.