APIs do Android 4.0

Nível da API: 14

O Android 4.0 (ICE_CREAM_SANDWICH) é uma versão principal da plataforma que adiciona vários novos recursos para usuários e desenvolvedores de apps. Além de todos os novos recursos e APIs discutidos abaixo, o Android 4.0 é uma versão de plataforma importante porque leva o amplo conjunto de APIs e temas holográficos do Android 3.x para telas menores. Como desenvolvedor de apps, agora você tem uma única plataforma e um framework de API unificado que permite desenvolver e publicar seu aplicativo com um único APK que oferece uma experiência do usuário otimizada para celulares, tablets e muito mais ao executar a mesma versão do Android: Android 4.0 (nível 14 da API) ou mais recente.

Para desenvolvedores, a plataforma Android 4.0 está disponível como um componente para download do SDK do Android. A plataforma para download inclui uma biblioteca Android e uma imagem do sistema, além de um conjunto de aparências do emulador e muito mais. Para começar a desenvolver ou testar no Android 4.0, use o Android SDK Manager para fazer o download da plataforma no seu SDK.

Visão geral da API

As seções abaixo oferecem uma visão geral técnica das novas APIs no Android 4.0.

APIs sociais no Provedor de contatos

As APIs de contato definidas pelo provedor ContactsContract foram estendidas para oferecer suporte a novos recursos voltados a redes sociais, como um perfil pessoal do proprietário do dispositivo e a capacidade de os usuários convidarem contatos individuais para as redes sociais instaladas no dispositivo.

Perfil do usuário

O Android agora inclui um perfil pessoal que representa o proprietário do dispositivo, conforme definido pela tabela ContactsContract.Profile. Os aplicativos sociais que mantêm uma identidade de usuário podem contribuir com os dados de perfil do usuário criando uma nova entrada ContactsContract.RawContacts no ContactsContract.Profile. Ou seja, os contatos brutos que representam o usuário do dispositivo não pertencem à tabela de contatos brutos tradicionais definida pelo URI ContactsContract.RawContacts. Em vez disso, é necessário adicionar um contato bruto do perfil à tabela em CONTENT_RAW_CONTACTS_URI. Os contatos brutos nessa tabela são agregados a um único perfil visível ao usuário chamado "Eu".

Para adicionar um novo contato bruto ao perfil, é preciso ter a permissão android.Manifest.permission#WRITE_PROFILE. Da mesma forma, para ler a tabela de perfil, é necessário solicitar a permissão android.Manifest.permission#READ_PROFILE. No entanto, a maioria dos apps não precisa ler o perfil do usuário, mesmo ao contribuir com dados para ele. Ler o perfil do usuário é uma permissão confidencial, e você pode esperar que os usuários sejam céticos em relação aos apps que a solicitam.

Intenção do convite

A ação da intent INVITE_CONTACT permite que um app invoque uma ação que indica que o usuário quer adicionar um contato a uma rede social. O app que recebe o app o usa para convidar o contato especificado para essa rede social. A maioria dos apps vai receber essa operação. Por exemplo, o app integrado Pessoas invoca a intent de convite quando o usuário seleciona "Adicionar conexão" para um app social específico que está listado nos detalhes de contato da pessoa.

Para que seu app fique visível como na lista "Adicionar conexão", ele precisa fornecer um adaptador de sincronização para sincronizar os dados de contato da sua rede social. Em seguida, indique ao sistema que seu app responde à intent INVITE_CONTACT adicionando o atributo inviteContactActivity ao arquivo de configuração de sincronização do app, com um nome totalmente qualificado da atividade que o sistema precisa iniciar ao enviar a intent de convite. A atividade iniciada pode recuperar o URI do contato em questão dos dados da intent e realizar o trabalho necessário para convidar esse contato para a rede ou adicionar a pessoa às conexões do usuário.

Fotos grandes

O Android agora oferece suporte a fotos em alta resolução para os contatos. Agora, quando você envia uma foto para um registro de contato, o sistema a processa em uma miniatura de 96x96 (como anteriormente) e uma "foto de exibição" de 256x256 que fica em um novo repositório de fotos baseado em arquivo. As dimensões exatas escolhidas pelo sistema podem variar no futuro. Você pode adicionar uma foto grande a um contato colocando uma foto grande na coluna PHOTO normal de uma linha de dados, que o sistema processará na miniatura adequada e exibirá os registros das fotos.

Entrar em contato com feedback de uso

As novas APIs ContactsContract.DataUsageFeedback permitem monitorar com que frequência o usuário usa métodos específicos para entrar em contato com as pessoas, como a frequência com cada número de telefone ou endereço de e-mail. Essas informações ajudam a melhorar a classificação de cada método de contato associado a cada pessoa e oferecem sugestões melhores para entrar em contato com cada uma.

Provedor de agenda

Com as novas APIs Calendar, você pode ler, adicionar, modificar e excluir agendas, eventos, participantes, lembretes e alertas, que são armazenados no Provedor de Agenda.

Diversos apps e widgets podem usar essas APIs para ler e modificar eventos da agenda. No entanto, alguns dos casos de uso mais interessantes são os adaptadores de sincronização que sincronizam a agenda do usuário de outros serviços com o Provedor de agenda para oferecer um local unificado para todos os eventos do usuário. Os eventos do Google Agenda, por exemplo, são sincronizados com o Provedor de Agenda pelo Adaptador de sincronização do Google Agenda, permitindo que esses eventos sejam visualizados com o app Calendário integrado do Android.

O modelo de dados para agendas e informações relacionadas a eventos no Provedor de Agenda é definido por CalendarContract. Todos os dados da agenda do usuário são armazenados em várias tabelas definidas por várias subclasses de CalendarContract:

  • A tabela CalendarContract.Calendars contém as informações específicas da agenda. Cada linha contém os detalhes de uma única agenda, como nome, cor, informações de sincronização etc.
  • A tabela CalendarContract.Events contém informações específicas do evento. Cada linha dessa tabela contém as informações de um único evento, como o título, o local, o horário de início, o horário de término e assim por diante. O evento pode ocorrer uma vez ou se repetir várias vezes. Participantes, lembretes e propriedades estendidas são armazenados em tabelas separadas e usam o _ID do evento para vinculá-los ao evento.
  • A tabela CalendarContract.Instances contém os horários de início e término das ocorrências de um evento. Cada linha nesta tabela representa uma única ocorrência. Para eventos únicos, há um mapeamento de instâncias para eventos de um para um. Para eventos recorrentes, várias linhas são geradas automaticamente para corresponder às diversas ocorrências desse evento.
  • A tabela CalendarContract.Attendees contém as informações dos participantes ou convidados do evento. Cada linha representa um único convidado de um evento. Ela especifica o tipo de convidado que a pessoa é e a resposta da pessoa para o evento.
  • A tabela CalendarContract.Reminders contém os dados de alerta/notificação. Cada linha representa um único alerta de um evento. Um evento pode ter vários lembretes. O número de lembretes por evento é especificado em MAX_REMINDERS, que é definido pelo adaptador de sincronização que proprietário da agenda fornecida. Os lembretes são especificados em números de minutos antes de o evento ser agendado e um método de alarme, como usar um alerta, e-mail ou SMS para lembrar o usuário.
  • A tabela CalendarContract.ExtendedProperties contém campos de dados opacos usados pelo adaptador de sincronização. O provedor não realiza nenhuma ação com os itens dessa tabela, a não ser excluí-los quando os eventos relacionados são excluídos.

Para acessar os dados de um usuário com o Provedor de agenda, seu aplicativo precisa solicitar a permissão READ_CALENDAR (para acesso de leitura) e WRITE_CALENDAR (para acesso de gravação).

Intent de evento

Se você quiser apenas adicionar um evento à agenda do usuário, poderá usar uma intent ACTION_INSERT com os dados definidos por Events.CONTENT_URI para iniciar uma atividade no app Agenda que crie novos eventos. O uso da intent não requer nenhuma permissão, e você pode especificar detalhes do evento com os extras abaixo:

Provedor de correio de voz

O novo provedor de correio de voz permite que os aplicativos adicionem correios de voz ao dispositivo para mostrar todos os correios de voz do usuário em uma única apresentação visual. Por exemplo, é possível que um usuário tenha várias origens de correio de voz, como uma do provedor de serviços do smartphone e outras do VoIP ou de outros serviços de voz alternativos. Esses apps podem usar as APIs Voicemail Provider para adicionar correios de voz ao dispositivo. Depois, o app Telefone integrado apresenta todos os correios de voz ao usuário em uma apresentação unificada. Embora o aplicativo Telefone do sistema seja o único que possa ler todos os correios de voz, cada aplicativo que fornece correios de voz pode ler aqueles adicionados ao sistema, mas não pode ler mensagens de voz de outros serviços.

Como as APIs atualmente não permitem que apps de terceiros leiam todos os correios de voz do sistema, os únicos apps de terceiros que precisam usar as APIs de correio de voz são aqueles que têm correio de voz para entregar ao usuário.

A classe VoicemailContract define o provedor de conteúdo do Voicemail Provder. As subclasses VoicemailContract.Voicemails e VoicemailContract.Status fornecem tabelas em que os apps podem inserir dados de correio de voz para armazenamento no dispositivo. Para ver um exemplo de um app de provedor de correio de voz, consulte a Demonstração do provedor de correio de voz.

Multimídia

O Android 4.0 adiciona várias novas APIs para aplicativos que interagem com mídia, como fotos, vídeos e músicas.

Efeitos de mídia

Um novo framework de efeitos de mídia permite aplicar vários efeitos visuais a imagens e vídeos. Por exemplo, os efeitos de imagem permitem corrigir olhos vermelhos, converter uma imagem em escala de cinza, ajustar brilho, ajustar a saturação, girar uma imagem, aplicar um efeito olho de peixe e muito mais. O sistema executa o processamento de todos os efeitos na GPU para conseguir o desempenho máximo.

Para um desempenho máximo, os efeitos são aplicados diretamente às texturas do OpenGL. Portanto, o aplicativo precisa ter um contexto válido do OpenGL antes de usar as APIs de efeitos. As texturas em que os efeitos são aplicados podem ser de bitmaps, vídeos ou até mesmo da câmera. No entanto, existem determinadas restrições que as texturas precisam atender:

  1. Elas precisam estar vinculadas a uma imagem de textura GL_TEXTURE_2D.
  2. Eles precisam conter pelo menos um nível de mipmap

Um objeto Effect define um único efeito de mídia que pode ser aplicado a um frame de imagem. O fluxo de trabalho básico para criar um Effect é o seguinte:

  1. Chame EffectContext.createWithCurrentGlContext() no contexto do OpenGL ES 2.0.
  2. Use o EffectContext retornado para chamar EffectContext.getFactory(), que retorna uma instância de EffectFactory.
  3. Chame createEffect(), transmitindo um nome de efeito de @link android.media.effect.EffectFactory}, como EFFECT_FISHEYE ou EFFECT_VIGNETTE.

Para ajustar os parâmetros de um efeito, chame setParameter() e transmita um nome e um valor de parâmetro. Cada tipo de efeito aceita parâmetros diferentes, que são documentados com o nome do efeito. Por exemplo, EFFECT_FISHEYE tem um parâmetro para a scale da distorção.

Para aplicar um efeito a uma textura, chame apply() no Effect e transmita a textura de entrada, a largura e a altura e a textura de saída. A textura de entrada precisa ser vinculada a uma imagem de textura GL_TEXTURE_2D, geralmente feita chamando a função glTexImage2D(). Você pode fornecer vários níveis de mipmap. Se a textura de saída não tiver sido vinculada a uma imagem de textura, ela será vinculada automaticamente pelo efeito como uma GL_TEXTURE_2D e com um nível de mipmap (0), que terá o mesmo tamanho da entrada.

Todos os efeitos listados em EffectFactory têm garantia de suporte. No entanto, alguns outros efeitos disponíveis em bibliotecas externas não têm suporte em todos os dispositivos. Portanto, primeiro é necessário verificar se o efeito desejado da biblioteca externa tem suporte chamando isEffectSupported().

Cliente de controle remoto

O novo RemoteControlClient permite que os players de mídia ativem controles de reprodução de clientes de controle remoto, como a tela de bloqueio do dispositivo. Os players de mídia também podem expor informações sobre a mídia que está sendo reproduzida no momento para exibição no controle remoto, como informações das faixas e a arte do álbum.

Para ativar clientes de controle remoto para seu player de mídia, instancie um RemoteControlClient com o construtor, transmitindo um PendingIntent que transmita ACTION_MEDIA_BUTTON. A intent também precisa declarar o componente BroadcastReceiver explícito que processa o evento ACTION_MEDIA_BUTTON no app.

Para declarar quais entradas de controle de mídia o player pode processar, chame setTransportControlFlags() no RemoteControlClient, transmitindo um conjunto de sinalizações FLAG_KEY_MEDIA_*, como FLAG_KEY_MEDIA_PREVIOUS e FLAG_KEY_MEDIA_NEXT.

Em seguida, você precisa registrar seu RemoteControlClient transmitindo-o para MediaManager.registerRemoteControlClient(). Depois de registrado, o broadcast receiver que você declarou quando instanciou o RemoteControlClient vai receber eventos ACTION_MEDIA_BUTTON quando um botão for pressionado em um controle remoto. A intent recebida inclui o KeyEvent para a tecla de mídia pressionada, que pode ser extraída da intent com getParcelableExtra(Intent.EXTRA_KEY_EVENT).

Para mostrar informações no controle remoto sobre a reprodução de mídia, chame editMetaData() e adicione metadados ao RemoteControlClient.MetadataEditor retornado. Você pode fornecer um bitmap para arte de mídia, informações numéricas, como tempo decorrido, e informações de texto, como o título da música. Para informações sobre chaves disponíveis, consulte as sinalizações METADATA_KEY_* em MediaMetadataRetriever.

Para ver um exemplo de implementação, consulte Random Music Player, que fornece uma lógica de compatibilidade para habilitar o cliente de controle remoto em dispositivos Android 4.0 e manter a compatibilidade com dispositivos desde o Android 2.1.

Player de mídia

  • O streaming de mídia on-line do MediaPlayer agora exige a permissão INTERNET. Se você usar MediaPlayer para abrir conteúdo da Internet, adicione a permissão INTERNET ao manifesto. Caso contrário, a reprodução de mídia não funcionará a partir do Android 4.0.
  • setSurface() permite definir um Surface para se comportar como o coletor de vídeo.
  • setDataSource() permite que você envie cabeçalhos HTTP adicionais com sua solicitação, o que pode ser útil para transmissões ao vivo HTTP(S)
  • A transmissão ao vivo de HTTP(S) agora respeita cookies HTTP nas solicitações

Tipos de mídia

O Android 4.0 adiciona suporte para:

  • Protocolo de transmissão ao vivo HTTP/HTTPS versão 3
  • Codificação de áudio AAC bruto ADTS
  • Imagens WEBP
  • Vídeo de Matroska

Para mais informações, consulte Formatos de mídia compatíveis.

Câmera

A classe Camera agora inclui APIs para detectar rostos e controlar o foco e as áreas de medição.

Detecção facial

Os apps de câmera agora podem melhorar as habilidades com as APIs de detecção facial do Android, que não apenas detectam o rosto de uma pessoa, mas também características faciais específicas, como os olhos e a boca.

Para detectar rostos no aplicativo de câmera, registre um Camera.FaceDetectionListener chamando setFaceDetectionListener(). Em seguida, inicie a superfície da câmera e comece a detectar rostos chamando startFaceDetection().

Quando o sistema detecta um ou mais rostos na cena da câmera, ele chama o callback onFaceDetection() na sua implementação de Camera.FaceDetectionListener, incluindo uma matriz de objetos Camera.Face.

Uma instância da classe Camera.Face fornece várias informações sobre o rosto detectado, incluindo:

  • Um Rect que especifica os limites do rosto em relação ao campo de visão atual da câmera.
  • Um número inteiro entre 1 e 100 que indica o grau de confiança do sistema de que o objeto é um rosto humano.
  • Um ID exclusivo para que você possa rastrear vários rostos
  • Vários objetos Point que indicam onde os olhos e a boca estão localizados

Observação:a detecção facial pode não ser compatível com alguns dispositivos. Por isso, chame getMaxNumDetectedFaces() para conferir se o valor de retorno é maior que zero. Além disso, alguns dispositivos podem não oferecer suporte à identificação de olhos e boca. Nesse caso, os campos no objeto Camera.Face serão nulos.

Áreas de foco e medição

Os apps de câmera agora podem controlar as áreas que a câmera usa para foco e para medir o equilíbrio de branco e a exposição automática. Os dois recursos usam a nova classe Camera.Area para especificar a região da visualização atual da câmera que precisa ser focada ou limitada. Uma instância da classe Camera.Area define os limites da área com um Rect e o peso dela, representando o nível de importância dessa área em relação a outras áreas em questão, com um número inteiro.

Antes de definir uma área de foco ou uma área de medição, chame getMaxNumFocusAreas() ou getMaxNumMeteringAreas(), respectivamente. Se eles retornarem zero, o dispositivo não vai oferecer suporte ao recurso correspondente.

Para especificar as áreas de foco ou medição a serem usadas, basta chamar setFocusAreas() ou setMeteringAreas(). Cada uma usa uma List de objetos Camera.Area que indicam as áreas a serem consideradas para foco ou medição. Por exemplo, você pode implementar um recurso que permite ao usuário definir a área de foco tocando em uma área da visualização, que você traduz em um objeto Camera.Area e solicita que a câmera foque essa área da cena. O foco ou a exposição nessa área são atualizados continuamente conforme a cena muda.

Foco automático contínuo para fotos

Agora você pode ativar o foco automático contínuo (CAF) ao tirar fotos. Para ativar o CAF no app de câmera, transmita FOCUS_MODE_CONTINUOUS_PICTURE para setFocusMode(). Quando estiver tudo pronto para capturar uma foto, chame autoFocus(). Seu Camera.AutoFocusCallback recebe imediatamente um callback para indicar se o foco foi alcançado. Para retomar o CAF depois de receber o callback, é necessário chamar cancelAutoFocus().

Observação:o foco automático contínuo também é compatível com a captura de vídeos usando FOCUS_MODE_CONTINUOUS_VIDEO, que foi adicionado no nível 9 da API.

Outros recursos da câmera

  • Durante a gravação de vídeos, agora você pode chamar takePicture() para salvar uma foto sem interromper a sessão de vídeo. Antes de fazer isso, chame isVideoSnapshotSupported() para ter certeza de que o hardware oferece suporte a ele.
  • Agora você pode bloquear a exposição automática e o balanço de branco com setAutoExposureLock() e setAutoWhiteBalanceLock() para evitar que essas propriedades sejam alteradas.
  • Agora é possível chamar setDisplayOrientation() enquanto a visualização da câmera está em execução. Antes, era possível fazer essa chamada apenas antes de iniciar a visualização, mas agora é possível mudar a orientação a qualquer momento.

Intents de transmissão da câmera

  • Camera.ACTION_NEW_PICTURE: indica que o usuário capturou uma nova foto. O app Câmera integrado invoca essa transmissão depois que uma foto é capturada, e os apps de câmera de terceiros também precisam transmitir essa intent após capturar uma foto.
  • Camera.ACTION_NEW_VIDEO: indica que o usuário capturou um novo vídeo. O app Câmera integrado invoca essa transmissão depois que um vídeo é gravado, e os apps de câmera de terceiros também precisam transmitir essa intent após capturar um vídeo.

Android Beam (envio NDEF com NFC)

O Android Beam é um novo recurso NFC que permite enviar mensagens NDEF de um dispositivo para outro (um processo também conhecido como "envio NDEF"). A transferência de dados é iniciada quando dois dispositivos Android compatíveis com o Android Beam estão próximos (cerca de 4 cm), geralmente com as costas encostadas. Os dados dentro da mensagem NDEF podem conter qualquer dado que você queira compartilhar entre dispositivos. Por exemplo, o app Pessoas compartilha contatos, o YouTube compartilha vídeos, e o navegador compartilha URLs usando o Android Beam.

Para transmitir dados entre dispositivos usando o Android Beam, é necessário criar um NdefMessage que contenha as informações que você quer compartilhar enquanto a atividade estiver em primeiro plano. Em seguida, você precisa transmitir o NdefMessage para o sistema de duas maneiras:

Caso você queira executar um código específico depois que o sistema entregar a mensagem NDEF ao outro dispositivo, implemente NfcAdapter.OnNdefPushCompleteCallback e defina-o com setNdefPushCompleteCallback(). O sistema chamará onNdefPushComplete() quando a mensagem for entregue.

No dispositivo receptor, o sistema envia mensagens push NDEF de maneira semelhante às tags NFC normais. O sistema invoca uma intent com a ação ACTION_NDEF_DISCOVERED para iniciar uma atividade, com um URL ou um tipo MIME definido de acordo com o primeiro NdefRecord no NdefMessage. Para a atividade a que você quer responder, é possível declarar filtros de intent para os URLs ou tipos MIME importantes para seu app. Para mais informações sobre o envio de tags, consulte o guia para desenvolvedores de NFC.

Se você quiser que NdefMessage tenha um URI, agora poderá usar o método de conveniência createUri para construir um novo NdefRecord com base em uma string ou um objeto Uri. Se o URI for um formato especial que você quer que o aplicativo também receba durante um evento do Android Beam, crie um filtro de intent para sua atividade usando o mesmo esquema de URI para receber a mensagem NDEF recebida.

Você também precisa transmitir um "registro do aplicativo Android" com o NdefMessage para garantir que o aplicativo processe a mensagem NDEF recebida, mesmo que outros aplicativos filtrem a mesma ação da intent. É possível criar um registro de aplicativo Android chamando createApplicationRecord() e transmitindo o nome do pacote do seu aplicativo. Quando o outro dispositivo recebe a mensagem NDEF com o registro do aplicativo e vários aplicativos contêm atividades que processam a intent especificada, o sistema sempre entrega a mensagem para a atividade no seu aplicativo, com base no registro correspondente. Se o dispositivo de destino não tiver o app instalado, o sistema vai usar o registro do app Android para iniciar o Google Play e levar o usuário ao app para instalá-lo.

Se o aplicativo não usar APIs NFC para enviar mensagens NDEF push, o Android fornecerá um comportamento padrão: quando seu aplicativo estiver em primeiro plano em um dispositivo e o Android Beam for invocado com outro dispositivo Android, o outro dispositivo receberá uma mensagem NDEF com um registro de aplicativo Android que identifique seu aplicativo. Se o dispositivo receptor tiver o aplicativo instalado, o sistema o iniciará. Caso contrário, o Google Play será aberto e levará o usuário ao seu aplicativo para instalá-lo.

Leia mais sobre o Android Beam e outros recursos de NFC no guia do desenvolvedor Noções básicas de NFC. Para ver alguns exemplos de código usando o Android Beam, consulte a Demonstração do Android Beam.

Wi-Fi P2P

O Android agora oferece suporte a conexões Wi-Fi ponto a ponto (P2P) entre dispositivos Android e outros tipos de dispositivos (em conformidade com o programa de certificação Wi-Fi DirectTM da Wi-Fi Alliance) sem um ponto de acesso ou conexão de Internet. O framework do Android oferece um conjunto de APIs de Wi-Fi P2P que permitem descobrir e se conectar a outros dispositivos quando cada um deles oferecer suporte ao Wi-Fi P2P e, em seguida, se comunicar por uma conexão rápida por distâncias muito maiores do que uma conexão Bluetooth.

Um novo pacote, android.net.wifi.p2p, contém todas as APIs para realizar conexões ponto a ponto com Wi-Fi. A classe principal com que você precisa trabalhar é WifiP2pManager, que pode ser adquirida chamando getSystemService(WIFI_P2P_SERVICE). O WifiP2pManager inclui APIs que permitem:

  • Inicialize seu aplicativo para conexões P2P chamando initialize()
  • Descobrir dispositivos por perto ligando para discoverPeers()
  • Inicie uma conexão P2P chamando connect()
  • E mais

Várias outras interfaces e classes também são necessárias, como:

  • A interface WifiP2pManager.ActionListener permite que você receba callbacks quando uma operação, como a descoberta de pares ou a conexão com eles, for bem-sucedida ou falhar.
  • A interface WifiP2pManager.PeerListListener permite que você receba informações sobre pares descobertos. O callback fornece um WifiP2pDeviceList, de onde é possível extrair um objeto WifiP2pDevice para cada dispositivo dentro do alcance e receber informações como o nome, o endereço e o tipo de dispositivo, as configurações de WPS com suporte e muito mais.
  • A interface WifiP2pManager.GroupInfoListener permite que você receba informações sobre um grupo P2P. O callback fornece um objeto WifiP2pGroup, que fornece informações do grupo, como proprietário, nome da rede e senha longa.
  • A interface WifiP2pManager.ConnectionInfoListener permite que você receba informações sobre a conexão atual. O callback fornece um objeto WifiP2pInfo, que contém informações, por exemplo, se um grupo foi formado e quem é o proprietário dele.

Para usar as APIs de Wi-Fi P2P, seu aplicativo precisa solicitar as seguintes permissões de usuário:

O sistema Android também transmite várias ações diferentes durante certos eventos de Wi-Fi P2P:

Consulte a documentação do WifiP2pManager para mais informações. Veja também o aplicativo de exemplo demonstração de Wi-Fi P2P.

Dispositivos de saúde com Bluetooth

O Android agora oferece suporte a dispositivos com o Perfil de Saúde Bluetooth, então você pode criar aplicativos que usam o Bluetooth para se comunicar com dispositivos de saúde compatíveis com Bluetooth, como monitores de frequência cardíaca, medidores de sangue, termômetros e balanças.

Assim como nos dispositivos com perfil A2DP e fone de ouvido comuns, é necessário chamar getProfileProxy() com um BluetoothProfile.ServiceListener e o tipo de perfil HEALTH para estabelecer uma conexão com o objeto de proxy de perfil.

Depois de adquirir o proxy do perfil de saúde (o objeto BluetoothHealth), a conexão e a comunicação com dispositivos de saúde pareados envolvem estas novas classes do Bluetooth:

  • BluetoothHealthCallback: é necessário estender essa classe e implementar os métodos de callback para receber atualizações sobre mudanças no estado de registro do aplicativo e no estado do canal Bluetooth.
  • BluetoothHealthAppConfiguration: durante callbacks para o BluetoothHealthCallback, você vai receber uma instância desse objeto, que fornece informações de configuração sobre o dispositivo de integridade Bluetooth disponível, que você precisa usar para executar várias operações, como iniciar e encerrar conexões com as APIs BluetoothHealth.

Para mais informações sobre como usar o perfil de integridade do Bluetooth, consulte a documentação de BluetoothHealth.

Acessibilidade

O Android 4.0 melhora a acessibilidade de usuários com deficiência visual usando o novo modo de exploração por toque e APIs estendidas que permitem fornecer mais informações sobre a visualização de conteúdo ou desenvolver serviços avançados de acessibilidade.

Modo de exploração por toque

Usuários com perda de visão agora podem explorar a tela tocando e arrastando um dedo pela tela para ouvir descrições de voz do conteúdo. Como o modo de exploração por toque funciona como um cursor virtual, ele permite que os leitores de tela identifiquem o texto descritivo da mesma forma que os leitores de tela fazem quando o usuário navega com um botão direcional ou trackball, lendo informações fornecidas por android:contentDescription e setContentDescription() em um evento de "passar o cursor" simulado. Portanto, considere que isso é um lembrete de que você precisa fornecer texto descritivo para as visualizações no aplicativo, especialmente para ImageButton, EditText, ImageView e outros widgets que podem não conter texto descritivo natural.

Acessibilidade para visualizações

Para melhorar as informações disponíveis para os serviços de acessibilidade, como leitores de tela, você pode implementar novos métodos de callback para eventos de acessibilidade nos seus componentes View personalizados.

É importante observar primeiro que o comportamento do método sendAccessibilityEvent() mudou no Android 4.0. Assim como na versão anterior do Android, quando o usuário ativa os serviços de acessibilidade no dispositivo e ocorre um evento de entrada, como um clique ou o cursor, a visualização correspondente é notificada com uma chamada para sendAccessibilityEvent(). Anteriormente, a implementação de sendAccessibilityEvent() inicializaria um AccessibilityEvent e o enviaria para AccessibilityManager. O novo comportamento envolve mais alguns métodos de callback que permitem que a visualização e os pais adicionem mais informações contextuais ao evento:

  1. Quando invocados, os métodos sendAccessibilityEvent() e sendAccessibilityEventUnchecked() são adiados para onInitializeAccessibilityEvent().

    As implementações personalizadas de View podem querer implementar onInitializeAccessibilityEvent() para anexar outras informações de acessibilidade ao AccessibilityEvent, mas também precisam chamar a superimplementação para fornecer informações padrão, como a descrição de conteúdo padrão, o índice de itens e muito mais. No entanto, não adicione conteúdo de texto extra nesse callback, que acontece em seguida.

  2. Depois de inicializado, se o evento for um dos vários tipos que precisam ser preenchidos com informações de texto, a visualização receberá uma chamada para dispatchPopulateAccessibilityEvent(), que adia o callback onPopulateAccessibilityEvent().

    As implementações personalizadas de View geralmente precisam implementar onPopulateAccessibilityEvent() para adicionar mais conteúdo de texto ao AccessibilityEvent se o texto de android:contentDescription estiver ausente ou insuficiente. Para adicionar mais descrição de texto ao AccessibilityEvent, chame getText().add().

  3. Nesse ponto, o View transmite o evento para cima na hierarquia de visualização chamando requestSendAccessibilityEvent() na visualização mãe. Cada visualização mãe tem a chance de aumentar as informações de acessibilidade adicionando um AccessibilityRecord até chegar à visualização raiz, que envia o evento ao AccessibilityManager com sendAccessibilityEvent().

Além dos novos métodos acima, que são úteis ao estender a classe View, você também pode interceptar esses callbacks de evento em qualquer View estendendo AccessibilityDelegate e definindo-o na visualização com setAccessibilityDelegate(). Quando você faz isso, cada método de acessibilidade na visualização adia a chamada para o método correspondente no delegado. Por exemplo, quando a visualização recebe uma chamada para onPopulateAccessibilityEvent(), ela é transmitida para o mesmo método no View.AccessibilityDelegate. Todos os métodos não processados pelo delegado são retornados diretamente à visualização para o comportamento padrão. Isso permite que você substitua apenas os métodos necessários para qualquer visualização sem estender a classe View.

Se você quiser manter a compatibilidade com versões do Android anteriores à 4.0 e também oferecer suporte às novas APIs de acessibilidade, poderá fazer isso com a versão mais recente da Biblioteca de Suporte v4 (no Pacote de compatibilidade, r4) usando um conjunto de classes de utilitários que oferecem as novas APIs de acessibilidade em um design compatível com versões anteriores.

Serviços de acessibilidade

Se você estiver desenvolvendo um serviço de acessibilidade, as informações sobre vários eventos de acessibilidade foram significativamente expandidas para permitir um feedback mais avançado para os usuários. Em particular, os eventos são gerados com base na composição da visualização, fornecendo melhores informações de contexto e permitindo que os serviços de acessibilidade passem por hierarquias de visualização para receber mais informações e lidar com casos especiais.

Se você estiver desenvolvendo um serviço de acessibilidade, como um leitor de tela, poderá acessar mais informações de conteúdo e percorrer hierarquias de visualização com o seguinte procedimento:

  1. Ao receber um AccessibilityEvent de um aplicativo, chame AccessibilityEvent.getRecord() para recuperar um AccessibilityRecord específico (pode haver vários registros anexados ao evento).
  2. Usando AccessibilityEvent ou um AccessibilityRecord individual, você pode chamar getSource() para extrair um objeto AccessibilityNodeInfo.

    Um AccessibilityNodeInfo representa um único nó do conteúdo da janela em um formato que permite consultar informações de acessibilidade sobre esse nó. O objeto AccessibilityNodeInfo retornado de AccessibilityEvent descreve a fonte do evento, enquanto a origem de um AccessibilityRecord descreve o antecessor da fonte de eventos.

  3. Com o AccessibilityNodeInfo, é possível consultar informações sobre ele, chamar getParent() ou getChild() para percorrer a hierarquia de visualização e até mesmo adicionar visualizações filhas ao nó.

Para que o aplicativo se publique no sistema como um serviço de acessibilidade, ele precisa declarar um arquivo de configuração XML correspondente a AccessibilityServiceInfo. Para mais informações sobre como criar um serviço de acessibilidade, consulte AccessibilityService e SERVICE_META_DATA para saber mais sobre a configuração XML.

Outras APIs de acessibilidade

Se você tiver interesse no estado de acessibilidade do dispositivo, o AccessibilityManager tem algumas novas APIs, como:

Serviços de corretor ortográfico

Um novo framework de corretor ortográfico permite que os apps criem verificadores ortográficos de maneira semelhante ao framework do método de entrada (para IMEs). Para criar um novo corretor ortográfico, é necessário implementar um serviço que estenda SpellCheckerService e estender a classe SpellCheckerService.Session para fornecer sugestões de ortografia com base no texto fornecido pelos métodos de callback da interface. Nos métodos de callback SpellCheckerService.Session, retorne as sugestões de ortografia como objetos SuggestionsInfo.

Os aplicativos com um serviço de corretor ortográfico precisam declarar a permissão BIND_TEXT_SERVICE conforme exigido pelo serviço. O serviço também precisa declarar um filtro de intent com <action android:name="android.service.textservice.SpellCheckerService" /> como a ação da intent e incluir um elemento <meta-data> que declare informações de configuração do corretor corretográfico.

Consulte o app de exemplo Ortografia de serviço e o exemplo de app de cliente de verificação de ortografia para ver o código de exemplo.

Mecanismos de conversão de texto em voz

As APIs de conversão de texto em voz (TTS) do Android foram significativamente estendidas para permitir que os aplicativos implementem com mais facilidade mecanismos de TTS personalizados, enquanto os aplicativos que querem usar um mecanismo de TTS têm algumas novas APIs para selecionar um mecanismo.

Como usar mecanismos de conversão de texto em voz

Nas versões anteriores do Android, era possível usar a classe TextToSpeech para realizar operações de conversão de texto em voz (TTS, na sigla em inglês) usando o mecanismo TTS fornecido pelo sistema ou definir um mecanismo personalizado usando setEngineByPackageName(). No Android 4.0, o método setEngineByPackageName() foi descontinuado, e você pode especificar o mecanismo a ser usado com um novo construtor TextToSpeech que aceita o nome do pacote de um mecanismo TTS.

Também é possível consultar os mecanismos de TTS disponíveis usando o getEngines(). Esse método retorna uma lista de objetos TextToSpeech.EngineInfo, que incluem metadados como o ícone, o rótulo e o nome do pacote do mecanismo.

Como criar mecanismos de conversão de texto em voz

Anteriormente, os mecanismos personalizados exigiam que o mecanismo fosse criado usando um arquivo principal de cabeçalho nativo não documentado. No Android 4.0, há um conjunto completo de APIs de framework para a criação de mecanismos TTS.

A configuração básica requer uma implementação de TextToSpeechService que responda à intent INTENT_ACTION_TTS_SERVICE. O trabalho principal para um mecanismo de TTS acontece durante o callback onSynthesizeText() em um serviço que estende TextToSpeechService. O sistema entrega dois objetos a esse método:

  • SynthesisRequest: contém vários dados, incluindo o texto a sintetizar, a localidade, a velocidade da fala e o tom de voz.
  • SynthesisCallback: é a interface usada pelo mecanismo de TTS para entregar os dados de fala resultantes como streaming de áudio. Primeiro, o mecanismo precisa chamar start() para indicar que está pronto para entregar o áudio e, em seguida, chamar audioAvailable(), transmitindo a ele os dados de áudio em um buffer de bytes. Quando o mecanismo tiver passado todo o áudio pelo buffer, chame done().

Agora que o framework é compatível com uma API verdadeira para a criação de mecanismos TTS, o suporte para a implementação de código nativo foi removido. Procure uma postagem de blog sobre uma camada de compatibilidade que pode ser usada para converter seus mecanismos de TTS antigos para o novo framework.

Para ver um exemplo de mecanismo de TTS usando as novas APIs, consulte o app de exemplo Mecanismo de texto em voz.

Uso da rede

O Android 4.0 oferece aos usuários uma visibilidade precisa da quantidade de dados de rede que os aplicativos estão usando. O app Configurações oferece controles que permitem aos usuários gerenciar limites definidos para o uso de dados de rede e até mesmo desativar o uso de dados em segundo plano para apps individuais. Para evitar que os usuários desativem o acesso do app aos dados em segundo plano, desenvolva estratégias para usar a conexão de dados de forma eficiente e ajustar o uso dependendo do tipo de conexão disponível.

Caso seu aplicativo realize muitas transações de rede, forneça configurações que permitam que os usuários controlem os hábitos de dados do app. Por exemplo, com que frequência o app sincroniza dados, se é necessário fazer uploads/downloads somente quando estiver usando Wi-Fi, usar ou não dados em roaming etc. Com esses controles disponíveis, é muito menos provável que os usuários desativem o acesso do app aos dados quando se aproximarem do limite, já que é possível controlar a quantidade de dados com precisão. Se você fornecer uma atividade de preferências com essas configurações, inclua na declaração do manifesto um filtro de intent para a ação ACTION_MANAGE_NETWORK_USAGE. Por exemplo:

<activity android:name="DataPreferences" android:label="@string/title_preferences">
    <intent-filter>
       <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
       <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

Esse filtro de intent indica ao sistema que essa é a atividade que controla o uso de dados do seu aplicativo. Assim, quando o usuário inspeciona a quantidade de dados que seu app está usando no app Configurações, fica disponível um botão “Ver configurações do aplicativo” que inicia sua atividade de preferência para que o usuário possa refinar a quantidade de dados usados pelo app.

Esteja ciente também de que getBackgroundDataSetting() agora foi descontinuado e sempre retorna verdadeiro. Use getActiveNetworkInfo(). Antes de tentar qualquer transação de rede, sempre chame getActiveNetworkInfo() para receber o NetworkInfo que representa a rede atual e consulte isConnected() para verificar se o dispositivo tem uma conexão. Depois, você pode verificar outras propriedades da conexão, como se o dispositivo está em roaming ou conectado ao Wi-Fi.

Empresarial

O Android 4.0 expande as funcionalidades de aplicativos corporativos com os recursos a seguir.

Serviços de VPN

O novo VpnService permite que os aplicativos criem a própria VPN (rede privada virtual), executada como uma Service. Um serviço de VPN cria uma interface para uma rede virtual com as próprias regras de endereço e roteamento e executa todas as leituras e gravações com um descritor de arquivos.

Para criar um serviço de VPN, use VpnService.Builder, que permite especificar o endereço de rede, o servidor DNS, a rota da rede e muito mais. Quando concluído, você pode estabelecer a interface chamando establish(), que retorna um ParcelFileDescriptor.

Como um serviço de VPN pode interceptar pacotes, há implicações de segurança. Assim, se você implementar VpnService, o serviço vai precisar exigir o BIND_VPN_SERVICE para garantir que somente o sistema possa se vincular a ele (somente o sistema recebe essa permissão, e os apps não podem solicitá-la). Para usar o serviço de VPN, os usuários precisam ativá-lo manualmente nas configurações do sistema.

Políticas do dispositivo

Os aplicativos que gerenciam as restrições do dispositivo agora podem desativar a câmera usando a setCameraDisabled() e a propriedade USES_POLICY_DISABLE_CAMERA, aplicada com um elemento <disable-camera /> no arquivo de configuração da política.

Gerenciamento de certificados

A nova classe KeyChain fornece APIs que permitem importar e acessar certificados no armazenamento de chaves do sistema. Os certificados simplificam a instalação de certificados do cliente (para validar a identidade do usuário) e de autoridade de certificação (para verificar a identidade do servidor). Aplicativos como navegadores da Web ou clientes de e-mail podem acessar os certificados instalados para autenticar usuários nos servidores. Consulte a documentação do KeyChain para mais informações.

Sensores do dispositivo

Dois novos tipos de sensor foram adicionados ao Android 4.0:

Se um dispositivo tiver sensores TYPE_AMBIENT_TEMPERATURE e TYPE_RELATIVE_HUMIDITY, eles poderão ser usados para calcular o ponto de orvalho e a umidade absoluta.

O sensor de temperatura anterior, TYPE_TEMPERATURE, foi descontinuado. Em vez disso, use o sensor TYPE_AMBIENT_TEMPERATURE.

Além disso, os três sensores sintéticos do Android foram muito aprimorados, então agora têm menor latência e saída mais suave. Esses sensores incluem o sensor de gravidade (TYPE_GRAVITY), o sensor vetorial de rotação (TYPE_ROTATION_VECTOR) e o sensor de aceleração linear (TYPE_LINEAR_ACCELERATION). Os sensores aprimorados dependem do sensor do giroscópio para melhorar a saída. Eles aparecem apenas em dispositivos que têm um giroscópio.

Barra de ações

O ActionBar foi atualizado para oferecer suporte a vários novos comportamentos. O mais importante é que o sistema gerencia normalmente o tamanho e a configuração da barra de ações ao ser executada em telas menores para fornecer uma experiência do usuário ideal em todos os tamanhos de tela. Por exemplo, quando a tela é estreita (como quando um celular está na orientação retrato), as guias de navegação da barra de ações aparecem em uma "barra empilhada", que aparece logo abaixo da barra de ações principal. Você também pode ativar uma "barra de ações divididas", que coloca todas as ações necessárias em uma barra separada na parte de baixo da tela quando ela é estreita.

Dividir barra de ações

Se a barra de ações incluir vários itens de ação, nem todos vão caber na barra de ações em uma tela estreita, então o sistema vai colocar mais deles no menu flutuante. No entanto, o Android 4.0 permite ativar a "barra de ações divididas" para que mais ações possam aparecer em uma barra separada na parte de baixo da tela. Para ativar a barra de ações divididas, adicione android:uiOptions com "splitActionBarWhenNarrow" à sua tag <application> ou às tags <activity> individuais no arquivo de manifesto. Quando ativada, o sistema adiciona uma barra extra na parte de baixo da tela para todos os itens de ação quando ela está estreita. Nenhuma ação é mostrada na barra de ações principal.

Se você quiser usar as guias de navegação fornecidas pelas APIs ActionBar.Tab, mas não precisar da barra de ação principal na parte de cima (ou seja, quer que apenas as guias apareçam na parte de cima), ative a barra de ações divididas conforme descrito acima e chame setDisplayShowHomeEnabled(false) para desativar o ícone do aplicativo na barra de ações. Sem nada restante na barra de ações principal, ela desaparece. Tudo o que resta são as guias de navegação na parte de cima e os itens de ação na parte de baixo da tela.

Estilos da barra de ações

Caso queira aplicar um estilo personalizado à barra de ações, use as novas propriedades de estilo backgroundStacked e backgroundSplit para aplicar um drawable ou uma cor em segundo plano à barra empilhada e à barra dividida, respectivamente. Também é possível definir esses estilos durante a execução com setStackedBackgroundDrawable() e setSplitBackgroundDrawable().

Provedor de ações

A nova classe ActionProvider permite que você crie um gerenciador especializado para itens de ação. Um provedor de ações pode definir uma visualização de ação, um comportamento padrão e um submenu para cada item de ação a que ele está associado. Para criar um item de ação que tenha comportamentos dinâmicos (como uma visualização de ação variável, uma ação padrão ou um submenu), estender ActionProvider é uma boa solução para criar um componente reutilizável, em vez de processar as várias transformações de item de ação no fragmento ou na atividade.

Por exemplo, ShareActionProvider é uma extensão de ActionProvider que facilita uma ação de "compartilhar" na barra de ações. Em vez de usar um item de ação tradicional que invoca a intent ACTION_SEND, você pode usar esse provedor para apresentar uma visualização de ação com uma lista suspensa de aplicativos que processam a intent ACTION_SEND. Quando o usuário seleciona um aplicativo a ser usado para a ação, o ShareActionProvider lembra essa seleção e a fornece na visualização da ação para um acesso mais rápido ao compartilhamento com o app.

Para declarar um provedor de ações para um item de ação, inclua o atributo android:actionProviderClass no elemento <item> do menu de opções da atividade, com o nome da classe do provedor de ação como o valor. Por exemplo:

<item android:id="@+id/menu_share"
      android:title="Share"
      android:showAsAction="ifRoom"
      android:actionProviderClass="android.widget.ShareActionProvider" />

No método de callback onCreateOptionsMenu() da atividade, extraia uma instância do provedor de ações no item de menu e defina a intent:

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.options, menu)
    val shareActionProvider = menu.findItem(R.id.menu_share)?.actionProvider as? ShareActionProvider
    // Set the share intent of the share action provider.
    shareActionProvider?.setShareIntent(createShareIntent())
    ...
    return super.onCreateOptionsMenu(menu)
}

Java

public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.options, menu);
    ShareActionProvider shareActionProvider =
          (ShareActionProvider) menu.findItem(R.id.menu_share).getActionProvider();
    // Set the share intent of the share action provider.
    shareActionProvider.setShareIntent(createShareIntent());
    ...
    return super.onCreateOptionsMenu(menu);
}

Para ver um exemplo que usa o ShareActionProvider, consulte ActionBarShareActionProviderActivity no ApiDemos.

Visualizações de ações recolhíveis

Os itens de ação que fornecem uma visualização de ação agora podem alternar entre o estado de visualização e o estado tradicional do item de ação. Antes, apenas a SearchView oferecia suporte para o recolhimento quando usado como uma visualização de ação, mas agora é possível adicionar uma visualização de ação para qualquer item de ação e alternar entre o estado expandido (a visualização de ação está visível) e o estado recolhido (o item de ação está visível).

Para declarar que um item de ação que contém uma visualização de ação pode ser recolhido, inclua a sinalização “collapseActionView" no atributo android:showAsAction do elemento <item> no arquivo XML do menu.

Para receber callbacks quando uma visualização de ação alternar entre expandida e recolhida, registre uma instância de MenuItem.OnActionExpandListener com o respectivo MenuItem chamando setOnActionExpandListener(). Normalmente, isso precisa ser feito durante o callback onCreateOptionsMenu().

Para controlar a visualização de ações recolhíveis, chame collapseActionView() e expandActionView() no respectivo MenuItem.

Ao criar uma visualização de ação personalizada, você também pode implementar a nova interface CollapsibleActionView para receber callbacks quando a visualização for expandida e recolhida.

Outras APIs para a barra de ações

  • setHomeButtonEnabled() permite especificar se o ícone/logotipo se comporta como um botão para navegar para a página inicial ou para "para cima" (transmita "verdadeiro" para fazer com que ele se comporte como um botão).
  • setIcon() e setLogo() permitem que você defina o ícone ou o logotipo da barra de ações no momento da execução.
  • Fragment.setMenuVisibility() permite ativar ou desativar a visibilidade dos itens do menu de opções declarados pelo fragmento. Isso é útil se o fragmento foi adicionado à atividade, mas não está visível, portanto, os itens de menu precisam ficar ocultos.
  • FragmentManager.invalidateOptionsMenu() permite invalidar o menu de opções de atividade durante vários estados do ciclo de vida do fragmento, em que o uso do método equivalente de Activity pode não estar disponível.

Interface do usuário e visualizações

O Android 4.0 apresenta uma variedade de novas visualizações e outros componentes de interface do usuário.

GridLayout

GridLayout é um novo grupo de visualizações que coloca visualizações filhas em uma grade retangular. Ao contrário de TableLayout, GridLayout depende de uma hierarquia lisa e não usa visualizações intermediárias, como linhas da tabela, para fornecer estrutura. Em vez disso, os filhos especificam quais linhas e colunas devem ocupar (as células podem abranger várias linhas e/ou colunas) e, por padrão, são dispostas em sequência nas linhas e colunas da grade. A orientação GridLayout determina se os filhos sequenciais são, por padrão, dispostos horizontalmente ou verticalmente. O espaço entre filhos pode ser especificado usando instâncias da nova visualização Space ou definindo os parâmetros de margem relevantes nos filhos.

Consulte ApiDemos (link em inglês) para ver exemplos que usam GridLayout.

TextureView

TextureView é uma nova visualização que permite mostrar um stream de conteúdo, como um vídeo ou uma cena OpenGL. Embora seja semelhante à SurfaceView, a TextureView é única porque se comporta como uma visualização normal, em vez de criar uma janela separada. Ela pode ser tratada como qualquer outro objeto View. Por exemplo, é possível aplicar transformações, animá-las usando ViewPropertyAnimator ou ajustar a opacidade com setAlpha().

TextureView só funciona em uma janela acelerada por hardware.

Para saber mais, consulte a documentação do TextureView.

Alternar widget

O novo widget Switch é um botão de alternância de dois estados que os usuários podem arrastar para um lado ou para outro (ou simplesmente tocar) para alternar uma opção entre dois estados.

Você pode usar os atributos android:textOn e android:textOff para especificar o texto que aparece na chave na configuração de ativação e desativação. O atributo android:text também permite colocar um rótulo ao lado da chave.

Para ver um exemplo que usa interruptores, consulte o arquivo de layout switches.xml e a respectiva atividade de chaves .

O Android 3.0 introduziu PopupMenu para criar menus contextuais curtos que são exibidos em um ponto de fixação especificado, geralmente no ponto do item selecionado. O Android 4.0 estende a PopupMenu com alguns recursos úteis:

  • Agora é possível inflar facilmente o conteúdo de um menu pop-up de um recurso de menu XML com inflate(), transmitindo o ID do recurso de menu.
  • Agora você também pode criar um PopupMenu.OnDismissListener que recebe um callback quando o menu é dispensado

Preferências

Uma nova classe abstrata TwoStatePreference serve como base para preferências que fornecem uma opção de seleção de dois estados. O novo SwitchPreference é uma extensão do TwoStatePreference que fornece um widget Switch na visualização de preferências para permitir que os usuários ativem ou desativem uma configuração sem a necessidade de abrir outra tela de preferência ou caixa de diálogo. Por exemplo, o app Configurações usa um SwitchPreference para as configurações de Wi-Fi e Bluetooth.

Temas do sistema

O tema padrão para todos os aplicativos destinados ao Android 4.0 (definindo targetSdkVersion ou minSdkVersion como “14" ou mais recente) agora é o tema "padrão do dispositivo": Theme.DeviceDefault. Pode ser o tema escuro do Holo ou um tema escuro diferente definido pelo dispositivo específico.

A família de temas Theme.Holo garante que não vai mudar de um dispositivo para outro quando a mesma versão do Android for executada. Se você aplicar explicitamente qualquer um dos temas Theme.Holo às suas atividades, terá garantia de que esses temas não mudarão de personagem em dispositivos diferentes dentro da mesma versão da plataforma.

Se você quiser que seu app se misture com o tema geral do dispositivo (por exemplo, quando diferentes OEMs fornecem temas padrão distintos para o sistema), aplique explicitamente temas da família Theme.DeviceDefault.

Botão do menu "Opções"

A partir do Android 4.0, você notará que os celulares não exigem mais um botão físico de menu. No entanto, não é necessário se preocupar com isso se o app existente fornecer um menu de opções e esperar que haja um botão de menu. Para garantir que os apps existentes continuem funcionando conforme o esperado, o sistema fornece um botão de menu na tela para apps projetados para versões mais antigas do Android.

Para a melhor experiência do usuário, apps novos e atualizados precisam usar ActionBar para fornecer acesso a itens de menu e definir targetSdkVersion como "14" para aproveitar os comportamentos padrão mais recentes do framework.

Controles de visibilidade da IU do sistema

Desde os primeiros dias do Android, o sistema gerenciava um componente de interface conhecido como barra de status, que fica na parte de cima dos smartphones para fornecer informações como o sinal da operadora, o horário, as notificações e assim por diante. O Android 3.0 adicionou a barra do sistema para tablets, que fica na parte de baixo da tela para fornecer controles de navegação do sistema (Início, Voltar e assim por diante) e também uma interface para elementos tradicionalmente fornecidos pela barra de status. No Android 4.0, o sistema oferece um novo tipo de IU do sistema, chamado barra de navegação. Você pode considerar a barra de navegação como uma versão reajustada da barra do sistema projetada para celulares. Ela fornece controles de navegação para dispositivos que não têm contrapartes de hardware para navegar no sistema, mas não inclui a interface de notificação e os controles de configuração da barra do sistema. Dessa forma, um dispositivo que fornece a barra de navegação também tem a barra de status na parte de cima.

Até hoje, é possível ocultar a barra de status em celulares usando a sinalização FLAG_FULLSCREEN. No Android 4.0, as APIs que controlam a visibilidade da barra do sistema foram atualizadas para refletir melhor o comportamento dela e da barra de navegação:

  • A sinalização SYSTEM_UI_FLAG_LOW_PROFILE substitui a sinalização STATUS_BAR_HIDDEN. Quando definida, essa flag ativa o modo de "baixo perfil" para a barra de sistema ou de navegação. Os botões de navegação esmaecem e outros elementos na barra do sistema também ficam ocultos. Ativar essa opção é útil para criar jogos mais imersivos sem distração para os botões de navegação do sistema.
  • A sinalização SYSTEM_UI_FLAG_VISIBLE substitui a sinalização STATUS_BAR_VISIBLE para solicitar que a barra do sistema ou de navegação seja visível.
  • O SYSTEM_UI_FLAG_HIDE_NAVIGATION é uma nova flag que solicita que a barra de navegação fique completamente oculta. Isso funciona apenas para a barra de navegação usada por alguns celulares (essa opção não oculta a barra do sistema em tablets). A barra de navegação retorna à visualização assim que o sistema recebe entrada do usuário. Sendo assim, esse modo é útil principalmente para reprodução de vídeo ou outros casos em que a tela inteira é necessária, mas a entrada do usuário não é necessária.

Você pode definir cada uma dessas sinalizações para a barra do sistema e de navegação chamando setSystemUiVisibility() em qualquer visualização na atividade. O gerenciador de janelas combina (OU) todas as flags de todas as visualizações na janela e as aplica à IU do sistema, desde que a janela tenha foco de entrada. Quando a janela perde o foco de entrada (o usuário sai do app ou uma caixa de diálogo é exibida), as flags deixam de ter efeito. Da mesma forma, se você remover essas visualizações da hierarquia de visualização, as sinalizações delas não serão mais aplicadas.

Para sincronizar outros eventos na sua atividade com mudanças de visibilidade na IU do sistema (por exemplo, ocultar a barra de ações ou outros controles de IU quando a IU do sistema estiver oculta), registre um View.OnSystemUiVisibilityChangeListener para ser notificado quando a visibilidade da barra do sistema ou da barra de navegação mudar.

Consulte a classe OverscanActivity para ver uma demonstração de diferentes opções de IU do sistema.

Estrutura de entrada

O Android 4.0 adiciona suporte a eventos de passagem do cursor e novos eventos de stylus e botão do mouse.

Eventos de passagem de cursor

A classe View agora oferece suporte a eventos "passar o cursor" para permitir interações mais avançadas com o uso de dispositivos ponteiro, como um mouse ou outros dispositivos que direcionam um cursor na tela.

Para receber eventos de passar o cursor em uma visualização, implemente o View.OnHoverListener e registre-o com setOnHoverListener(). Quando ocorre um evento de passar o cursor na visualização, seu listener recebe uma chamada para onHover(), fornecendo o View que recebeu o evento e um MotionEvent que descreve o tipo de evento de passar o cursor que ocorreu. O evento de passar o cursor pode ser um dos seguintes:

Seu View.OnHoverListener vai retornar "true" de onHover() se processar o evento de passar o cursor. Se o listener retornar "false", o evento de passar o cursor será enviado para a visualização pai como de costume.

Caso seu aplicativo use botões ou outros widgets que mudam a aparência com base no estado atual, você pode usar o atributo android:state_hovered em um drawable de lista de estados para fornecer um drawable de segundo plano diferente quando um cursor passar sobre a visualização.

Para uma demonstração dos novos eventos de passar o cursor, consulte a classe Hover no ApiDemos.

Eventos do botão do mouse e da stylus

O Android agora oferece APIs para receber entradas de um dispositivo de entrada com stylus, como um periférico de tablet digital ou uma tela touchscreen com stylus.

A entrada com a stylus funciona de maneira semelhante à entrada por toque ou mouse. Quando a stylus está em contato com o digitalizador, os aplicativos recebem eventos de toque da mesma forma que receberiam quando um dedo é usado para tocar na tela. Quando a stylus está passando o cursor sobre o digitalizador, os aplicativos recebem eventos de passagem do cursor da mesma forma que receberiam se um ponteiro do mouse estivesse sendo movido pela tela quando nenhum botão for pressionado.

O app pode distinguir entre entradas de dedo, mouse, stylus e borracha, consultando o "tipo de ferramenta" associado a cada ponteiro em um MotionEvent usando getToolType(). Os tipos de ferramentas definidos atualmente são: TOOL_TYPE_UNKNOWN, TOOL_TYPE_FINGER, TOOL_TYPE_MOUSE, TOOL_TYPE_STYLUS e TOOL_TYPE_ERASER. Ao consultar o tipo de ferramenta, seu aplicativo pode optar por processar a entrada da stylus de maneiras diferentes da entrada com o dedo ou o mouse.

O aplicativo também pode consultar quais botões do mouse ou da stylus são pressionados ao consultar o "estado do botão" de um MotionEvent usando getButtonState(). Os estados do botão definidos atualmente são: BUTTON_PRIMARY, BUTTON_SECONDARY, BUTTON_TERTIARY, BUTTON_BACK e BUTTON_FORWARD. Por conveniência, os botões "Voltar" e "Avançar" do mouse são mapeados automaticamente para as teclas KEYCODE_BACK e KEYCODE_FORWARD. Seu aplicativo pode processar essas teclas para oferecer suporte à navegação para voltar e avançar, baseada em botões do mouse.

Além de medir com precisão a posição e a pressão de um contato, alguns dispositivos de entrada da stylus também informam a distância entre a ponta da stylus e o digitalizador, o ângulo de inclinação e o ângulo de orientação da stylus. Seu aplicativo pode consultar essas informações usando getAxisValue() com os códigos de eixo AXIS_DISTANCE, AXIS_TILT e AXIS_ORIENTATION.

Para uma demonstração de tipos de ferramenta, estados de botão e novos códigos de eixo, consulte a classe TouchPaint no ApiDemos.

Propriedades

A nova classe Property oferece uma maneira rápida, eficiente e fácil de especificar uma propriedade em qualquer objeto que permite aos autores de chamada definir/receber valores de forma genérica em objetos de destino. Ela também permite a funcionalidade de transmitir referências de campo/método e permite que o código defina/receba valores da propriedade sem conhecer os detalhes dos campos/métodos.

Por exemplo, se você quiser definir o valor do campo bar no objeto foo, faça o seguinte:

Kotlin

foo.bar = value

Java

foo.bar = value;

Se você quiser chamar o setter para um campo particular subjacente bar, faça o seguinte:

Kotlin

foo.setBar(value)

Java

foo.setBar(value);

No entanto, se você quiser transmitir a instância foo e ter outro código para definir o valor bar, não há como fazer isso antes do Android 4.0.

Usando a classe Property, você pode declarar um objeto Property BAR na classe Foo para definir o campo na instância foo da classe Foo desta forma:

Kotlin

BAR.set(foo, value)

Java

BAR.set(foo, value);

A classe View agora aproveita a classe Property para permitir que você defina vários campos, como propriedades de transformação que foram adicionadas no Android 3.0 (ROTATION, ROTATION_X, TRANSLATION_X etc.).

A classe ObjectAnimator também usa a classe Property, para que você possa criar um ObjectAnimator com um Property, que é mais rápido, eficiente e com mais segurança de tipo do que a abordagem baseada em strings.

Aceleração de hardware

A partir do Android 4.0, a aceleração de hardware para todas as janelas será ativada por padrão se o aplicativo tiver definido targetSdkVersion ou minSdkVersion como “14" ou mais recente. A aceleração de hardware geralmente resulta em animações mais suaves, rolagem mais suave e melhor desempenho e resposta gerais à interação do usuário.

Se necessário, você pode desativar manualmente a aceleração de hardware com o atributo hardwareAccelerated para elementos <activity> individuais ou para o elemento <application>. Como alternativa, você pode desativar a aceleração de hardware para visualizações individuais chamando setLayerType(LAYER_TYPE_SOFTWARE).

Para saber mais sobre aceleração de hardware, incluindo uma lista de operações de desenho sem suporte, consulte o documento Aceleração de hardware.

Mudanças na JNI

Nas versões anteriores do Android, as referências locais de JNI não eram identificadores indiretos, mas o Android usava ponteiros diretos. Isso não era um problema, desde que o coletor de lixo não movia objetos, mas parecia funcionar porque era possível escrever um código com bugs. No Android 4.0, o sistema agora usa referências indiretas para detectar esses bugs.

Os detalhes das referências locais de JNI são descritos em "Referências locais e globais" nas Dicas de JNI. No Android 4.0, o CheckJNI foi aprimorado para detectar esses erros. Assista o Blog de desenvolvedores Android (link em inglês) para ver uma postagem sobre erros comuns com referências de JNI e como você pode corrigi-los.

Essa mudança na implementação de JNI afeta apenas apps destinados ao Android 4.0 definindo targetSdkVersion ou minSdkVersion como “14" ou mais recente. Se você tiver definido esses atributos com qualquer valor menor, as referências locais de JNI vão se comportar da mesma forma que nas versões anteriores.

WebKit

  • WebKit atualizado para a versão 534.30
  • Suporte a fontes indianas (Devanagari, bengali e tâmil, incluindo o suporte a caracteres complexos necessário para combinar glifos) no WebView e no navegador integrado.
  • Suporte a fontes etíopes, georgianas e armênias no WebView e no navegador integrado.
  • O suporte ao WebDriver facilita o teste de apps que usam WebView.

Navegador Android

O aplicativo Navegador adiciona os seguintes recursos para oferecer suporte a aplicativos da web:

Permissões

Confira a seguir as novas permissões:

Recursos do dispositivo

Estes são os novos recursos do dispositivo:

Para ter uma visão detalhada de todas as mudanças da API no Android 4.0 (nível 14 da API), consulte o Relatório de diferenças da API.

APIs anteriores

Além de tudo o que foi mencionado acima, o Android 4.0 oferece suporte natural a todas as APIs das versões anteriores. Como a plataforma Android 3.x está disponível apenas para dispositivos de tela grande, se você tem desenvolvido principalmente para celulares, talvez não conheça todas as APIs adicionadas ao Android nestas versões recentes.

Confira algumas das APIs mais importantes que você pode ter perdido e que agora também estão disponíveis em smartphones:

Android 3.0
  • Fragment: um componente de framework que permite separar elementos distintos de uma atividade em módulos independentes que definem a própria IU e o ciclo de vida. Consulte o guia para desenvolvedores sobre fragmentos.
  • ActionBar: uma substituição da barra de título tradicional na parte de cima da janela de atividade. Ele inclui o logotipo do aplicativo no canto esquerdo e fornece uma nova interface para itens de menu. Consulte o guia para desenvolvedores sobre a barra de ações.
  • Loader: componente de framework que facilita o carregamento assíncrono de dados em combinação com componentes de IU para carregar dados dinamicamente sem bloquear a linha de execução principal. Consulte o guia do desenvolvedor de Carregadores.
  • Área de transferência do sistema: os aplicativos podem copiar e colar dados (além de textos) para e da área de transferência do sistema. Os dados recortados podem ser texto simples, um URI ou uma intent. Consulte o guia do desenvolvedor sobre Copiar e colar.
  • Arrastar e soltar: um conjunto de APIs integradas ao framework de visualização que facilita as operações de arrastar e soltar. Consulte o guia para desenvolvedores sobre Arrastar e soltar.
  • Um novo framework de animação flexível permite que você anime propriedades arbitrárias de qualquer objeto (visualização, drawable, fragmento, objeto ou qualquer outro item) e defina aspectos de animação, como duração, interpolação, repetição e muito mais. O novo framework torna as animações no Android mais simples do que nunca. Consulte o guia do desenvolvedor sobre Animação de propriedade.
  • Gráficos do RenderScript e Compute Engine: o RenderScript oferece uma API de computação e renderização de gráficos 3D de alto desempenho no nível nativo, que você escreve no C (padrão C99), fornecendo o tipo de desempenho esperado de um ambiente nativo e mantendo a portabilidade em várias CPUs e GPUs. Consulte o guia do desenvolvedor do RenderScript.
  • Gráficos 2D acelerados por hardware: agora você pode ativar o renderizador OpenGL para seu aplicativo definindo {android:hardwareAccelerated="true"} no elemento <application> do elemento de manifesto ou para elementos <activity> individuais. Isso resulta em animações e rolagem mais suaves, além de um melhor desempenho geral e resposta à interação do usuário.

    Observação:se você definir o minSdkVersion ou o targetSdkVersion do seu aplicativo como "14" ou uma versão mais recente, a aceleração de hardware será ativada por padrão.

  • E muito, muito mais. Consulte as notas da Plataforma Android 3.0 para mais informações.
Android 3.1
  • APIs USB: novas APIs avançadas para integrar periféricos conectados a aplicativos Android. As APIs são baseadas em uma pilha USB e em serviços integrados à plataforma, incluindo suporte a interações de host e dispositivo USB. Consulte o guia do desenvolvedor sobre Host e acessórios USB.
  • APIs MTP/PTP: os aplicativos podem interagir diretamente com câmeras conectadas e outros dispositivos PTP para receber notificações quando dispositivos são conectados e removidos, gerenciar arquivos e armazenamento nesses dispositivos e transferir arquivos e metadados para eles. A API MTP implementa o subconjunto PTP (Protocolo de transferência de imagens) da especificação MTP (Protocolo de transferência de mídia). Consulte a documentação do android.mtp.
  • APIs de RTP: o Android expõe uma API à pilha de protocolo de transporte em tempo real (RTP, na sigla em inglês) integrada, que pode ser usada por aplicativos para gerenciar o streaming de dados sob demanda ou interativo. Em especial, apps que oferecem VOIP, "push-to-talk", conferência e streaming de áudio podem usar a API para iniciar sessões e transmitir ou receber fluxos de dados por qualquer rede disponível. Consulte a documentação do android.net.rtp.
  • Compatibilidade com joysticks e outras entradas de movimento genéricas.
  • Consulte as notas da Plataforma Android 3.1 para ver muitas outras APIs novas.
Android 3.2
  • As novas telas oferecem suporte a APIs que oferecem mais controle sobre como os aplicativos são exibidos em diferentes tamanhos de tela. A API amplia o modelo de suporte à tela existente com a capacidade de segmentar com precisão intervalos de tamanho de tela específicos por dimensões, medidas em unidades de pixel independentes de densidade (como 600 dp ou 720 dp de largura), em vez de por tamanhos de tela generalizados (como grande ou extra grande). Isso é importante, por exemplo, para ajudar você a distinguir entre um dispositivo de 5" e um de 7", que tradicionalmente seriam agrupados como telas "grandes". Consulte a postagem do blog New Tools for Managing Screen Sizes.
  • Novas constantes de <uses-feature> para declarar os requisitos de orientação de tela de paisagem ou retrato.
  • A configuração de "tamanho da tela" do dispositivo agora muda durante uma mudança de orientação da tela. Se o app for direcionado ao nível 13 da API ou mais recente, será necessário processar a mudança de configuração "screenSize" se você também quiser processar a mudança de configuração "orientation". Consulte android:configChanges para mais informações.
  • Consulte as notas da Plataforma Android 3.2 para ver outras novas APIs.

Nível de API

A API Android 4.0 recebe um identificador de número inteiro (14), que é armazenado no próprio sistema. Esse identificador, chamado de "nível da API", permite que o sistema determine corretamente se um aplicativo é compatível com o sistema antes de instalá-lo.

Para usar as APIs introduzidas no Android 4.0 no seu aplicativo, você precisa compilá-lo em uma plataforma Android com suporte ao nível 14 da API ou mais recente. Dependendo do que você precisa, talvez seja necessário adicionar um atributo android:minSdkVersion="14" ao elemento <uses-sdk>.

Para mais informações, leia O que é o nível da API?.