1page.title=Otimizações em segundo plano
2page.metaDescription=Novas restrições a transmissões implícitas.
3page.keywords="android N", "implicit broadcasts", "job scheduler"
4page.image=images/cards/card-nyc_2x.jpg
5
6@jd:body
7
8<div id="qv-wrapper">
9  <div id="qv">
10    <h2>
11      Neste documento
12    </h2>
13
14    <ol>
15      <li>
16        <a href="#connectivity-action">Restrições sobre CONNECTIVITY_ACTION</a>
17      </li>
18
19      <li>
20        <a href="#sched-jobs">Agendamento de trabalhos de rede em conexões
21 ilimitadas</a>
22      </li>
23
24      <li>
25        <a href="#monitor-conn">Monitoramento de conectividade de rede durante a execução
26 do aplicativo</a>
27      </li>
28
29      <li>
30        <a href="#media-broadcasts">Restrições sobre NEW_PICTURE e
31 NEW_VIDEO</a>
32      </li>
33
34      <li>
35        <a href="#new-jobinfo">Novos métodos JobInfo</a>
36      </li>
37
38      <li>
39        <a href="#new-jobparam">Novos métodos JobParameter</a>
40      </li>
41
42      <li>
43        <a href="#further-optimization">Otimização adicional do aplicativo</a>
44      </li>
45    </ol>
46  </div>
47</div>
48
49<p>
50  Os processos em segundo plano podem fazer uso intensivo de memória e bateria. Por exemplo, uma
51 transmissão implícita poderá iniciar diversos processos em segundo plano registrados
52 para escutá-la, mesmo se esses processos não forem muito usados. Isso pode afetar
53 substancialmente o desempenho do dispositivo e a experiência do usuário.
54</p>
55
56<p>
57  Para aliviar esse problema, o Android N aplica as seguintes
58restrições:
59</p>
60
61<ul>
62  <li>Os aplicativos direcionados ao Preview não receberão transmissões {@link
63 android.net.ConnectivityManager#CONNECTIVITY_ACTION} se estiverem
64 registrados para recebê-las no seu manifesto. Os aplicativos em execução ainda
65poderão escutar {@code CONNECTIVITY_CHANGE} no encadeamento principal registrando um
66{@link android.content.BroadcastReceiver} em {@link
67 android.content.Context#registerReceiver Context.registerReceiver()}.
68  </li>
69
70  <li>Os aplicativos não podem enviar nem receber transmissões {@link
71 android.hardware.Camera#ACTION_NEW_PICTURE} ou {@link
72 android.hardware.Camera#ACTION_NEW_VIDEO}. Essa otimização
73 afeta todos os aplicativos e não apenas os direcionados ao Preview.
74  </li>
75</ul>
76
77<p>
78  Se o seu aplicativo usar qualquer uma dessas intenções, remova as dependências delas
79 assim que possível para direcionar corretamente os dispositivos Android N.
80  A estrutura do Android oferece diversas soluções para reduzir a necessidade dessas
81 transmissões implícitas. Por exemplo, {@link android.app.job.JobScheduler}
82 e <a href="https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
83{@code GcmNetworkManager}</a> oferecem mecanismos robustos para agendar operações
84 de rede quando ocorrem condições especificadas, como conexão a uma
85 rede ilimitada. Agora, você também pode usar {@link android.app.job.JobScheduler}
86 para reagir a mudanças em provedores de conteúdo. Os objetos {@link android.app.job.JobInfo}
87 encapsulam os parâmetros usados por {@link android.app.job.JobScheduler}
88 para agendar o seu trabalho. Quando as condições do trabalho forem atendidas, o sistema
89 executará o trabalho no {@link android.app.job.JobService} do seu aplicativo.
90</p>
91
92<p>
93  Neste documento, veremos como usar métodos alternativos, como
94 {@link android.app.job.JobScheduler}, para adaptar seu aplicativo a essas novas
95 restrições.
96</p>
97
98<h2 id="connectivity-action">
99  Restrições sobre CONNECTIVITY_ACTION
100</h2>
101
102<p>
103  Os aplicativos direcionados ao Android N não receberão transmissões {@link
104 android.net.ConnectivityManager#CONNECTIVITY_ACTION} se estiverem
105 registrados para recebê-las no seu manifesto e os processos que dependerem dessas
106 transmissões não serão iniciados. Isso pode ser um problema para aplicativos que quiserem
107 escutar mudanças de rede ou executar atividades de rede em massa quando o
108 dispositivo se conectar a uma rede ilimitada. Já existem várias soluções para contornar essa
109 restrição na estrutura do Android, mas a escolha da solução correta
110 depende do que o aplicativo pretende realizar.
111</p>
112
113<p class="note">
114  <strong>Observação:</strong> Um {@link android.content.BroadcastReceiver} registrado em
115 {@link android.content.Context#registerReceiver Context.registerReceiver()}
116 continuará a receber essas transmissões enquanto o aplicativo estiver em execução.
117</p>
118
119<h3 id="sched-jobs">
120  Agendamento de trabalhos de rede em conexões ilimitadas
121</h3>
122
123<p>
124  Ao usar a classe {@link android.app.job.JobInfo.Builder JobInfo.Builder}
125 para compilar o objeto {@link android.app.job.JobInfo}, aplique o método {@link
126  android.app.job.JobInfo.Builder#setRequiredNetworkType
127  setRequiredNetworkType()} e passe {@link android.app.job.JobInfo
128  JobInfo.NETWORK_TYPE_UNMETERED} como parâmetro do trabalho. O código a seguir
129 agendará a execução de um serviço quando o dispositivo se conectar a uma rede
130 ilimitada e estiver carregando:
131</p>
132
133<pre>
134public static final int MY_BACKGROUND_JOB = 0;
135...
136public static void scheduleJob(Context context) {
137  JobScheduler js =
138      (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
139  JobInfo job = new JobInfo.Builder(
140    MY_BACKGROUND_JOB,
141    new ComponentName(context, MyJobService.class))
142      .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
143      .setRequiresCharging(true)
144      .build();
145  js.schedule(job);
146}
147</pre>
148
149<p>
150  Quando as condições para o trabalho forem atendidas, o aplicativo receberá um retorno de chamada para executar
151 o método {@link android.app.job.JobService#onStartJob onStartJob()} na
152 {@code JobService.class} especificada. Para ver mais exemplos da implementação de {@link
153  android.app.job.JobScheduler}, consulte o <a href="{@docRoot}samples/JobScheduler/index.html">aplicativo de exemplo do JobScheduler</a>.
154</p>
155
156<p>
157  Os aplicativos que usarem serviços do GMSCore e forem direcionados ao Android 5.0 (nível da API 21)
158 ou anterior poderão usar <a href="https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
159  {@code GcmNetworkManager}</a> e especificar {@code Task.NETWORK_STATE_UNMETERED}.
160</p>
161
162<h3 id="monitor-conn">
163  Monitoramento de conectividade de rede durante a execução do aplicativo
164</h3>
165
166<p>
167  Os aplicativos em execução ainda poderão escutar {@code CONNECTIVITY_CHANGE} com um
168 {@link android.content.BroadcastReceiver} registrado. No entanto, a API {@link
169 android.net.ConnectivityManager} oferece um método mais robusto para solicitar
170 um retorno de chamada apenas quando condições de rede especificadas são atendidas.
171</p>
172
173<p>
174  Os objetos {@link android.net.NetworkRequest} definem os parâmetros do
175 retorno de chamada de rede em termos de {@link android.net.NetworkCapabilities}. Objetos
176 {@link android.net.NetworkRequest} são criados com a classe {@link
177  android.net.NetworkRequest.Builder NetworkRequest.Builder}. Em seguida, {@link
178  android.net.ConnectivityManager#registerNetworkCallback(android.net.NetworkRequest,
179  android.net.ConnectivityManager.NetworkCallback) registerNetworkCallback()}
180 passa o objeto {@link android.net.NetworkRequest} ao sistema. Quando
181 as condições de rede forem atendidas, o aplicativo receberá um retorno de chamada para executar o
182 método {@link android.net.ConnectivityManager.NetworkCallback#onAvailable
183  onAvailable()} definido em sua classe {@link
184  android.net.ConnectivityManager.NetworkCallback}.
185</p>
186
187<p>
188  O aplicativo continuará a receber retornos de chamada até que o aplicativo encerre ou chame
189  {@link android.net.ConnectivityManager#unregisterNetworkCallback
190  unregisterNetworkCallback()}.
191</p>
192
193<h2 id="media-broadcasts">
194  Restrições sobre NEW_PICTURE e NEW_VIDEO
195</h2>
196
197<p>
198  No Android N, os aplicativos não conseguem enviar nem receber transmissões {@link
199 android.hardware.Camera#ACTION_NEW_PICTURE} ou {@link
200 android.hardware.Camera#ACTION_NEW_VIDEO}. Essa restrição ajuda a
201 aliviar os impactos no desempenho e na experiência de usuário quando vários aplicativos devem
202 despertar para processar uma nova imagem ou vídeo. O Android N
203 estende {@link android.app.job.JobInfo} e {@link
204 android.app.job.JobParameters} para oferecer uma solução alternativa.
205</p>
206
207<h3 id="new-jobinfo">
208  Novos métodos JobInfo
209</h3>
210
211<p>
212  Para acionar trabalhos em mudanças de URI de conteúdo, o Android N estende
213 a API {@link android.app.job.JobInfo} com os seguintes métodos:
214</p>
215
216<dl>
217  <dt>
218    {@code JobInfo.TriggerContentUri()}
219  </dt>
220
221  <dd>
222    Encapsula os parâmetros necessários para acionar um trabalho quando ocorrem mudanças de URI de conteúdo.
223  </dd>
224
225  <dt>
226    {@code JobInfo.Builder.addTriggerContentUri()}
227  </dt>
228
229  <dd>
230    Passa um objeto {@code TriggerContentUri} para {@link
231    android.app.job.JobInfo}. Um {@link android.database.ContentObserver}
232 monitora o URI de conteúdo encapsulado. Se houver vários objetos {@code
233    TriggerContentUri} associados a um trabalho, o sistema fornecerá um
234 retorno de chamada, mesmo se indicar uma mudança em apenas um dos URIs de conteúdo.
235  </dd>
236
237  <dd>
238    Adicione o sinalizador {@code TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS} para
239 acionar o trabalho em caso de mudança em qualquer um dos descendentes do URI especificado. Esse indicador
240 corresponde ao parâmetro {@code notifyForDescendants} passado para {@link
241    android.content.ContentResolver#registerContentObserver
242    registerContentObserver()}.
243  </dd>
244</dl>
245
246<p class="note">
247  <strong>Observação:</strong> não é possível usar {@code TriggerContentUri()}
248 juntamente com {@link android.app.job.JobInfo.Builder#setPeriodic
249  setPeriodic()} ou {@link android.app.job.JobInfo.Builder#setPersisted
250  setPersisted()}. Para monitorar continuamente mudanças de conteúdo, agende um novo
251 {@link android.app.job.JobInfo} antes que o {@link
252  android.app.job.JobService} do aplicativo encerre o processamento do retorno de chamada mais recente.
253</p>
254
255<p>
256  O exemplo de código a seguir agenda um trabalho que será acionado quando o sistema indicar
257 uma mudança no URI de conteúdo {@code MEDIA_URI}:
258</p>
259
260<pre>
261public static final int MY_BACKGROUND_JOB = 0;
262...
263public static void scheduleJob(Context context) {
264  JobScheduler js =
265          (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
266  JobInfo.Builder builder = new JobInfo.Builder(
267          MY_BACKGROUND_JOB,
268          new ComponentName(context, MediaContentJob.class));
269  builder.addTriggerContentUri(
270          new JobInfo.TriggerContentUri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
271          JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
272  js.schedule(builder.build());
273}
274</pre>
275<p>
276  Quando o sistema indicar uma mudança nos URIs de conteúdo especificados, o aplicativo
277 receberá um retorno de chamada e um objeto {@link android.app.job.JobParameters} será
278 passado para o método {@link android.app.job.JobService#onStartJob onStartJob()}
279 na {@code MediaContentJob.class}.
280</p>
281
282<h3 id="new-jobparam">
283  Novos métodos JobParameter
284</h3>
285
286<p>
287  O Android N também estende {@link android.app.job.JobParameters} para
288 permitir que o aplicativo receba informações úteis sobre quais autoridades de conteúdo
289 e URIs acionaram o trabalho:
290</p>
291
292<dl>
293  <dt>
294    {@code Uri[] getTriggeredContentUris()}
295  </dt>
296
297  <dd>
298    Retorna uma matriz de URIs que acionaram o trabalho. O retorno será {@code
299    null} se o trabalho não foi acionado por URIs (por exemplo, o trabalho foi
300 acionado devido a um prazo ou por outro motivo) ou o número de URIs modificados
301 for maior que 50.
302  </dd>
303
304  <dt>
305    {@code String[] getTriggeredContentAuthorities()}
306  </dt>
307
308  <dd>
309    Retorna uma matriz de strings de autoridades de conteúdo que acionaram o trabalho.
310    Se a matriz retornada não for {@code null}, use {@code getTriggeredContentUris()}
311 para recuperar os detalhes sobre quais URIs foram modificados.
312  </dd>
313</dl>
314
315<p>
316  O exemplo de código a seguir substitui o método {@link
317  android.app.job.JobService#onStartJob JobService.onStartJob()} e
318 registra as autoridades de conteúdo e URIs que acionaram o trabalho:
319</p>
320
321<pre>
322&#64;Override
323public boolean onStartJob(JobParameters params) {
324  StringBuilder sb = new StringBuilder();
325  sb.append("Media content has changed:\n");
326  if (params.getTriggeredContentAuthorities() != null) {
327      sb.append("Authorities: ");
328      boolean first = true;
329      for (String auth :
330          params.getTriggeredContentAuthorities()) {
331          if (first) {
332              first = false;
333          } else {
334             sb.append(", ");
335          }
336           sb.append(auth);
337      }
338      if (params.getTriggeredContentUris() != null) {
339          for (Uri uri : params.getTriggeredContentUris()) {
340              sb.append("\n");
341              sb.append(uri);
342          }
343      }
344  } else {
345      sb.append("(No content)");
346  }
347  Log.i(TAG, sb.toString());
348  return true;
349}
350</pre>
351
352<h2 id="further-optimization">
353  Otimização adicional do aplicativo
354</h2>
355
356<p>
357  A otimização dos aplicativos para execução em dispositivos com pouca memória ou em
358 condições de pouca memória pode melhorar o desempenho e a experiência do usuário. A remoção de
359 dependências de serviços em segundo plano e receptores de transmissão
360 implícita registrados estatisticamente pode aprimorar a execução do aplicativo nesses dispositivos. Embora
361 o Android N avance na redução de alguns desses problemas,
362 recomendamos que você otimize os aplicativos para execução sem o uso desses
363 processos em segundo plano.
364</p>
365
366<p>
367  O Android N introduz alguns comandos adicionais do <a href="{@docRoot}tools/help/adb.html">Android Debug Bridge (ADB)</a> que
368 podem ser usados para testar o comportamento do aplicativo de teste com esses processos em segundo plano desativados:
369</p>
370
371<ul>
372  <li>Para simular condições em que transmissões implícitas e serviços em segundo plano
373 não estão disponíveis, insira o seguinte comando:
374  </li>
375
376  <li style="list-style: none; display: inline">
377<pre class="no-pretty-print">
378{@code $ adb shell cmd appops set &lt;package&gt; RUN_IN_BACKGROUND ignore}
379</pre>
380  </li>
381
382  <li>Para reativar transmissões implícitas e serviços em segundo plano, insira o
383 seguinte comando:
384  </li>
385
386  <li style="list-style: none; display: inline">
387<pre class="no-pretty-print">
388{@code $ adb shell cmd appops set &lt;package&gt; RUN_IN_BACKGROUND allow}
389</pre>
390  </li>
391</ul>
392