1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
|
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
<div id="qv-wrapper">
<div id="qv">
<h2>
Neste documento
</h2>
<ol>
<li>
<a href="#connectivity-action">Restrições sobre CONNECTIVITY_ACTION</a>
</li>
<li>
<a href="#sched-jobs">Agendamento de trabalhos de rede em conexões
ilimitadas</a>
</li>
<li>
<a href="#monitor-conn">Monitoramento de conectividade de rede durante a execução
do aplicativo</a>
</li>
<li>
<a href="#media-broadcasts">Restrições sobre NEW_PICTURE e
NEW_VIDEO</a>
</li>
<li>
<a href="#new-jobinfo">Novos métodos JobInfo</a>
</li>
<li>
<a href="#new-jobparam">Novos métodos JobParameter</a>
</li>
<li>
<a href="#further-optimization">Otimização adicional do aplicativo</a>
</li>
</ol>
</div>
</div>
<p>
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.
</p>
<p>
Para aliviar esse problema, o N Developer Preview aplica as seguintes
restrições:
</p>
<ul>
<li>Os aplicativos direcionados ao Preview não receberão transmissões {@link
android.net.ConnectivityManager#CONNECTIVITY_ACTION} se estiverem
registrados para recebê-las no seu manifesto. Aplicativos executados em primeiro plano
ainda poderão escutar {@code CONNECTIVITY_CHANGE} no encadeamento principal
registrando um {@link android.content.BroadcastReceiver} em {@link
android.content.Context#registerReceiver Context.registerReceiver()}.
</li>
<li>Os aplicativos não podem enviar nem receber transmissões {@link
android.hardware.Camera#ACTION_NEW_PICTURE} ou {@link
android.hardware.Camera#ACTION_NEW_VIDEO}. Essa otimização
afeta todos os aplicativos e não apenas os direcionados ao Preview.
</li>
</ul>
<p>
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 <a href="https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
{@code GcmNetworkManager}</a> 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.
</p>
<p>
Neste documento, veremos como usar métodos alternativos, como
{@link android.app.job.JobScheduler}, para adaptar seu aplicativo a essas novas
restrições.
</p>
<h2 id="connectivity-action">
Restrições sobre CONNECTIVITY_ACTION
</h2>
<p>
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.
</p>
<p class="note">
<strong>Observação:</strong> 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.
</p>
<h3 id="sched-jobs">
Agendamento de trabalhos de rede em conexões ilimitadas
</h3>
<p>
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:
</p>
<pre>
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);
}
</pre>
<p>
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 <a href="{@docRoot}samples/JobScheduler/index.html">aplicativo de exemplo do JobScheduler</a>.
</p>
<p>
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 <a href="https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
{@code GcmNetworkManager}</a> e especificar {@code Task.NETWORK_STATE_UNMETERED}.
</p>
<h3 id="monitor-conn">
Monitoramento de conectividade de rede durante a execução do aplicativo
</h3>
<p>
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.
</p>
<p>
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}.
</p>
<p>
O aplicativo continuará a receber retornos de chamada até que o aplicativo encerre ou chame
{@link android.net.ConnectivityManager#unregisterNetworkCallback
unregisterNetworkCallback()}.
</p>
<h2 id="media-broadcasts">
Restrições sobre NEW_PICTURE e NEW_VIDEO
</h2>
<p>
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.
</p>
<h3 id="new-jobinfo">
Novos métodos JobInfo
</h3>
<p>
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:
</p>
<dl>
<dt>
{@code JobInfo.TriggerContentUri()}
</dt>
<dd>
Encapsula os parâmetros necessários para acionar um trabalho quando ocorrem mudanças de URI de conteúdo.
</dd>
<dt>
{@code JobInfo.Builder.addTriggerContentUri()}
</dt>
<dd>
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.
</dd>
<dd>
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()}.
</dd>
</dl>
<p class="note">
<strong>Observação:</strong> 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.
</p>
<p>
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}:
</p>
<pre>
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());
}
</pre>
<p>
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}.
</p>
<h3 id="new-jobparam">
Novos métodos JobParameter
</h3>
<p>
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:
</p>
<dl>
<dt>
{@code Uri[] getTriggeredContentUris()}
</dt>
<dd>
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.
</dd>
<dt>
{@code String[] getTriggeredContentAuthorities()}
</dt>
<dd>
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.
</dd>
</dl>
<p>
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:
</p>
<pre>
@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;
}
</pre>
<h2 id="further-optimization">
Otimização adicional do aplicativo
</h2>
<p>
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.
</p>
<p>
O N Developer Preview introduz alguns comandos adicionais do <a href="{@docRoot}tools/help/adb.html">Bridge de Debug Android (ADB)</a> que
podem ser usados para testar o comportamento do aplicativo de teste com esses processos em segundo plano desativados:
</p>
<ul>
<li>Para simular condições em que transmissões implícitas e serviços em segundo plano
não estão disponíveis, insira o seguinte comando:
</li>
<li style="list-style: none; display: inline">
<pre class="no-pretty-print">
{@code $ adb shell cmd appops set RUN_IN_BACKGROUND ignore}
</pre>
</li>
<li>Para reativar transmissões implícitas e serviços em segundo plano, insira o
seguinte comando:
</li>
<li style="list-style: none; display: inline">
<pre class="no-pretty-print">
{@code $ adb shell cmd appops set RUN_IN_BACKGROUND allow}
</pre>
</li>
</ul>
|