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@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 <package> 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 <package> RUN_IN_BACKGROUND allow} 389</pre> 390 </li> 391</ul> 392