1page.title=Optimizaciones en segundo plano
2page.metaDescription=Nuevas restricciones para transmisiones 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      En este documento
12    </h2>
13
14    <ol>
15      <li>
16        <a href="#connectivity-action">Restricciones en CONNECTIVITY_ACTION</a>
17      </li>
18
19      <li>
20        <a href="#sched-jobs">Programación de trabajos en red en conexiones
21        sin medición de uso</a>
22      </li>
23
24      <li>
25        <a href="#monitor-conn">Control de la conectividad de la red mientras la aplicación
26        se está ejecutando</a>
27      </li>
28
29      <li>
30        <a href="#media-broadcasts">Restricciones en NEW_PICTURE y
31        NEW_VIDEO</a>
32      </li>
33
34      <li>
35        <a href="#new-jobinfo">Nuevos métodos de JobInfo</a>
36      </li>
37
38      <li>
39        <a href="#new-jobparam">Nuevos métodos de JobParameter</a>
40      </li>
41
42      <li>
43        <a href="#further-optimization">Cómo optimizar aún más tu aplicación</a>
44      </li>
45    </ol>
46  </div>
47</div>
48
49<p>
50  Los procesos en segundo plano pueden consumir mucha memoria y batería. Por ejemplo, una
51  transmisión implícita puede iniciar muchos procesos en segundo plano registrados para
52  escucharla, aunque esos procesos quizá no desempeñen un trabajo considerable. Esto puede
53 afectar de forma significativa tanto el rendimiento del dispositivo como la experiencia de usuario.
54</p>
55
56<p>
57  Para corregir este problema, en Android N se aplican las siguientes
58 restricciones:
59</p>
60
61<ul>
62  <li>Las aplicaciones orientadas a la Preview no reciben transmisiones {@link
63  android.net.ConnectivityManager#CONNECTIVITY_ACTION} si
64 en su manifiesto registran que las reciben. Las aplicaciones que se ejecutan aún pueden
65 escuchar {@code CONNECTIVITY_CHANGE} en su subproceso principal mediante el registro de un
66 {@link android.content.BroadcastReceiver} con {@link
67  android.content.Context#registerReceiver Context.registerReceiver()}.
68  </li>
69
70  <li>Las aplicaciones no pueden enviar ni recibir transmisiones {@link
71  android.hardware.Camera#ACTION_NEW_PICTURE} ni {@link
72  android.hardware.Camera#ACTION_NEW_VIDEO}. Esta optimización
73 afecta a todas las aplicaciones, no solo a aquellas orientadas a la Preview.
74  </li>
75</ul>
76
77<p>
78  Si la aplicación utiliza cualquiera de estas intents, debes quitar las dependencias en
79 ellas lo antes posible a fin de poder orientar los dispositivos Android N correctamente.
80  El framework de Android ofrece varias soluciones para mitigar la necesidad de
81  estas transmisiones implícitas. Por ejemplo, {@link android.app.job.JobScheduler}
82  y <a href="https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
83  {@code GcmNetworkManager}</a> proporcionan mecanismos sólidos para programar operaciones
84  de red cuando se cumplen las condiciones especificadas, como una conexión a una
85  red de uso no medido. Ahora también puedes usar {@link android.app.job.JobScheduler}
86  para reaccionar a cambios en relación con los proveedores de contenido. Los objetos {@link android.app.job.JobInfo}
87  encapsulan los parámetros que usa {@link android.app.job.JobScheduler}
88  para programar el trabajo. Cuando se cumplen las condiciones del trabajo, el sistema
89  ejecuta ese trabajo en el {@link android.app.job.JobService} de tu aplicación.
90</p>
91
92<p>
93  En este documento, aprenderemos cómo usar métodos alternativos, como
94  {@link android.app.job.JobScheduler}, para adaptar tu aplicación a esas nuevas
95  restricciones.
96</p>
97
98<h2 id="connectivity-action">
99  Restricciones en CONNECTIVITY_ACTION
100</h2>
101
102<p>
103  Las aplicaciones orientadas a Android N no reciben transmisiones {@link
104  android.net.ConnectivityManager#CONNECTIVITY_ACTION} si en su manifiesto
105 registran que las reciben, y los procesos que dependan de esta
106 transmisión no se iniciarán. Esto podría ser un problema para aplicaciones que buscan
107 escuchar los cambios en la red o realizar múltiples actividades en red cuando el
108 dispositivo se conecta a una red sin medición de uso. Ya existen varias soluciones
109  en relación con esta restricción en el framework de Android, pero elegir
110  la correcta depende de lo que quieras lograr con tu aplicación.
111</p>
112
113<p class="note">
114  <strong>Nota:</strong> Un {@link android.content.BroadcastReceiver} registrado con
115 {@link android.content.Context#registerReceiver Context.registerReceiver()}
116 continúa recibiendo estas transmisiones mientras se ejecuta la aplicación.
117</p>
118
119<h3 id="sched-jobs">
120  Programación de trabajos en red en conexiones sin medición de uso
121</h3>
122
123<p>
124  Cuando uses la clase {@link android.app.job.JobInfo.Builder JobInfo.Builder}
125  para crear tu objeto {@link android.app.job.JobInfo}, aplica el método {@link
126  android.app.job.JobInfo.Builder#setRequiredNetworkType
127  setRequiredNetworkType()} y pasa {@link android.app.job.JobInfo
128  JobInfo.NETWORK_TYPE_UNMETERED} como parámetro de trabajo. El siguiente ejemplo de código
129  programa la ejecución de un servicio cuando el dispositivo se conecta a una red sin
130  medición de uso y se está cargando:
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  Cuando se cumplan las condiciones para tu trabajo, tu aplicación recibirá un callback para ejecutar
151  el método {@link android.app.job.JobService#onStartJob onStartJob()} en la
152   {@code JobService.class} especificada. Para ver más ejemplos de la implementación de {@link
153  android.app.job.JobScheduler}, consulta la <a href="{@docRoot}samples/JobScheduler/index.html">aplicación de ejemplo JobScheduler</a>.
154</p>
155
156<p>
157  Las aplicaciones que usan servicios de GMSCore y están orientadas a Android 5.0 (API nivel 21)
158  o anterior, pueden usar <a href="https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
159  {@code GcmNetworkManager}</a> y especificar {@code Task.NETWORK_STATE_UNMETERED}.
160</p>
161
162<h3 id="monitor-conn">
163  Control de la conectividad de la red mientras la aplicación se está ejecutando
164</h3>
165
166<p>
167  Las aplicaciones que se ejecutan aún pueden escuchar {@code CONNECTIVITY_CHANGE} con un
168 {@link android.content.BroadcastReceiver} registrado. No obstante, la API {@link
169  android.net.ConnectivityManager} ofrece un método más robusto para solicitar
170 un callback solo cuando se cumplen las condiciones de red especificadas.
171</p>
172
173<p>
174  Los objetos {@link android.net.NetworkRequest} definen los parámetros del
175  callback de la red en términos de {@link android.net.NetworkCapabilities}. Creas
176  objetos {@link android.net.NetworkRequest} con la clase {@link
177  android.net.NetworkRequest.Builder NetworkRequest.Builder}. {@link
178  android.net.ConnectivityManager#registerNetworkCallback(android.net.NetworkRequest,
179  android.net.ConnectivityManager.NetworkCallback) registerNetworkCallback()}
180  y luego pasa el objeto {@link android.net.NetworkRequest} al sistema. Cuando
181  se cumplen las condiciones de la red, la aplicación recibe un callback para ejecutar el método
182  {@link android.net.ConnectivityManager.NetworkCallback#onAvailable
183  onAvailable()} definido en su clase {@link
184  android.net.ConnectivityManager.NetworkCallback}.
185</p>
186
187<p>
188  La aplicación continuará recibiendo callbacks hasta que la aplicación salga o llame a
189  {@link android.net.ConnectivityManager#unregisterNetworkCallback
190  unregisterNetworkCallback()}.
191</p>
192
193<h2 id="media-broadcasts">
194  Restricciones en NEW_PICTURE y NEW_VIDEO
195</h2>
196
197<p>
198  En Android N, las aplicaciones no pueden enviar ni recibir transmisiones {@link
199  android.hardware.Camera#ACTION_NEW_PICTURE} ni {@link
200  android.hardware.Camera#ACTION_NEW_VIDEO}. Esta restricción ayuda a
201 aliviar el impacto en el rendimiento y la experiencia de usuario cuando varias aplicaciones deben
202 activarse para procesar una nueva imagen o video. Android N
203 extiende {@link android.app.job.JobInfo} y {@link
204  android.app.job.JobParameters} para proporcionar una solución alternativa.
205</p>
206
207<h3 id="new-jobinfo">
208  Nuevos métodos de JobInfo
209</h3>
210
211<p>
212  Para activar trabajos en los cambios del URI de contenido, Android N extiende
213 la API {@link android.app.job.JobInfo} con los siguientes métodos:
214</p>
215
216<dl>
217  <dt>
218    {@code JobInfo.TriggerContentUri()}
219  </dt>
220
221  <dd>
222    Encapsula parámetros necesarios para activar un trabajo en cambios del URI de contenido.
223  </dd>
224
225  <dt>
226    {@code JobInfo.Builder.addTriggerContentUri()}
227  </dt>
228
229  <dd>
230    Pasa un objeto {@code TriggerContentUri} a {@link
231    android.app.job.JobInfo}. Un {@link android.database.ContentObserver}
232    controla el URI de contenido encapsulado. Si hay múltiples objetos {@code
233    TriggerContentUri} asociados a un trabajo, el sistema proporciona un
234    callback aunque se informe un cambio en un solo URI de contenido.
235  </dd>
236
237  <dd>
238    Si cambia algún desencadenante del URI determinado, agrega el marcador {@code TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS} para
239    activar el trabajo. Este marcador
240    corresponde al parámetro {@code notifyForDescendants} pasado a {@link
241    android.content.ContentResolver#registerContentObserver
242    registerContentObserver()}.
243  </dd>
244</dl>
245
246<p class="note">
247  <strong>Nota:</strong> No se puede usar {@code TriggerContentUri()} junto
248  con {@link android.app.job.JobInfo.Builder#setPeriodic
249  setPeriodic()} ni {@link android.app.job.JobInfo.Builder#setPersisted
250  setPersisted()}. Para controlar de forma constante la presencia de cambios en el contenido, programa un nuevo
251  {@link android.app.job.JobInfo} antes de que el {@link
252  android.app.job.JobService} de la aplicación termine de administrar la callback más reciente.
253</p>
254
255<p>
256  El siguiente código de ejemplo programa la activación de un trabajo cuando el sistema informe
257  un cambio en el URI de contenido, {@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  Cuando el sistema informa un cambio en el(los) URI de contenido especificado(s), tu aplicación
277  recibe un callback y se pasa un objeto {@link android.app.job.JobParameters}
278  al método {@link android.app.job.JobService#onStartJob onStartJob()}
279  en {@code MediaContentJob.class}.
280</p>
281
282<h3 id="new-jobparam">
283  Nuevos métodos de JobParameter
284</h3>
285
286<p>
287  Android N también amplía {@link android.app.job.JobParameters} para
288 permitir que tu aplicación reciba información útil sobre qué autoridades de contenido
289 y URI activaron el trabajo:
290</p>
291
292<dl>
293  <dt>
294    {@code Uri[] getTriggeredContentUris()}
295  </dt>
296
297  <dd>
298    Devuelve el arreglo de los URI que activaron el trabajo. Ese arreglo será {@code
299    null} si ningún URI activó el trabajo (por ejemplo, el trabajo
300    se activó debido al cumplimiento de un plazo o por otro motivo), o la cantidad de URI
301    modificados es superior a 50.
302  </dd>
303
304  <dt>
305    {@code String[] getTriggeredContentAuthorities()}
306  </dt>
307
308  <dd>
309    Devuelve el arreglo de cadenas de autoridades de contenido que activaron el trabajo.
310    Si el arreglo devuelto no es {@code null}, usa {@code getTriggeredContentUris()}
311    para recuperar los detalles de los URI que se modificaron.
312  </dd>
313</dl>
314
315<p>
316  El siguiente código de ejemplo anula el método {@link
317  android.app.job.JobService#onStartJob JobService.onStartJob()} y
318  registra las autoridades de contenido y los URI que activaron el trabajo:
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  Cómo optimizar aún más tu aplicación
354</h2>
355
356<p>
357  Optimizar tus aplicaciones para que se ejecuten en dispositivos con poca memoria o en condiciones de niveles bajos
358  de memoria puede mejorar el rendimiento y la experiencia del usuario. Eliminar
359 dependencias en servicios en segundo plano y receptores de transmisiones implícitas
360 registrados estadísticamente puede ayudar a que tu aplicación se ejecute mejor en esos dispositivos. Si bien
361 Android N toma medidas para reducir algunos de estos problemas, te
362 recomendamos que optimices tu aplicación para que pueda ejecutarse sin utilizar esos
363 procesos en segundo plano.
364</p>
365
366<p>
367  Android N presenta algunos comandos adicionales de <a href="{@docRoot}tools/help/adb.html">Android Debug Bridge (ADB)</a> que
368 puedes usar para probar el comportamiento de la aplicación con esos procesos en segundo plano deshabilitados:
369</p>
370
371<ul>
372  <li>Para simular condiciones en las que no hay transmisiones implícitas ni servicios en segundo plano
373 disponibles, ingresa el siguiente 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 volver a habilitar las transmisiones implícitas y los servicios en segundo plano, ingresa el
383  siguiente 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