summaryrefslogtreecommitdiff
path: root/docs/html-intl/intl/es/preview/features/background-optimization.jd
blob: 151b5fc7b6334cc36a9a77b59cfe788185da749c (plain)
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=Optimizaciones en segundo plano
page.metaDescription=Nuevas restricciones para difusiones 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>
      Contenido del documento
    </h2>

    <ol>
      <li>
        <a href="#connectivity-action">Restricciones en CONNECTIVITY_ACTION</a>
      </li>

      <li>
        <a href="#sched-jobs">Programación de trabajos en red en conexiones
        sin medición</a>
      </li>

      <li>
        <a href="#monitor-conn">Control de la conectividad de la red mientras la aplicación
        se está ejecutando</a>
      </li>

      <li>
        <a href="#media-broadcasts">Restricciones en NEW_PICTURE y
        NEW_VIDEO</a>
      </li>

      <li>
        <a href="#new-jobinfo">Nuevos métodos de JobInfo</a>
      </li>

      <li>
        <a href="#new-jobparam">Nuevos métodos de JobParameter</a>
      </li>

      <li>
        <a href="#further-optimization">Cómo optimizar aún más tu aplicación</a>
      </li>
    </ol>
  </div>
</div>

<p>
  Los procesos en segundo plano pueden consumir mucha memoria y batería. Por ejemplo, una
  difusión implícita puede iniciar muchos procesos en segundo plano registrados para
  escucharla, aunque esos procesos quizá no desempeñen un trabajo considerable. Esto puede
  afectar de forma significativa tanto el rendimiento del dispositivo como la experiencia de usuario.
</p>

<p>
  Para atenuar este problema, la N Developer Preview aplica las siguientes 
  restricciones:
</p>

<ul>
  <li>Las aplicaciones orientadas a la Preview no reciben difusiones {@link
  android.net.ConnectivityManager#CONNECTIVITY_ACTION} si 
  en su manifiesto registran que las reciben. Las aplicaciones que se ejecutan en segundo plano
  aún pueden escuchar {@code CONNECTIVITY_CHANGE} en su subproceso principal al
  registrar un {@link android.content.BroadcastReceiver} con {@link
  android.content.Context#registerReceiver Context.registerReceiver()}.
  </li>

  <li>Las aplicaciones no pueden enviar ni recibir difusiones {@link
  android.hardware.Camera#ACTION_NEW_PICTURE} ni {@link
  android.hardware.Camera#ACTION_NEW_VIDEO}. Esta optimización
  afecta a todas las aplicaciones, no solo a las orientadas a la Preview.
  </li>
</ul>

<p>
  El framework de Android ofrece varias soluciones para mitigar la necesidad de
  estas difusiones implícitas. Por ejemplo, {@link android.app.job.JobScheduler}
  y <a href="https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
  {@code GcmNetworkManager}</a> proporcionan mecanismos sólidos para programar operaciones
  de red cuando se cumplen las condiciones especificadas, como una conexión a una
  red de uso no medido. Ahora también puedes usar {@link android.app.job.JobScheduler}
  para reaccionar a cambios en relación con los proveedores de contenido. Los objetos {@link android.app.job.JobInfo}
  encapsulan los parámetros que usa {@link android.app.job.JobScheduler}
  para programar el trabajo. Cuando se cumplen las condiciones del trabajo, el sistema
  ejecuta ese trabajo en el {@link android.app.job.JobService} de tu aplicación.
</p>

<p>
  En este documento, aprenderemos cómo usar métodos alternativos, como
  {@link android.app.job.JobScheduler}, para adaptar tu aplicación a esas nuevas
  restricciones.
</p>

<h2 id="connectivity-action">
  Restricciones en CONNECTIVITY_ACTION
</h2>

<p>
  Las aplicaciones orientadas a la N Developer Preview no reciben difusiones {@link
  android.net.ConnectivityManager#CONNECTIVITY_ACTION} si en su
  manifiesto registran que las reciben, y los procesos dependen de que
  no se inicie esa difusión. Esto podría ser un problema para aplicaciones que buscan
  escuchar los cambios en la red o realizar múltiples actividades en red cuando el
  dispositivo se conecta a una red sin medición de uso. Ya existen varias soluciones
  en relación con esta restricción en el framework de Android, pero elegir
  la correcta depende de lo que quieras lograr con tu aplicación.
</p>

<p class="note">
  <strong>Nota:</strong> Un {@link android.content.BroadcastReceiver} registrado con
  {@link android.content.Context#registerReceiver Context.registerReceiver()}
  continúa recibiendo esas difusiones mientras la aplicación está en segundo plano.
</p>

<h3 id="sched-jobs">
  Programación de trabajos en red en conexiones sin medición de uso
</h3>

<p>
  Cuando uses la clase {@link android.app.job.JobInfo.Builder JobInfo.Builder}
  para crear tu objeto {@link android.app.job.JobInfo}, aplica el método {@link
  android.app.job.JobInfo.Builder#setRequiredNetworkType
  setRequiredNetworkType()} y pasa {@link android.app.job.JobInfo
  JobInfo.NETWORK_TYPE_UNMETERED} como parámetro de trabajo. El siguiente ejemplo de código
  programa la ejecución de un servicio cuando el dispositivo se conecta a una red sin
  medición de uso y se está cargando:
</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>
  Cuando se cumplan las condiciones para tu trabajo, tu aplicación recibirá un callback para ejecutar
  el método {@link android.app.job.JobService#onStartJob onStartJob()} en la
   {@code JobService.class} especificada. Para ver más ejemplos de la implementación de {@link
  android.app.job.JobScheduler}, consulta la <a href="{@docRoot}samples/JobScheduler/index.html">aplicación de ejemplo JobScheduler</a>.
</p>

<p>
  Las aplicaciones que usan servicios de GMSCore y están orientadas a Android 5.0 (API nivel 21)
  o anterior, pueden usar <a href="https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
  {@code GcmNetworkManager}</a> y especificar {@code Task.NETWORK_STATE_UNMETERED}.
</p>

<h3 id="monitor-conn">
  Control de la conectividad de la red mientras la aplicación se está ejecutando
</h3>

<p>
  Las aplicaciones que se ejecutan en segundo plano aún pueden escuchar {@code
  CONNECTIVITY_CHANGE} con un {@link
  android.content.BroadcastReceiver} registrado. No obstante, la API {@link
  android.net.ConnectivityManager} ofrece un método más robusto para solicitar
  un callback solo cuando se cumplen las condiciones de red especificadas.
</p>

<p>
  Los objetos {@link android.net.NetworkRequest} definen los parámetros del
  callback de la red en términos de {@link android.net.NetworkCapabilities}. Creas
  objetos {@link android.net.NetworkRequest} con la clase {@link
  android.net.NetworkRequest.Builder NetworkRequest.Builder}. {@link
  android.net.ConnectivityManager#registerNetworkCallback(android.net.NetworkRequest,
  android.net.ConnectivityManager.NetworkCallback) registerNetworkCallback()}
  y luego pasa el objeto {@link android.net.NetworkRequest} al sistema. Cuando
  se cumplen las condiciones de la red, la aplicación recibe un callback para ejecutar el método
  {@link android.net.ConnectivityManager.NetworkCallback#onAvailable
  onAvailable()} definido en su clase {@link
  android.net.ConnectivityManager.NetworkCallback}.
</p>

<p>
  La aplicación continuará recibiendo callbacks hasta que la aplicación salga o llame a
  {@link android.net.ConnectivityManager#unregisterNetworkCallback
  unregisterNetworkCallback()}.
</p>

<h2 id="media-broadcasts">
  Restricciones en NEW_PICTURE y NEW_VIDEO
</h2>

<p>
  En la N Developer Preview, las aplicaciones no pueden enviar ni recibir difusiones {@link
  android.hardware.Camera#ACTION_NEW_PICTURE} ni {@link
  android.hardware.Camera#ACTION_NEW_VIDEO}. Esta restricción ayuda a
  aliviar el impacto en el rendimiento y la experiencia de usuario cuando varias aplicaciones deben
  activarse para procesar una nueva imagen o video. La N Developer Preview
  extiende {@link android.app.job.JobInfo} y {@link
  android.app.job.JobParameters} para proporcionar una solución alternativa.
</p>

<h3 id="new-jobinfo">
  Nuevos métodos de JobInfo
</h3>

<p>
  Para activar trabajos en los cambios del URI de contenido, la N Developer Preview amplía
  la API {@link android.app.job.JobInfo} con los siguientes métodos:
</p>

<dl>
  <dt>
    {@code JobInfo.TriggerContentUri()}
  </dt>

  <dd>
    Encapsula parámetros necesarios para activar un trabajo en cambios del URI de contenido.
  </dd>

  <dt>
    {@code JobInfo.Builder.addTriggerContentUri()}
  </dt>

  <dd>
    Pasa un objeto {@code TriggerContentUri} a {@link
    android.app.job.JobInfo}. Un {@link android.database.ContentObserver}
    controla el URI de contenido encapsulado. Si hay múltiples objetos {@code
    TriggerContentUri} asociados a un trabajo, el sistema proporciona un
    callback aunque se informe un cambio en un solo URI de contenido.
  </dd>

  <dd>
    Si cambia algún desencadenante del URI determinado, agrega el marcador {@code TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS} para
    activar el trabajo. Este marcador
    corresponde al parámetro {@code notifyForDescendants} pasado a {@link
    android.content.ContentResolver#registerContentObserver
    registerContentObserver()}.
  </dd>
</dl>

<p class="note">
  <strong>Nota:</strong> no se puede usar {@code TriggerContentUri()} junto
  con {@link android.app.job.JobInfo.Builder#setPeriodic
  setPeriodic()} ni {@link android.app.job.JobInfo.Builder#setPersisted
  setPersisted()}. Para controlar de forma constante la presencia de cambios, programa un nuevo
  {@link android.app.job.JobInfo} antes de que el {@link
  android.app.job.JobService} de la aplicación termine de administrar la callback más reciente.
</p>

<p>
  El siguiente código de ejemplo programa la activación de un trabajo cuando el sistema informe
  un cambio en el URI de contenido, {@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>
  Cuando el sistema informa un cambio en el(los) URI de contenido especificado(s), tu aplicación
  recibe un callback y se pasa un objeto {@link android.app.job.JobParameters} 
  al método {@link android.app.job.JobService#onStartJob onStartJob()}
  en {@code MediaContentJob.class}.
</p>

<h3 id="new-jobparam">
  Nuevos métodos de JobParameter
</h3>

<p>
  La N Developer Preview también amplía {@link android.app.job.JobParameters} para
  permitir que tu aplicación reciba información útil sobre qué autoridades de contenido
  y URI activaron el trabajo:
</p>

<dl>
  <dt>
    {@code Uri[] getTriggeredContentUris()}
  </dt>

  <dd>
    Devuelve el arreglo de los URI que activaron el trabajo. Ese arreglo será {@code
    null} si ningún URI activó el trabajo (por ejemplo, el trabajo
    se activó debido al cumplimiento de un plazo o por otro motivo), o la cantidad de URI
    modificados es superior a 50.
  </dd>

  <dt>
    {@code String[] getTriggeredContentAuthorities()}
  </dt>

  <dd>
    Devuelve el arreglo de cadenas de autoridades de contenido que activaron el trabajo.
    Si el arreglo devuelto no es {@code null}, usa {@code getTriggeredContentUris()}
    para recuperar los detalles de los URI que se modificaron.
  </dd>
</dl>

<p>
  El siguiente código de ejemplo anula el método {@link
  android.app.job.JobService#onStartJob JobService.onStartJob()} y
  registra las autoridades de contenido y los URI que activaron el trabajo:
</p>

<pre>
&#64;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">
  Cómo optimizar aún más tu aplicación
</h2>

<p>
  Optimizar tus aplicaciones para que se ejecuten en dispositivos con poca memoria o en condiciones de niveles bajos
  de memoria puede mejorar el rendimiento y la experiencia del usuario. Eliminar
  dependencias en servicios en segundo plano y receptores de difusiones implícitas
  registrados estadísticamente puede ayudar a que tu aplicación se ejecute mejor en esos dispositivos. Si bien
  la N Developer Preview toma medidas para reducir algunos de esos problemas, te
  recomendamos que optimices tu aplicación para que pueda ejecutarse sin utilizar esos
  procesos en segundo plano.
</p>

<p>
  La N Developer Preview presenta algunos comandos adicionales de <a href="{@docRoot}tools/help/adb.html">Puente de Depuración Android (en inglés, Android Debug Bridge, ADB)</a> que
  puedes usar para probar el comportamiento de la aplicación con esos procesos en segundo plano deshabilitados:
</p>

<ul>
  <li>Para simular condiciones en las que no hay difusiones implícitas ni servicios en segundo plano
  disponibles, ingresa el siguiente 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 volver a habilitar las difusiones implícitas y los servicios en segundo plano, ingresa el
  siguiente 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>