| page.title=Optimizaciones en segundo plano |
| page.metaDescription=Nuevas restricciones para transmisiones 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> |
| En este 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 de uso</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 |
| transmisió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 corregir este problema, en Android N se aplican las siguientes |
| restricciones: |
| </p> |
| |
| <ul> |
| <li>Las aplicaciones orientadas a la Preview no reciben transmisiones {@link |
| android.net.ConnectivityManager#CONNECTIVITY_ACTION} si |
| en su manifiesto registran que las reciben. Las aplicaciones que se ejecutan aún pueden |
| escuchar {@code CONNECTIVITY_CHANGE} en su subproceso principal mediante el registro de un |
| {@link android.content.BroadcastReceiver} con {@link |
| android.content.Context#registerReceiver Context.registerReceiver()}. |
| </li> |
| |
| <li>Las aplicaciones no pueden enviar ni recibir transmisiones {@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 aquellas orientadas a la Preview. |
| </li> |
| </ul> |
| |
| <p> |
| Si la aplicación utiliza cualquiera de estas intents, debes quitar las dependencias en |
| ellas lo antes posible a fin de poder orientar los dispositivos Android N correctamente. |
| El framework de Android ofrece varias soluciones para mitigar la necesidad de |
| estas transmisiones 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 Android N no reciben transmisiones {@link |
| android.net.ConnectivityManager#CONNECTIVITY_ACTION} si en su manifiesto |
| registran que las reciben, y los procesos que dependan de esta |
| transmisión no se iniciará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 estas transmisiones mientras se ejecuta la aplicación. |
| </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 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 Android N, las aplicaciones no pueden enviar ni recibir transmisiones {@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. Android N |
| 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, Android N extiende |
| 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 en el contenido, 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(MediaStore.Images.Media.EXTERNAL_CONTENT_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> |
| Android N 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> |
| @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 transmisiones implícitas |
| registrados estadísticamente puede ayudar a que tu aplicación se ejecute mejor en esos dispositivos. Si bien |
| Android N toma medidas para reducir algunos de estos problemas, te |
| recomendamos que optimices tu aplicación para que pueda ejecutarse sin utilizar esos |
| procesos en segundo plano. |
| </p> |
| |
| <p> |
| Android N presenta algunos comandos adicionales de <a href="{@docRoot}tools/help/adb.html">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 transmisiones 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 <package> RUN_IN_BACKGROUND ignore} |
| </pre> |
| </li> |
| |
| <li>Para volver a habilitar las transmisiones 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 <package> RUN_IN_BACKGROUND allow} |
| </pre> |
| </li> |
| </ul> |