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:
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.
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.
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.
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" ... >
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.