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 emMAX_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:
Events.TITLE
: nome do evento.CalendarContract.EXTRA_EVENT_BEGIN_TIME
: horário de início do evento em milissegundos a partir da época.CalendarContract.EXTRA_EVENT_END_TIME
: horário de término do evento em milissegundos a partir da épocaEvents.EVENT_LOCATION
: local do evento.Events.DESCRIPTION
: descrição do eventoIntent.EXTRA_EMAIL
: endereços de e-mail das pessoas a serem convidadas.Events.RRULE
: a regra de recorrência do eventoEvents.ACCESS_LEVEL
: se o evento é particular ou público.Events.AVAILABILITY
: se o período desse evento permite que outros eventos sejam programados ao mesmo tempo.
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:
- Elas precisam estar vinculadas a uma imagem de textura
GL_TEXTURE_2D
. - 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:
- Chame
EffectContext.createWithCurrentGlContext()
no contexto do OpenGL ES 2.0. - Use o
EffectContext
retornado para chamarEffectContext.getFactory()
, que retorna uma instância deEffectFactory
. - Chame
createEffect()
, transmitindo um nome de efeito de @link android.media.effect.EffectFactory}, comoEFFECT_FISHEYE
ouEFFECT_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ãoINTERNET
. Se você usarMediaPlayer
para abrir conteúdo da Internet, adicione a permissãoINTERNET
ao manifesto. Caso contrário, a reprodução de mídia não funcionará a partir do Android 4.0. setSurface()
permite definir umSurface
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, chameisVideoSnapshotSupported()
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()
esetAutoWhiteBalanceLock()
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:
- Defina um único
NdefMessage
para enviar durante a atividade:Chame
setNdefPushMessage()
a qualquer momento para definir a mensagem que você quer enviar. Por exemplo, você pode chamar esse método e transmitir oNdefMessage
durante o métodoonCreate()
da sua atividade. Assim, sempre que o Android Beam for ativado com outro dispositivo enquanto a atividade estiver em primeiro plano, o sistema vai enviar aNdefMessage
para o outro dispositivo. - Defina o
NdefMessage
a ser enviado no momento em que o Android Beam é iniciado:Implemente
NfcAdapter.CreateNdefMessageCallback
, em que a implementação do métodocreateNdefMessage()
retorna oNdefMessage
que você quer enviar. Em seguida, transmita a implementação deNfcAdapter.CreateNdefMessageCallback
parasetNdefPushMessageCallback()
.Nesse caso, quando o Android Beam é ativado com outro dispositivo enquanto sua atividade está em primeiro plano, o sistema chama
createNdefMessage()
para extrair oNdefMessage
que você quer enviar. Isso permite que você defina oNdefMessage
para ser entregue apenas quando o Android Beam for iniciado, caso o conteúdo da mensagem possa variar durante a vida útil da atividade.
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 umWifiP2pDeviceList
, de onde é possível extrair um objetoWifiP2pDevice
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 objetoWifiP2pGroup
, 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 objetoWifiP2pInfo
, 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:
ACCESS_WIFI_STATE
CHANGE_WIFI_STATE
INTERNET
(embora o app não se conecte tecnicamente à Internet, a comunicação com pares Wi-Fi P2P com soquetes Java padrão exige permissão de Internet).
O sistema Android também transmite várias ações diferentes durante certos eventos de Wi-Fi P2P:
WIFI_P2P_CONNECTION_CHANGED_ACTION
: o estado da conexão P2P mudou. Isso carregaEXTRA_WIFI_P2P_INFO
com um objetoWifiP2pInfo
eEXTRA_NETWORK_INFO
com um objetoNetworkInfo
.WIFI_P2P_STATE_CHANGED_ACTION
: o estado P2P mudou entre ativado e desativado. Ela carregaEXTRA_WIFI_STATE
comWIFI_P2P_STATE_DISABLED
ouWIFI_P2P_STATE_ENABLED
.WIFI_P2P_PEERS_CHANGED_ACTION
: a lista de dispositivos de peering mudou.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION
: os detalhes deste dispositivo mudaram.
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 oBluetoothHealthCallback
, 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 APIsBluetoothHealth
.
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:
- Quando invocados, os métodos
sendAccessibilityEvent()
esendAccessibilityEventUnchecked()
são adiados paraonInitializeAccessibilityEvent()
.As implementações personalizadas de
View
podem querer implementaronInitializeAccessibilityEvent()
para anexar outras informações de acessibilidade aoAccessibilityEvent
, 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. - 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 callbackonPopulateAccessibilityEvent()
.As implementações personalizadas de
View
geralmente precisam implementaronPopulateAccessibilityEvent()
para adicionar mais conteúdo de texto aoAccessibilityEvent
se o texto deandroid:contentDescription
estiver ausente ou insuficiente. Para adicionar mais descrição de texto aoAccessibilityEvent
, chamegetText()
.add()
. - Nesse ponto, o
View
transmite o evento para cima na hierarquia de visualização chamandorequestSendAccessibilityEvent()
na visualização mãe. Cada visualização mãe tem a chance de aumentar as informações de acessibilidade adicionando umAccessibilityRecord
até chegar à visualização raiz, que envia o evento aoAccessibilityManager
comsendAccessibilityEvent()
.
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:
- Ao receber um
AccessibilityEvent
de um aplicativo, chameAccessibilityEvent.getRecord()
para recuperar umAccessibilityRecord
específico (pode haver vários registros anexados ao evento). - Usando
AccessibilityEvent
ou umAccessibilityRecord
individual, você pode chamargetSource()
para extrair um objetoAccessibilityNodeInfo
.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 objetoAccessibilityNodeInfo
retornado deAccessibilityEvent
descreve a fonte do evento, enquanto a origem de umAccessibilityRecord
descreve o antecessor da fonte de eventos. - Com o
AccessibilityNodeInfo
, é possível consultar informações sobre ele, chamargetParent()
ougetChild()
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:
AccessibilityManager.AccessibilityStateChangeListener
é uma interface que permite receber um callback sempre que a acessibilidade estiver ativada ou desativada.getEnabledAccessibilityServiceList()
fornece informações sobre quais serviços de acessibilidade estão ativados no momento.isTouchExplorationEnabled()
informa se o modo de exploração por toque está ativado.
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 chamarstart()
para indicar que está pronto para entregar o áudio e, em seguida, chamaraudioAvailable()
, transmitindo a ele os dados de áudio em um buffer de bytes. Quando o mecanismo tiver passado todo o áudio pelo buffer, chamedone()
.
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:
TYPE_AMBIENT_TEMPERATURE
: um sensor de temperatura que fornece a temperatura do ambiente (ambiente) em graus Celsius.TYPE_RELATIVE_HUMIDITY
: um sensor que fornece a umidade relativa do ambiente (sala) como porcentagem.
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()
esetLogo()
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 deActivity
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 .
Menus pop-up
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çãoSTATUS_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çãoSTATUS_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:
- Atualização do compilador JavaScript V8 para melhorar a performance
- Além disso, outras melhorias importantes transferidas do Android
3.0 agora estão disponíveis para celulares:
- Suporte para elementos de posição fixa em todas as páginas
- Captura de mídia HTML
- Eventos de orientação do dispositivo
- Transformações CSS 3D
Permissões
Confira a seguir as novas permissões:
ADD_VOICEMAIL
: permite que um serviço de correio de voz adicione mensagens de correio de voz ao dispositivo.BIND_TEXT_SERVICE
: um serviço que implementaSpellCheckerService
precisa exigir essa permissão para si.BIND_VPN_SERVICE
: um serviço que implementaVpnService
precisa exigir essa permissão para si.- android.Manifest.permission#READ_PROFILE: dá acesso de leitura ao provedor
ContactsContract.Profile
. - android.Manifest.permission#WRITE_PROFILE: dá acesso de gravação ao provedor
ContactsContract.Profile
.
Recursos do dispositivo
Estes são os novos recursos do dispositivo:
FEATURE_WIFI_DIRECT
: declara que o aplicativo usa Wi-Fi para comunicações ponto a ponto.
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 otargetSdkVersion
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"
. Consulteandroid: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?.