page.title=Otimizações em segundo plano page.metaDescription=Novas restrições a transmissões implícitas. page.keywords="android N", "implicit broadcasts", "job scheduler" page.image=images/cards/card-nyc_2x.jpg @jd:body

Neste documento

  1. Restrições sobre CONNECTIVITY_ACTION
  2. Agendamento de trabalhos de rede em conexões ilimitadas
  3. Monitoramento de conectividade de rede durante a execução do aplicativo
  4. Restrições sobre NEW_PICTURE e NEW_VIDEO
  5. Novos métodos JobInfo
  6. Novos métodos JobParameter
  7. Otimização adicional do aplicativo

Os processos em segundo plano podem fazer uso intensivo de memória e bateria. Por exemplo, uma transmissão implícita poderá iniciar diversos processos em segundo plano registrados para escutá-la, mesmo se esses processos não forem muito usados. Isso pode afetar substancialmente o desempenho do dispositivo e a experiência de usuário.

Para aliviar esse problema, o N Developer Preview aplica as seguintes restrições:

A estrutura do Android oferece diversas soluções para reduzir a necessidade dessas transmissões implícitas. Por exemplo, {@link android.app.job.JobScheduler} e {@code GcmNetworkManager} oferecem mecanismos robustos para agendar operações de rede quando ocorrem condições especificadas, como conexão a uma rede ilimitada. Agora, você também pode usar {@link android.app.job.JobScheduler} para reagir a mudanças em provedores de conteúdo. Os objetos {@link android.app.job.JobInfo} encapsulam os parâmetros usados por {@link android.app.job.JobScheduler} para agendar o seu trabalho. Quando as condições do trabalho forem atendidas, o sistema executará o trabalho no {@link android.app.job.JobService} do seu aplicativo.

Neste documento, veremos como usar métodos alternativos, como {@link android.app.job.JobScheduler}, para adaptar seu aplicativo a essas novas restrições.

Restrições sobre CONNECTIVITY_ACTION

Os aplicativos direcionados ao N Developer Preview não receberão transmissões {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION} se estiverem registrados para recebê-las no seu manifesto e os processos que dependerem dessas transmissões não serão iniciados. Isso pode ser um problema para aplicativos que quiserem escutar mudanças de rede ou executar atividades de rede em massa quando o dispositivo se conectar a uma rede ilimitada. Já existem várias soluções para contornar essa restrição na estrutura do Android, mas a escolha da solução correta depende do que o aplicativo pretende realizar.

Observação: um {@link android.content.BroadcastReceiver} registrado em {@link android.content.Context#registerReceiver Context.registerReceiver()} continuará a receber essas transmissões enquanto o aplicativo estiver em primeiro plano.

Agendamento de trabalhos de rede em conexões ilimitadas

Ao usar a classe {@link android.app.job.JobInfo.Builder JobInfo.Builder} para compilar o objeto {@link android.app.job.JobInfo}, aplique o método {@link android.app.job.JobInfo.Builder#setRequiredNetworkType setRequiredNetworkType()} e passe {@link android.app.job.JobInfo JobInfo.NETWORK_TYPE_UNMETERED} como parâmetro do trabalho. O código a seguir agendará a execução de um serviço quando o dispositivo se conectar a uma rede ilimitada e estiver carregando:

public static final int MY_BACKGROUND_JOB = 0;
...
public static void scheduleJob(Context context) {
  JobScheduler js =
      (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
  JobInfo job = new JobInfo.Builder(
    MY_BACKGROUND_JOB,
    new ComponentName(context, MyJobService.class))
      .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
      .setRequiresCharging(true)
      .build();
  js.schedule(job);
}

Quando as condições para o trabalho forem atendidas, o aplicativo receberá um retorno de chamada para executar o método {@link android.app.job.JobService#onStartJob onStartJob()} na {@code JobService.class} especificada. Para ver mais exemplos da implementação de {@link android.app.job.JobScheduler}, consulte o aplicativo de exemplo do JobScheduler.

Os aplicativos que usarem serviços do GMSCore e forem direcionados ao Android 5.0 (nível da API 21) ou anterior poderão usar {@code GcmNetworkManager} e especificar {@code Task.NETWORK_STATE_UNMETERED}.

Monitoramento de conectividade de rede durante a execução do aplicativo

Aplicativos executados em primeiro plano ainda poderão escutar {@code CONNECTIVITY_CHANGE} com um {@link android.content.BroadcastReceiver} registrado. No entanto, a API {@link android.net.ConnectivityManager} oferece um método mais robusto para solicitar um retorno de chamada apenas quando condições de rede especificadas são atendidas.

Os objetos {@link android.net.NetworkRequest} definem os parâmetros do retorno de chamada de rede em termos de {@link android.net.NetworkCapabilities}. Objetos {@link android.net.NetworkRequest} são criados com a classe {@link android.net.NetworkRequest.Builder NetworkRequest.Builder}. Em seguida, {@link android.net.ConnectivityManager#registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback) registerNetworkCallback()} passa o objeto {@link android.net.NetworkRequest} ao sistema. Quando as condições de rede forem atendidas, o aplicativo receberá um retorno de chamada para executar o método {@link android.net.ConnectivityManager.NetworkCallback#onAvailable onAvailable()} definido em sua classe {@link android.net.ConnectivityManager.NetworkCallback}.

O aplicativo continuará a receber retornos de chamada até que o aplicativo encerre ou chame {@link android.net.ConnectivityManager#unregisterNetworkCallback unregisterNetworkCallback()}.

Restrições sobre NEW_PICTURE e NEW_VIDEO

No N Developer Preview, os aplicativos não conseguem enviar nem receber transmissões {@link android.hardware.Camera#ACTION_NEW_PICTURE} ou {@link android.hardware.Camera#ACTION_NEW_VIDEO}. Essa restrição ajuda a aliviar os impactos no desempenho e na experiência de usuário quando vários aplicativos devem despertar para processar uma nova imagem ou vídeo. O N Developer Preview estende {@link android.app.job.JobInfo} e {@link android.app.job.JobParameters} para oferecer uma solução alternativa.

Novos métodos JobInfo

Para acionar trabalhos em mudanças de URI de conteúdo, o N Developer Preview estende a API {@link android.app.job.JobInfo} com os seguintes métodos:

{@code JobInfo.TriggerContentUri()}
Encapsula os parâmetros necessários para acionar um trabalho quando ocorrem mudanças de URI de conteúdo.
{@code JobInfo.Builder.addTriggerContentUri()}
Passa um objeto {@code TriggerContentUri} para {@link android.app.job.JobInfo}. Um {@link android.database.ContentObserver} monitora o URI de conteúdo encapsulado. Se houver vários objetos {@code TriggerContentUri} associados a um trabalho, o sistema fornecerá um retorno de chamada, mesmo se indicar uma mudança em apenas um dos URIs de conteúdo.
Adicione o sinalizador {@code TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS} para acionar o trabalho em caso de mudança em qualquer um dos descendentes do URI especificado. Esse indicador corresponde ao parâmetro {@code notifyForDescendants} passado para {@link android.content.ContentResolver#registerContentObserver registerContentObserver()}.

Observação: não é possível usar {@code TriggerContentUri()} juntamente com {@link android.app.job.JobInfo.Builder#setPeriodic setPeriodic()} ou {@link android.app.job.JobInfo.Builder#setPersisted setPersisted()}. Para monitorar continuamente mudanças de conteúdo, agende um novo {@link android.app.job.JobInfo} antes que o {@link android.app.job.JobService} do aplicativo encerre o processamento do retorno de chamada mais recente.

O exemplo de código a seguir agenda um trabalho que será acionado quando o sistema indicar uma mudança no URI de conteúdo {@code MEDIA_URI}:

public static final int MY_BACKGROUND_JOB = 0;
...
public static void scheduleJob(Context context) {
  JobScheduler js =
          (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
  JobInfo.Builder builder = new JobInfo.Builder(
          MY_BACKGROUND_JOB,
          new ComponentName(context, MediaContentJob.class));
  builder.addTriggerContentUri(
          new JobInfo.TriggerContentUri(MEDIA_URI,
          JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
  js.schedule(builder.build());
}

Quando o sistema indicar uma mudança nos URIs de conteúdo especificados, o aplicativo receberá um retorno de chamada e um objeto {@link android.app.job.JobParameters} será passado para o método {@link android.app.job.JobService#onStartJob onStartJob()} na {@code MediaContentJob.class}.

Novos métodos JobParameter

O N Developer Preview também estende {@link android.app.job.JobParameters} para permitir que o aplicativo receba informações úteis sobre quais autoridades de conteúdo e URIs acionaram o trabalho:

{@code Uri[] getTriggeredContentUris()}
Retorna uma matriz de URIs que acionaram o trabalho. O retorno será {@code null} se o trabalho não foi acionado por URIs (por exemplo, o trabalho foi acionado devido a um prazo ou por outro motivo) ou o número de URIs modificados for maior que 50.
{@code String[] getTriggeredContentAuthorities()}
Retorna uma matriz de strings de autoridades de conteúdo que acionaram o trabalho. Se a matriz retornada não for {@code null}, use {@code getTriggeredContentUris()} para recuperar os detalhes sobre quais URIs foram modificados.

O exemplo de código a seguir substitui o método {@link android.app.job.JobService#onStartJob JobService.onStartJob()} e registra as autoridades de conteúdo e URIs que acionaram o trabalho:

@Override
public boolean onStartJob(JobParameters params) {
  StringBuilder sb = new StringBuilder();
  sb.append("Media content has changed:\n");
  if (params.getTriggeredContentAuthorities() != null) {
      sb.append("Authorities: ");
      boolean first = true;
      for (String auth :
          params.getTriggeredContentAuthorities()) {
          if (first) {
              first = false;
          } else {
             sb.append(", ");
          }
           sb.append(auth);
      }
      if (params.getTriggeredContentUris() != null) {
          for (Uri uri : params.getTriggeredContentUris()) {
              sb.append("\n");
              sb.append(uri);
          }
      }
  } else {
      sb.append("(No content)");
  }
  Log.i(TAG, sb.toString());
  return true;
}

Otimização adicional do aplicativo

A otimização dos aplicativos para execução em dispositivos com pouca memória ou em condições de pouca memória pode melhorar o desempenho e a experiência do usuário. A remoção de dependências de serviços em segundo plano e receptores de transmissão implícita registrados estatisticamente podem aprimorar a execução do aplicativo nesses dispositivos. Embora o N Developer Preview avance na redução de alguns desses problemas, recomendamos que você otimize os aplicativos para execução sem o uso desses processos em segundo plano.

O N Developer Preview introduz alguns comandos adicionais do Bridge de Debug Android (ADB) que podem ser usados para testar o comportamento do aplicativo de teste com esses processos em segundo plano desativados: