Android 4.2 APIs

API de nível: 17

Android 4.2 (JELLY_BEAN_MR1) é uma atualização da versão Jelly Bean que oferece novos recursos para usuários e apps desenvolvedores de aplicativos. Este documento fornece uma introdução às novas APIs mais importantes e úteis para desenvolvedores.

Como desenvolvedor de apps, você precisa fazer o download da imagem do sistema e da plataforma do SDK do Android 4.2 pelo SDK Manager assim que possível. Se você não tiver um dispositivo com Android 4.2 no qual testar o aplicativo, use o sistema Android 4.2 para testar seu app no Android Emulator. Em seguida, crie seus aplicativos na plataforma Android 4.2 para começar a usar as APIs mais recentes.

Para otimizar seu aplicativo para dispositivos com o Android 4.2, defina o targetSdkVersion como "17", instale em uma imagem do sistema Android 4.2, testá-lo e publicar uma atualização com essa alteração.

Você podem usar APIs no Android 4.2 e, ao mesmo tempo, oferecer suporte a versões mais antigas, adicionando ao código que verificam o nível da API do sistema antes da execução APIs não compatíveis com seu minSdkVersion. Para saber mais sobre manter a compatibilidade com versões anteriores, leia Criação de compatibilidade com versões anteriores IUs.

Confira mais informações sobre como os níveis de API funcionam em O que é o nível da API?.

Mudanças de comportamento importantes

Se você já tiver publicado um app para Android, saiba que: mudanças que podem afetar o comportamento do app:

  • Os provedores de conteúdo não são mais exportados por padrão. Ou seja, o valor padrão para o atributo android:exported agora é “false". Se é importante que outros apps sejam conseguir acessar seu provedor de conteúdo, defina explicitamente android:exported="true".

    Essa mudança só vai entrar em vigor se você definir android:targetSdkVersion ou android:minSdkVersion como 17 ou mais recente. Caso contrário, o valor padrão ainda será “true". mesmo com o Android 4.2 ou superior.

  • Em comparação com versões anteriores do Android, os resultados de local do usuário podem ser menos precisos se o app solicitar a permissão ACCESS_COARSE_LOCATION, mas não a ACCESS_FINE_LOCATION.

    Para atender às expectativas de privacidade dos usuários quando o app solicita permissão para localização aproximada (e não precisa), o sistema não vai fornecer uma estimativa de local do usuário um resultado mais preciso do que um quarteirão.

  • Algumas configurações do dispositivo definidas por Settings.System agora estão somente leitura. Se o app tentar gravar mudanças nas configurações definidas no Settings.System que foram movidas para Settings.Global, faça o seguinte: a operação de gravação falhará silenciosamente ao ser executada no Android 4.2 e versões posteriores.

    Mesmo que o valor de android:targetSdkVersion e android:minSdkVersion seja menor que 17, o app não poderá modificar as configurações que movido para Settings.Global ao executar no Android 4.2 e versões mais recentes.

  • Se o app usar WebView, o Android 4.2 adiciona uma camada extra de segurança para que você possa vincular o JavaScript com mais segurança ao código do Android. Se você definir seu targetSdkVersion para 17 ou maior, agora é preciso adicionar a anotação @JavascriptInterface a qualquer método que você que devem estar disponíveis para seu JavaScript (o método também precisa ser público). Se você não fornecer a anotação, o método não poderá ser acessado por uma página da Web no WebView quando executado no Android 4.2 ou mais recente. Se você definir o targetSdkVersion para 16 ou menos, a anotação não é necessária, mas recomendamos que você atualize sua versão de destino e adicione a anotação para aumentar a segurança.

    Leia mais sobre vinculação do código JavaScript para o código do Android.

Daydream

O Daydream é um novo modo de protetor de tela interativo para dispositivos Android. Ele é ativado automaticamente quando o dispositivo está inserido em uma base ou quando o dispositivo fica inativo enquanto conectado a uma carregador (em vez de desligar a tela). O Daydream mostra um sonho por vez, que pode ser uma exibição puramente visual e passiva que é dispensada ao tocar ou pode ser interativa e responsiva ao pacote completo de eventos de entrada. Seus sonhos são executados no processo do app e têm acesso total ao kit de ferramentas de interface do Android, incluindo visualizações, layouts e animações. Assim, eles são mais flexíveis e poderosos do que os papéis de parede animados ou widgets de apps.

Você pode criar um sonho para o Daydream implementando uma subclasse de DreamService. As APIs DreamService são projetadas para serem semelhantes às de Activity. Para especificar a interface do usuário sonhar, transmita um ID de recurso de layout ou View para setContentView() a qualquer momento depois de em uma janela, como do onAttachedToWindow() o retorno de chamada.

A classe DreamService fornece outro callback importante do ciclo de vida métodos com base nas APIs Service básicas, como onDreamingStarted(), onDreamingStopped() e onDetachedFromWindow(). Não é possível iniciar uma DreamService no app. Ela é iniciada automaticamente pelo sistema.

Se o sonho for interativo, você poderá iniciar uma atividade dele para enviar o usuário à interface completa do app para mais detalhes ou controle. Você pode usar finish() para encerrar o sonho e permitir que o usuário veja a nova atividade.

Para disponibilizar o modo de suspensão ao sistema, declare o DreamService com um elemento <service> no arquivo de manifesto. Em seguida, inclua um filtro de intent com a ação "android.service.dreams.DreamService". Exemplo:

<service android:name=".MyDream" android:exported="true"
    android:icon="@drawable/dream_icon" android:label="@string/dream_label" >
    <intent-filter>
        <action android:name="android.service.dreams.DreamService" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>

Há outros métodos úteis em DreamService que você deve conhecer:

  • setInteractive(boolean) controla se o Dream recebe eventos de entrada ou sai imediatamente após a entrada do usuário. Se o sonho é interativo, o usuário pode usar os botões Voltar ou Início para sair do sonho, ou você pode chamar finish() para impedi-lo.
  • Se você quiser uma tela totalmente imersiva, chame setFullscreen() para ocultar a barra de status.
  • Antes do Daydream começar, a tela fica escura para sinalizar ao usuário que o tempo limite de inatividade está se aproximando. Chamar setScreenBright(true) permite que você configure a tela com o brilho normal.

Para mais informações, consulte a documentação DreamService.

Telas secundárias

O Android agora permite que seu app mostre conteúdo exclusivo em outras telas conectadas ao dispositivo do usuário por conexão com fio ou Wi-Fi. Para criar conteúdo exclusivo para uma tela secundária, estenda o Presentation e implemente o callback onCreate(). Em onCreate(), especifique a interface para a tela secundária chamando setContentView(). Como uma extensão da classe Dialog, a classe Presentation fornece a região em que o app pode mostrar uma IU exclusiva na tela secundária.

Para detectar telas secundárias em que você pode mostrar o Presentation, use as APIs DisplayManager ou MediaRouter. Embora as APIs DisplayManager permitam enumerar várias telas que podem ser conectadas ao mesmo tempo, geralmente é necessário usar MediaRouter para acessar rapidamente a tela padrão do sistema para apresentações.

Para definir a tela padrão da sua apresentação, chame MediaRouter.getSelectedRoute() e transmita-a ROUTE_TYPE_LIVE_VIDEO. Isso retorna um objeto MediaRouter.RouteInfo que descreve a rota selecionada atualmente pelo sistema para apresentações de vídeo. Se o MediaRouter.RouteInfo não for nulo, chame getPresentationDisplay() para receber o Display que representa a tela conectada.

Você pode mostrar sua apresentação transmitindo o objeto Display como um construtor para a classe Presentation. Sua apresentação agora será na tela secundária.

Para detectar no momento da execução quando uma nova tela for conectada, crie uma instância de MediaRouter.SimpleCallback em que você implemente o método de callback onRoutePresentationDisplayChanged(), que o sistema vai chamar quando uma nova tela de apresentação for conectada. Em seguida, registre o MediaRouter.SimpleCallback transmitindo-o para MediaRouter.addCallback() com o tipo de rota ROUTE_TYPE_LIVE_VIDEO. Quando você receber uma chamada para onRoutePresentationDisplayChanged(), basta chamar MediaRouter.getSelectedRoute(), conforme mencionado acima.

Para otimizar ainda mais a interface no Presentation para telas secundárias, é possível aplicar um tema diferente especificando o atributo android:presentationTheme no <style> que você aplicou ao aplicativo ou à atividade.

Lembre-se de que as telas conectadas ao dispositivo do usuário geralmente têm um tamanho de tela maior e provavelmente uma densidade de tela diferente. Como as características da tela podem ser diferentes, é necessário fornecer recursos otimizados especificamente para telas maiores. Se você precisar solicitar mais recursos do Presentation, chame getContext().getResources() para receber o objeto Resources correspondente à tela. Isso fornece os recursos apropriados do app mais adequados para o tamanho e a densidade da tela da tela secundária.

Para mais informações e alguns exemplos de código, consulte a Presentation documentação da classe.

Widgets da tela de bloqueio

O Android agora permite que os usuários adicionem widgets de apps à tela de bloqueio. Para disponibilizar o widget do app na tela de bloqueio, adicione o atributo android:widgetCategory ao arquivo XML que especifica o AppWidgetProviderInfo. Esse atributo é compatível com dois valores: home_screen e keyguard. Por padrão, o atributo é definido como home_screen para que os usuários possam adicionar seus widget do app à tela inicial. Se você quiser que o widget do app também esteja disponível na tela de bloqueio, adicione o valor keyguard:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    android:widgetCategory="keyguard|home_screen">
</appwidget-provider>

Também é necessário especificar um layout inicial para o widget de app na tela de bloqueio com o atributo android:initialKeyguardLayout. Ele funciona da mesma forma que o android:initialLayout, fornecendo um layout que pode aparecer imediatamente até que o widget do app seja inicializado e possa atualizar o layout.

Para mais informações sobre como criar widgets de app para a tela de bloqueio, incluindo o tamanho adequado do widget de app na tela de bloqueio, consulte o guia Widgets de app.

Vários usuários

Agora, o Android permite vários espaços de usuário em dispositivos compartilháveis, como tablets. Cada usuário em um dispositivo tem um conjunto de contas, apps, configurações do sistema, arquivos e outros dados associados ao usuário.

Como desenvolvedor de apps, você não precisa fazer nada diferente para que seu app funcione com vários usuários em um único dispositivo. Independentemente de quantos usuários dispositivo, os dados que o app salva para um determinado usuário são mantidos separados dos dados que o app salva para outros usuários. O sistema rastreia quais dados do usuário pertencem ao processo em que o app está sendo executado e fornece acesso apenas aos dados desse usuário, não permitindo acesso aos dados de outros usuários.

Como salvar dados em um ambiente multiusuário

Sempre que o app salvar preferências do usuário, criar um banco de dados ou gravar um arquivo no espaço de armazenamento interno ou externo do usuário, esses dados só poderão ser acessados durante a execução como esse usuário.

Para ter certeza de que seu app se comporta corretamente em um ambiente multiusuário, não consulte o diretório interno do app ou local de armazenamento externo usando caminhos codificados e sempre as APIs apropriadas:

Não importa qual dessas APIs você usa para salvar dados de um determinado usuário. Os dados não vão ser acessíveis durante a execução como um usuário diferente. Do ponto de vista do seu app, cada usuário está executando em um dispositivo completamente separado.

Como identificar usuários em um ambiente multiusuário

Se o app quiser identificar usuários únicos, por exemplo, para coletar análises ou criar outras associações de conta, siga as práticas recomendadas para identificar instalações únicas. Crie uma nova UUID quando o app for iniciado para o pela primeira vez, você certamente obterá um ID exclusivo para rastrear cada usuário, independentemente de quantos que os usuários instalem seu app em um único dispositivo. Como alternativa, você pode salvar um token local buscado em seu servidor ou use o ID de registro fornecido pelo Google Cloud Messaging.

Esteja ciente de que, se o aplicativo solicitar um dos identificadores de dispositivo de hardware (como o MAC Wi-Fi endereço ou o número da SERIAL), elas fornecerão o mesmo valor para cada usuário, porque esses identificadores estão vinculados ao hardware e não ao usuário. Sem mencionar o outro problemas que esses identificadores apresentam, conforme discutido no tópico Como Postagem do blog sobre instalações de apps (em inglês).

Novas configurações globais

As configurações do sistema foram atualizadas para oferecer suporte a vários usuários com a adição de Settings.Global. Esta coleção de configurações é semelhante às configurações do Settings.Secure, porque são somente leitura, mas são aplicadas globalmente todos os espaços do usuário no dispositivo.

Várias configurações atuais foram realocadas aqui de Settings.System ou Settings.Secure. Se o app estiver fazendo mudanças nas configurações definidas anteriormente em Settings.System (como AIRPLANE_MODE_ON), isso não vai mais funcionar em um dispositivo com o Android 4.2 ou mais recente se essas configurações forem transferidas para Settings.Global. É possível continuar lendo as configurações que estão em Settings.Global, mas, como elas não são mais consideradas seguras para mudanças de apps, a tentativa de fazer isso vai falhar silenciosamente, e o sistema vai gravar um aviso no registro do sistema ao executar o app no Android 4.2 ou mais recente.

Suporte a layout RTL

O Android agora oferece diversas APIs que permitem criar interfaces do usuário que funcionam Transforme a orientação do layout para oferecer suporte a idiomas que usam interfaces e leitura da direita para a esquerda (RTL, na sigla em inglês) direção, como árabe e hebraico.

Para começar a oferecer suporte a layouts RTL no app, defina o atributo android:supportsRtl como o elemento <application> no arquivo de manifesto e defina como “true". Depois disso, o sistema vai ativar várias APIs RTL para exibir seu aplicativo com layouts RTL. Por exemplo, a barra de ações vai mostrar o ícone e o título no lado direito e os botões de ação à esquerda. Além disso, todos os layouts que você criou com as classes View fornecidas pelo framework também serão invertidos.

Se você precisar otimizar ainda mais a aparência do app quando ele for exibido com um layout RTL, há dois níveis básicos de otimização:

  1. Converter propriedades de layout orientadas à esquerda e à direita para um layout orientado ao início e ao fim propriedades.

    Por exemplo, use android:layout_marginStart. no lugar de android:layout_marginLeft e android:layout_marginEnd no lugar de android:layout_marginRight.

    A classe RelativeLayout também fornece o layout correspondente para substituir as posições esquerda/direita, como android:layout_alignParentStart para substituir android:layout_alignParentLeft e android:layout_toStartOf em vez de android:layout_toLeftOf.

  2. Ou, para oferecer otimização completa para layouts RTL, forneça arquivos de layout completamente separados usando o qualificador de recurso ldrtl (ldrtl significa layout-direction-right-to-left}). Por exemplo, é possível salvar os arquivos de layout padrão em res/layout/ e os layouts otimizados para RTL em res/layout-ldrtl/.

    O qualificador ldrtl é ótimo para recursos drawable, para que você possa fornecer gráficos orientados na direção correspondente à direção de leitura.

Várias outras APIs estão disponíveis no framework para oferecer suporte a layouts RTL, como na classe View, para que você possa implementar os comportamentos adequados para visualizações personalizadas, e em Configuration para consultar a direção de layout atual.

Observação: se você estiver usando o SQlite e tiver tabelas ou nomes de colunas que são "somente números", tenha cuidado: o uso de String.format(String, Object...) pode levar a erros em que os números foram convertidos nos equivalentes em árabe se o dispositivo tiver sido definido para a localidade árabe. Use String.format(Locale,String,Object...) para garantir que os números sejam preservados como ASCII. Use também String.format("%d", int) em vez de String.valueOf(int) para formatar números.

Fragments aninhados

Agora é possível incorporar fragmentos em outros fragmentos. Isso é útil para várias situações em que você quer colocar componentes de IU dinâmicos e reutilizáveis em um componente de IU que é dinâmico e reutilizável. Por exemplo, se você usar ViewPager para criar fragmentos que deslizam para a esquerda e para a direita e consomem a maior parte do espaço da tela, Agora é possível inserir fragmentos em cada página de fragmentos.

Para aninhar um fragmento, basta chamar getChildFragmentManager() no o Fragment em que você quer adicionar um fragmento. Isso retorna um FragmentManager que pode ser usado normalmente na atividade de nível superior. para criar transações de fragmentos. Por exemplo, este é um código que adiciona um fragmento de uma classe Fragment existente:

Kotlin

val videoFragment = VideoPlayerFragment()
childFragmentManager.beginTransaction().apply {
    add(R.id.video_fragment, videoFragment)
    commit()
}

Java

Fragment videoFragment = new VideoPlayerFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.video_fragment, videoFragment).commit();

A partir de um fragmento aninhado, você pode obter uma referência ao fragmento pai chamando getParentFragment():

A Biblioteca de Suporte do Android também oferece suporte a fragmentos aninhados, para que você possa implementar designs de fragmentos aninhados no Android 1.6 e versões mais recentes.

Observação:não é possível inflar um layout em um fragmento quando ele inclui um <fragment>. Fragmentos aninhados são aceitos apenas quando adicionados a um fragmentar dinamicamente.

RenderScript

A funcionalidade de cálculo do RenderScript foi aprimorada com os seguintes recursos:

Intrínsecos do script

É possível usar os intrínsecos de script integrados do Renderscript que implementam operações comuns, como:

Para usar um script intrínseco, chame o método estático create() de cada para criar uma instância do script. Em seguida, chame os métodos set() disponíveis de cada script intrínseco para definir as entradas e opções necessárias. Por fim, chame o método forEach() para executar o script.

Grupos de script

ScriptGroups permitem encadear o Renderscript relacionado. scripts e executá-los com uma chamada.

Use um ScriptGroup.Builder para adicionar todos os scripts ao grupo chamando addKernel(). Depois de adicionar todos os scripts, crie as conexões entre eles chamando addConnection(). Quando terminar de adicionar as conexões, chame create(). para criar o grupo de scripts. Antes de executar o grupo de scripts, especifique a entrada Allocation e o script inicial para execução com o método setInput(Script.KernelID, Allocation) e forneça a saída Allocation em que o resultado será gravado e o script final para execução com setOutput(). Por fim, chame execute() para executar o grupo de scripts.

Filterscript (em inglês)

O Filterscript define restrições nas APIs Renderscript existentes que permitem que o código resultante seja executado em uma variedade maior de processadores (CPUs, GPUs e DSPs). Para criar arquivos Filterscript, crie arquivos .fs em vez de .rs e especifique #pragma rs_fp_relaxed para informar ao ambiente de execução do Renderscript que seus scripts não exigem precisão de ponto flutuante IEEE 754-2008 estrita. Essa precisão permite a liberação de zero para desnormalização e arredondamento em direção a zero. Além disso, o Filterscript os scripts não devem usar tipos integrados de 32 bits e devem especificar uma função raiz personalizada usando o __attribute__((kernel)) porque o Filterscript não é compatível com ponteiros, que define a assinatura padrão da função root().

Observação:embora o Filterscript seja compatível com a plataforma, o desenvolvedor O suporte será disponibilizado na versão 21.0.1 das Ferramentas do SDK.

Para conferir uma visão detalhada de todas as mudanças de API no Android 4.2, consulte o Relatório de diferenças de API.