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
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.
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.
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}.
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()}.
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.
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:
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}.
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:
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;
}
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:
{@code $ adb shell cmd appops set RUN_IN_BACKGROUND ignore}
{@code $ adb shell cmd appops set RUN_IN_BACKGROUND allow}