Android 4.1 APIs

API de nível: 16

O Android 4.1 (JELLY_BEAN) é uma progressão da plataforma que oferece desempenho aprimorado e experiência do usuário aprimorada. Ele adiciona novos recursos para usuários e desenvolvedores de apps. Este documento fornece uma introdução às novas APIs mais importantes e úteis para desenvolvedores de apps.

Como desenvolvedor de apps, o Android 4.1 está disponível para você no SDK Manager como uma imagem do sistema que pode ser executada no Android Emulator e em uma plataforma do SDK em que é possível criar seu app. Faça o download da imagem e da plataforma do sistema o mais rápido possível para criar e testar seu app no Android 4.1.

Para otimizar melhor seu app para dispositivos com o Android 4.1, defina targetSdkVersion como "16", instale-o em uma imagem do sistema Android 4.1, teste e publique uma atualização com essa mudança.

Você pode usar APIs no Android 4.1 e, ao mesmo tempo, oferecer suporte a versões mais antigas, adicionando condições ao código que verificam o nível da API do sistema antes de executar APIs sem suporte da minSdkVersion. Para saber mais sobre como manter a compatibilidade com versões anteriores, leia Como criar IUs compatíveis com versões anteriores.

Para mais informações sobre como os níveis da API funcionam, consulte O que é o nível da API?.

Componentes do app

Serviços isolados

Ao especificar android:isolatedProcess="true" na tag <service>, sua Service será executada no próprio processo isolado de ID do usuário sem permissões próprias.

Gerenciamento de memória

Novas constantes ComponentCallbacks2, como TRIM_MEMORY_RUNNING_LOW e TRIM_MEMORY_RUNNING_CRITICAL, fornecem processos em primeiro plano mais informações sobre o estado da memória antes que o sistema chame onLowMemory().

O novo método getMyMemoryState(ActivityManager.RunningAppProcessInfo) permite que você extraia o estado geral da memória.

Provedores de conteúdo

Um novo método, acquireUnstableContentProviderClient(), permite acessar uma ContentProviderClient que pode ser "instável" para que o app não falhe se o provedor de conteúdo falhar. Ele é útil ao interagir com provedores de conteúdo em um app separado.

Planos fundo interativos

Novo protocolo de intent para iniciar diretamente a atividade de visualização do plano de fundo interativo para que você possa ajudar os usuários a selecionar seu plano de fundo interativo com facilidade, sem forçá-los a sair do app e navegar pelo seletor do plano de fundo interativo.

Para iniciar o seletor de plano de fundo interativo, chame startActivity() com um Intent usando ACTION_CHANGE_LIVE_WALLPAPER e um extra que especifique o plano de fundo interativo ComponentName como uma string em EXTRA_LIVE_WALLPAPER_COMPONENT.

Navegação na pilha de apps

O Android 4.1 facilita muito a implementação dos padrões de design adequados para a navegação Para cima. Você só precisa adicionar o android:parentActivityName a cada elemento <activity> no arquivo de manifesto. O sistema usa essas informações para abrir a atividade adequada quando o usuário pressiona o botão "Para cima" na barra de ações (ao mesmo tempo que conclui a atividade atual). Portanto, se você declarar o android:parentActivityName para cada atividade, não vai precisar do método onOptionsItemSelected() para processar eventos de clique no ícone do app da barra de ações. O sistema agora vai processar esse evento e retomar ou criar a atividade adequada.

Isso é particularmente útil para cenários em que o usuário entra em uma das atividades do app por meio de uma intent de "mergulho profundo", como em uma notificação ou uma intent de um app diferente (conforme descrito no guia de design de Como navegar entre apps). Quando o usuário insere sua atividade dessa maneira, o app pode não ter naturalmente uma backstack de atividades que podem ser retomadas à medida que o usuário navega para cima. No entanto, quando você fornece o atributo android:parentActivityName para suas atividades, o sistema reconhece se o app já tem uma backstack de atividades pai e, caso não tenha, vai criar uma backstack sintética que contenha todas as atividades pai.

Observação:quando o usuário insere uma atividade profunda no app e cria uma nova tarefa para o app, o sistema insere a pilha de atividades mãe na tarefa. Dessa forma, pressionar o botão "Voltar" também navega de volta pela pilha de atividades pai.

Quando o sistema cria uma backstack sintética para o app, ele gera uma Intent básica para gerar uma nova instância de cada atividade mãe. Portanto, não há estado salvo para as atividades mãe, da maneira esperada que o usuário navegasse naturalmente por cada atividade. Se alguma das atividades pai normalmente mostrar uma interface dependente do contexto do usuário, essas informações estarão ausentes e você precisará fornecê-las quando o usuário navegar de volta pela pilha. Por exemplo, se o usuário estiver visualizando um álbum em um app de música, navegar para cima poderá levar a uma atividade que lista todos os álbuns de um gênero de música escolhido. Nesse caso, se a pilha precisar ser criada, será necessário informar à atividade pai a que gênero o álbum atual pertence para que o pai possa exibir a lista adequada como se o usuário realmente viesse dessa atividade. Para enviar essas informações a uma atividade mãe sintética, é necessário substituir o método onPrepareNavigateUpTaskStack(). Isso fornece um objeto TaskStackBuilder que o sistema criou para sintetizar as atividades pai. O TaskStackBuilder contém objetos Intent que o sistema usa para criar cada atividade mãe. Na implementação do onPrepareNavigateUpTaskStack(), você pode modificar a Intent adequada para adicionar outros dados que a atividade mãe possa usar para determinar o contexto adequado e mostrar a interface adequada.

Quando o sistema cria a TaskStackBuilder, ele adiciona os objetos Intent usados para criar as atividades mãe na ordem lógica, começando pela parte de cima da árvore de atividades. Portanto, o último Intent adicionado à matriz interna é o pai direto da atividade atual. Se você quiser modificar o Intent do pai da atividade, primeiro determine o comprimento da matriz com getIntentCount() e transmita esse valor para editIntentAt().

Se a estrutura do app for mais complexa, há várias outras APIs disponíveis que permitem lidar com o comportamento da navegação para cima e personalizar totalmente a backstack sintética. Estas são algumas das APIs que oferecem mais controle:

onNavigateUp()
Substitua isso para executar uma ação personalizada quando o usuário pressionar o botão "Para cima".
navigateUpTo(Intent)
Chame para concluir a atividade atual e ir para a atividade indicada pelo Intent fornecido. Se a atividade existir na backstack, mas não for o pai mais próximo, todas as outras atividades entre a atividade atual e a especificada com a intent também serão concluídas.
getParentActivityIntent()
Chame esta função para receber a Intent que iniciará o pai lógico da atividade atual.
shouldUpRecreateTask(Intent)
Chame para consultar se uma backstack sintética precisa ser criada para navegar para cima. Retorna verdadeiro se uma pilha sintética precisar ser criada e falso se a pilha apropriada já existir.
finishAffinity()
Chame para concluir a atividade atual e todas as atividades mãe com a mesma afinidade de tarefa encadeada à atividade atual. Se você substituir os comportamentos padrão, como onNavigateUp(), chame esse método ao criar uma backstack sintética na navegação para cima.
onCreateNavigateUpTaskStack
Substitua essa opção se você precisar controlar totalmente como a pilha de tarefas sintética é criada. Se você quiser simplesmente adicionar mais dados às intents da backstack, substitua onPrepareNavigateUpTaskStack()

No entanto, a maioria dos apps não precisa usar essas APIs ou implementar onPrepareNavigateUpTaskStack(), mas pode alcançar o comportamento correto simplesmente adicionando android:parentActivityName a cada elemento <activity>.

Multimídia

Codecs de mídia

A classe MediaCodec fornece acesso a codecs de mídia de baixo nível para codificar e decodificar sua mídia. É possível instanciar um MediaCodec chamando createEncoderByType() para codificar mídia ou createDecoderByType() para decodificar mídia. Cada um desses métodos usa um tipo MIME para o tipo de mídia que você quer codificar ou decodificar, por exemplo, "video/3gpp" ou "audio/vorbis".

Com uma instância de MediaCodec criada, você pode chamar configure() para especificar propriedades como o formato de mídia ou se o conteúdo é criptografado ou não.

Esteja você codificando ou decodificando a mídia, o restante do processo será o mesmo depois de criar o MediaCodec. Primeiro, chame getInputBuffers() para receber uma matriz de objetos ByteBuffer de entrada e getOutputBuffers() para receber uma matriz de objetos ByteBuffer de saída.

Quando estiver tudo pronto para codificar ou decodificar, chame dequeueInputBuffer() para receber a posição do índice do ByteBuffer (da matriz de buffers de entrada) que você precisa usar para alimentar a mídia de origem. Depois de preencher ByteBuffer com a mídia de origem, libere a propriedade do buffer chamando queueInputBuffer().

Da mesma forma, para o buffer de saída, chame dequeueOutputBuffer() para conferir a posição do índice do ByteBuffer em que você vai receber os resultados. Depois de ler a saída de ByteBuffer, libere a propriedade chamando releaseOutputBuffer().

Você pode processar dados de mídia criptografados nos codecs chamando queueSecureInputBuffer() em vez das APIs MediaCrypto, em vez do queueInputBuffer() normal.

Para mais informações sobre como usar codecs, consulte a documentação MediaCodec.

Gravar áudio no sinal

O novo método startRecording() permite que você inicie a gravação de áudio com base em um sinal definido por um MediaSyncEvent. O MediaSyncEvent especifica uma sessão de áudio (como uma definida por MediaPlayer), que, quando concluída, aciona o gravador de áudio para iniciar a gravação. Por exemplo, você pode usar essa funcionalidade para tocar um toque de áudio que indique o início de uma sessão de gravação, e a gravação começa automaticamente para que você não precise sincronizar manualmente o tom e o início da gravação.

Faixas de texto com marcação de tempo

O MediaPlayer agora processa faixas de texto dentro e fora de banda. As faixas de texto em banda são fornecidas como uma faixa de texto em uma fonte de mídia MP4 ou 3GPP. As faixas de texto fora de banda podem ser adicionadas como uma origem de texto externa usando o método addTimedTextSource(). Depois que todas as origens de faixas de texto externas forem adicionadas, getTrackInfo() precisará ser chamado para ver a lista atualizada de todas as faixas disponíveis em uma fonte de dados.

Para definir a faixa a ser usada com o MediaPlayer, é necessário chamar selectTrack(), usando a posição de índice da faixa que você quer usar.

Para receber uma notificação quando a faixa de texto estiver pronta para ser reproduzida, implemente a interface MediaPlayer.OnTimedTextListener e transmita-a para setOnTimedTextListener().

Efeitos de áudio

A classe AudioEffect agora oferece suporte a outros tipos de pré-processamento de áudio ao capturar áudio:

  • O cancelamento de eco acústico (AEC, na sigla em inglês) com AcousticEchoCanceler remove a contribuição do sinal recebido do dispositivo remoto pelo sinal de áudio capturado.
  • O Controle automático de ganho (AGC, na sigla em inglês) com AutomaticGainControl normaliza automaticamente a saída do sinal capturado.
  • O supressor de ruído (NS, na sigla em inglês) com NoiseSuppressor remove o ruído de fundo do sinal capturado.

É possível aplicar esses efeitos de pré-processador ao áudio capturado com um AudioRecord usando uma das subclasses AudioEffect.

Observação:não é possível garantir que todos os dispositivos ofereçam suporte a esses efeitos. Portanto, sempre verifique a disponibilidade chamando isAvailable() na classe de efeito de áudio correspondente.

Reprodução sem intervalos

Agora você pode executar a reprodução sem lacunas entre dois objetos MediaPlayer separados. A qualquer momento antes do primeiro MediaPlayer terminar, chame setNextMediaPlayer(), e o Android tenta iniciar o segundo jogador assim que o primeiro é interrompido.

Roteador de mídia. As novas APIs MediaRouter, MediaRouteActionProvider e MediaRouteButton fornecem mecanismos padrão e IU para escolher onde reproduzir a mídia.

Câmera

Movimento de foco automático

A nova interface Camera.AutoFocusMoveCallback permite que você detecte mudanças no movimento de foco automático. Você pode registrar sua interface com setAutoFocusMoveCallback(). Depois, quando a câmera estiver em um modo de foco automático contínuo (FOCUS_MODE_CONTINUOUS_VIDEO ou FOCUS_MODE_CONTINUOUS_PICTURE), você receberá uma chamada para onAutoFocusMoving(), que informa se o foco automático começou a se mover ou parou de se mover.

Sons da câmera

A classe MediaActionSound oferece um conjunto simples de APIs para produzir sons padrão feitos pela câmera ou por outras ações de mídia. Use essas APIs para reproduzir o som adequado ao criar uma câmera estática ou de vídeo personalizada.

Para tocar um som, basta instanciar um objeto MediaActionSound, chamar load() para pré-carregar o som desejado e, no momento adequado, chamar play().

Conectividade

Android Beam

O Android BeamTM agora oferece suporte a grandes transferências de payload por Bluetooth. Quando você define os dados a serem transferidos com o novo método setBeamPushUris() ou com a nova interface de callback NfcAdapter.CreateBeamUrisCallback, o Android entrega a transferência de dados para Bluetooth ou outro transporte alternativo para alcançar velocidades de transferência mais rápidas. Isso é especialmente útil para grandes payloads, como arquivos de imagem e áudio, e não exige pareamento visível entre os dispositivos. Seu app não precisa fazer mais nada para aproveitar as transferências por Bluetooth.

O método setBeamPushUris() usa uma matriz de objetos Uri que especificam os dados que você quer transferir do app. Como alternativa, você pode implementar a interface NfcAdapter.CreateBeamUrisCallback, que pode ser especificada para sua atividade chamando setBeamPushUrisCallback().

Ao usar a interface de callback, o sistema chama o método createBeamUris() da interface quando o usuário executa um compartilhamento com o Android Beam para que você possa definir os URIs a serem compartilhados no momento do compartilhamento. Isso é útil se os URIs a serem compartilhados variam de acordo com o contexto do usuário dentro da atividade, enquanto chamar setBeamPushUris() é útil quando os URIs a serem compartilhados não mudam e você pode defini-los com segurança antecipadamente.

Detecção de serviço de rede

O Android 4.1 adiciona suporte à descoberta de serviços baseada em DNS multicast, que permite encontrar e se conectar a serviços oferecidos por dispositivos de peering por Wi-Fi, como dispositivos móveis, impressoras, câmeras, players de mídia e outros registrados na rede local.

O novo pacote android.net.nsd contém as novas APIs que permitem transmitir serviços na rede local, descobrir dispositivos locais na rede e se conectar a eles.

Para registrar seu serviço, primeiro crie um objeto NsdServiceInfo e defina as várias propriedades do serviço com métodos como setServiceName(), setServiceType() e setPort().

Em seguida, é necessário implementar NsdManager.RegistrationListener e transmiti-lo para registerService() com seu NsdServiceInfo.

Para descobrir serviços na rede, implemente NsdManager.DiscoveryListener e transmita-o para discoverServices().

Quando seu NsdManager.DiscoveryListener recebe callbacks sobre os serviços encontrados, é necessário resolver o serviço chamando resolveService(), transmitindo uma implementação de NsdManager.ResolveListener que recebe um objeto NsdServiceInfo contendo informações sobre o serviço descoberto, permitindo que você inicie a conexão.

Descoberta de serviços Wi-Fi P2P

As APIs de Wi-Fi P2P foram aprimoradas no Android 4.1 para oferecer suporte à descoberta de serviços de pré-associação no WifiP2pManager. Isso permite que você descubra e filtre dispositivos próximos por serviços usando o Wi-Fi P2P antes de se conectar a um, enquanto a descoberta de serviços de rede permite descobrir um serviço em uma rede conectada existente (como uma rede Wi-Fi local).

Para transmitir seu app como um serviço por Wi-Fi para que outros dispositivos possam descobrir seu app e se conectar a ele, chame addLocalService() com um objeto WifiP2pServiceInfo que descreva os serviços do seu app.

Para iniciar a descoberta de dispositivos por perto por Wi-Fi, primeiro você precisa decidir se vai se comunicar usando o Bonjour ou o Upnp. Para usar o Bonjour, primeiro configure alguns listeners de callback com setDnsSdResponseListeners(), que usa WifiP2pManager.DnsSdServiceResponseListener e WifiP2pManager.DnsSdTxtRecordListener. Para usar o Upnp, chame setUpnpServiceResponseListener(), que usa um WifiP2pManager.UpnpServiceResponseListener.

Antes de começar a descobrir serviços em dispositivos locais, você também precisa chamar addServiceRequest(). Quando o WifiP2pManager.ActionListener transmitido para esse método receber um callback, você poderá começar a descobrir serviços em dispositivos locais chamando discoverServices().

Quando serviços locais forem descobertos, você vai receber uma chamada de retorno para WifiP2pManager.DnsSdServiceResponseListener ou WifiP2pManager.UpnpServiceResponseListener, dependendo se você se registrou para usar o Bonjour ou o Upnp. Em ambos os casos, o callback recebido contém um objeto WifiP2pDevice que representa o dispositivo de peering.

Uso da rede

O novo método isActiveNetworkMetered() permite que você verifique se o dispositivo está conectado a uma rede limitada. Ao verificar esse estado antes de realizar transações intensivas de rede, você ajuda a gerenciar o uso de dados que pode gerar custos e tomar decisões informadas sobre fazer as transações agora ou depois (como quando o dispositivo se conecta ao Wi-Fi).

Acessibilidade

APIs de serviço de acessibilidade

O alcance das APIs de serviço de acessibilidade aumentou significativamente no Android 4.1. Agora, é possível criar serviços que monitoram e respondem a mais eventos de entrada, como gestos complexos usando onGesture() e outros eventos de entrada, fazendo adições às classes AccessibilityEvent, AccessibilityNodeInfo e AccessibilityRecord.

Os serviços de acessibilidade também podem realizar ações em nome do usuário, incluindo clicar, rolar e percorrer o texto usando performAction e setMovementGranularities. O método performGlobalAction() também permite que os serviços executem ações como "Voltar", "Início" e "Apps e notificações recentes".

Navegação personalizável do app

Ao criar um app Android, agora você pode personalizar esquemas de navegação, encontrando elementos e widgets de entrada focalizáveis usando findFocus() e focusSearch(), e definir o foco usando setAccessibilityFocused().

Widgets mais acessíveis

A nova classe android.view.accessibility.AccessibilityNodeProvider permite mostrar visualizações personalizadas complexas para serviços de acessibilidade, para que eles possam apresentar as informações de forma mais acessível. O android.view.accessibility.AccessibilityNodeProvider permite que um widget de usuário com conteúdo avançado, como uma grade de agenda, apresente uma estrutura semântica lógica para serviços de acessibilidade completamente separada da estrutura de layout do widget. Essa estrutura semântica permite que os serviços de acessibilidade apresentem um modelo de interação mais útil para usuários com deficiência visual.

Copiar e colar

Copiar e colar com intents

Agora você pode associar um objeto ClipData a um Intent usando o método setClipData(). Isso é especialmente útil ao usar uma intent para transferir vários URIs content: para outro aplicativo, como ao compartilhar vários documentos. Os URIs content: fornecidos dessa maneira também respeitarão as flags da intent para oferecer acesso de leitura ou gravação, permitindo que você conceda acesso a vários URIs em uma intent. Ao iniciar uma intent ACTION_SEND ou ACTION_SEND_MULTIPLE, os URIs fornecidos nela agora são propagados automaticamente para ClipData para que o receptor possa ter acesso a eles.

Suporte a estilos de HTML e string

A classe ClipData agora oferece suporte a texto com estilo, como strings estilizadas HTML ou do Android. É possível adicionar texto com estilo HTML a ClipData usando newHtmlText().

RenderScript

A funcionalidade de computação de Renderscript foi aprimorada com os seguintes recursos:

  • Suporte a vários kernels dentro de um script.
  • Suporte à leitura da alocação com amostras filtradas da computação em uma nova API de script rsSample.
  • Suporte a diferentes níveis de precisão de FP em #pragma.
  • Suporte para consultar outras informações de objetos RS a partir de um script de computação.
  • Várias melhorias de desempenho.

Novos pragmas também estão disponíveis para definir a precisão de ponto flutuante exigida pelos Renderscripts de computação. Isso permite ativar operações semelhantes às do NEON, por exemplo, operações matemáticas de vetor rápido no caminho da CPU, que não seriam possíveis com o padrão IEEE 754-2008 completo.

Observação:o mecanismo experimental de gráficos Renderscript foi descontinuado.

Animação

Animações de inicialização de atividades

Agora você pode iniciar uma Activity usando animações de zoom ou suas próprias animações personalizadas Para especificar a animação que você quer, use as APIs ActivityOptions para criar uma Bundle que pode ser transmitida para qualquer um dos métodos que iniciam uma atividade, como startActivity().

A classe ActivityOptions inclui um método diferente para cada tipo de animação que você queira mostrar à medida que a atividade é aberta:

makeScaleUpAnimation()
Cria uma animação que dimensiona a janela de atividade a partir de uma posição inicial especificada na tela e um tamanho inicial especificado. Por exemplo, a tela inicial no Android 4.1 usa isso ao abrir um app.
makeThumbnailScaleUpAnimation()
Cria uma animação que dimensiona a janela de atividade começando de uma posição especificada e uma imagem de miniatura fornecida. Por exemplo, a janela "Apps recentes" no Android 4.1 usa essa opção ao retornar a um app.
makeCustomAnimation()
Cria uma animação definida pelos seus próprios recursos: uma que define a animação para a abertura da atividade e outra para a atividade que está sendo interrompida.

Animador de tempo

O novo TimeAnimator oferece um mecanismo de callback simples com o TimeAnimator.TimeListener, que notifica você a cada frame da animação. Não há duração, interpolação ou definição de valor de objeto com esse Animator. O callback do listener recebe informações para cada frame, incluindo o tempo decorrido total e o tempo decorrido desde o frame de animação anterior.

Interface do usuário

Notificações

No Android 4.1, é possível criar notificações com regiões de conteúdo maiores, visualizações de imagens grandes, vários botões de ação e prioridade configurável.

Estilos de notificação

O novo método setStyle() permite especificar um dos três novos estilos para notificação, cada um oferecendo uma região de conteúdo maior. Para especificar o estilo para sua região de conteúdo grande, transmita a setStyle() um dos seguintes objetos:

Notification.BigPictureStyle
Para notificações que incluem um anexo de imagem grande.
Notification.BigTextStyle
Para notificações que incluem muito texto, como um único e-mail.
Notification.InboxStyle
Para notificações que incluem uma lista de strings, como snippets de vários e-mails.
Ações da notificação

Agora há suporte para até dois botões de ação que aparecem na parte de baixo da mensagem de notificação, independente de ela usar o estilo normal ou maior.

Para adicionar um botão de ação, chame addAction(). Esse método usa três argumentos: um recurso drawable para um ícone, um texto para o botão e um PendingIntent que define a ação a ser executada.

Prioridades

Agora, você pode indicar ao sistema a importância da notificação para afetar a ordem dela na lista, definindo a prioridade com setPriority(). É possível transmitir esse dos cinco níveis de prioridade diferentes definidos pelas constantes PRIORITY_* na classe Notification. O padrão é PRIORITY_DEFAULT, e há dois níveis mais altos e dois mais baixos.

Notificações de alta prioridade são itens a que os usuários geralmente querem responder rapidamente, como uma nova mensagem instantânea, mensagem de texto ou lembrete de evento iminente. Notificações de baixa prioridade são eventos como eventos da agenda expirados ou promoções de apps.

Controles da interface do sistema

O Android 4.0 (Ice Cream Sandwich) adicionou novas sinalizações para controlar a visibilidade dos elementos da IU do sistema, como escurecer a aparência da barra do sistema ou fazê-la desaparecer completamente em celulares. O Android 4.1 adiciona mais algumas flags que permitem controlar ainda mais a aparência dos elementos da IU do sistema e o layout da atividade em relação a eles chamando setSystemUiVisibility() e transmitindo estas flags:

SYSTEM_UI_FLAG_FULLSCREEN
Oculta a interface não essencial do sistema, como a barra de status. Se a atividade usar a barra de ações no modo de sobreposição (ativando android:windowActionBarOverlay), essa sinalização também ocultará a barra de ação e fará isso com uma animação coordenada ao ocultar e exibir as duas.
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
Define o layout da atividade para usar a mesma área de tela disponível quando você ativou SYSTEM_UI_FLAG_FULLSCREEN, mesmo que os elementos da IU do sistema ainda estejam visíveis. Embora partes do layout sejam sobrepostas pela interface do sistema, isso é útil se o app geralmente se oculta e mostra a interface com SYSTEM_UI_FLAG_FULLSCREEN, porque evita que o layout se ajuste aos novos limites sempre que a interface é oculta ou exibida.
SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
Define o layout da atividade para usar a mesma área de tela disponível quando você ativou SYSTEM_UI_FLAG_HIDE_NAVIGATION (adicionado no Android 4.0), mesmo que os elementos da interface do sistema ainda estejam visíveis. Embora partes do layout sejam sobrepostas pela barra de navegação, isso é útil se o app costuma ocultar e mostrar a barra de navegação com SYSTEM_UI_FLAG_HIDE_NAVIGATION, porque evita que o layout se ajuste aos novos limites sempre que a barra de navegação é oculta ou exibida.
SYSTEM_UI_FLAG_LAYOUT_STABLE
É recomendável adicionar essa sinalização se você estiver usando SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN e/ou SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION para garantir que, ao chamar fitSystemWindows() em uma visualização, os limites definidos permaneçam consistentes em relação ao espaço de tela disponível. Ou seja, com essa flag definida, fitSystemWindows() se comportará como se a visibilidade dos elementos da IU do sistema não fosse alterada, mesmo depois de ocultar toda a IU do sistema.

Para ver mais discussões sobre as outras sinalizações de IU do sistema relacionadas, leia sobre as que foram adicionadas no Android 4.0.

Visualizações remotas

GridLayout e ViewStub agora são visualizações remotas para que você possa usá-las em layouts para seus widgets de apps e layouts personalizados de notificação.

Famílias de fontes

O Android 4.1 adiciona muitas outras variantes do estilo de fonte Roboto, totalizando 10 variantes, e todas elas podem ser usadas por apps. Seus apps agora têm acesso ao conjunto completo de variantes leves e condensadas.

O conjunto completo de variantes de fonte Roboto disponíveis é:

  • Regular
  • Itálico
  • Negrito
  • Negrito e itálico
  • Claro
  • itálico-claro
  • Normal condensado
  • Itálico condensado
  • Negrito condensado
  • Negrito e itálico condensado

É possível aplicar qualquer um deles com o novo atributo fontFamily em combinação com o atributo textStyle.

Os valores aceitos para fontFamily são:

  • "sans-serif" para Roboto normal
  • "sans-serif-light" para Roboto Light
  • "sans-serif-condensed" para Roboto Condensed

Em seguida, você pode aplicar negrito e/ou itálico com os valores "bold" e "italic" de textStyle. É possível aplicar as duas formas: android:textStyle="bold|italic".

Você também pode usar Typeface.create(). Por exemplo, Typeface.create("sans-serif-light", Typeface.NORMAL).

Estrutura de entrada

Vários dispositivos de entrada

A nova classe InputManager permite que você consulte o conjunto de dispositivos de entrada conectados no momento e se registre para receber uma notificação quando um novo dispositivo for adicionado, modificado ou removido. Isso é particularmente útil se você está criando um jogo que oferece suporte a vários jogadores e quer detectar quantos controles estão conectados e quando há mudanças no número de controles.

É possível consultar todos os dispositivos de entrada conectados chamando getInputDeviceIds(). Isso retorna uma matriz de números inteiros, cada um sendo um ID para um dispositivo de entrada diferente. Você pode chamar getInputDevice() para adquirir um InputDevice para um ID de dispositivo de entrada especificado.

Se você quiser receber um aviso quando novos dispositivos de entrada forem conectados, alterados ou desconectados, implemente a interface InputManager.InputDeviceListener e registre-a com registerInputDeviceListener().

Vibrar para controladores de entrada

Se os dispositivos de entrada conectados tiverem os próprios recursos de vibração, agora será possível controlar a vibração desses dispositivos usando as APIs Vibrator existentes, basta chamar getVibrator() no InputDevice.

Permissões

Confira a seguir as novas permissões:

READ_EXTERNAL_STORAGE
Dá acesso de leitura protegido ao armazenamento externo. No Android 4.1, por padrão, todos os aplicativos ainda têm acesso de leitura. Isso será alterado em uma versão futura para exigir que os aplicativos solicitem explicitamente acesso de leitura usando essa permissão. Se o aplicativo já solicitar acesso de gravação, ele também receberá acesso de leitura automaticamente. Há uma nova opção para ativar a restrição de acesso de leitura. Com ela, os desenvolvedores podem testar os aplicativos em relação a como o Android vai se comportar no futuro.
android.Manifest.permission.READ_USER_DICTIONARY
Permite que um aplicativo leia o dicionário do usuário. Isso só precisa ser exigido por um IME ou um editor de dicionário, como o app Configurações.
READ_CALL_LOG
Permite que um aplicativo leia o registro de chamadas do sistema que contém informações sobre chamadas recebidas e realizadas.
WRITE_CALL_LOG
Permite que um aplicativo modifique o registro de chamadas do sistema armazenado no smartphone
android.Manifest.permission.WRITE_USER_DICTIONARY
Permite que um aplicativo grave no dicionário de palavras do usuário.

Recursos do dispositivo

O Android 4.1 inclui uma nova declaração de recurso para dispositivos dedicados a exibir a interface do usuário em uma tela de televisão: FEATURE_TELEVISION. Para declarar que seu app exige uma interface de televisão, declare esse recurso no arquivo de manifesto com o elemento <uses-feature>:

<manifest ... >
    <uses-feature android:name="android.hardware.type.television"
                  android:required="true" />
    ...
</manifest>

Esse recurso define "televisão" como uma experiência típica de televisão na sala de estar: exibida em uma tela grande, com o usuário sentado a longe, e a forma dominante de entrada é algo como um botão direcional, e geralmente não por toque ou um mouse/dispositivo apontador.