Spanish (Español) translation by Andrea J (you can also view the original English article)
En este tutorial, aprenderás a usar la API JobScheduler
disponible en Android Lollipop. La API JobScheduler
permite que los desarrolladores creen tareas que se ejecuten en segundo plano cuando se cumplen determinadas condiciones.
Introducción
Cuando trabajes con Android, habrá ocasiones en las que querrás ejecutar una tarea en un momento determinado o en ciertas condiciones, como cuando un dispositivo está conectado a una fuente de energía o conectado a una red Wi-Fi. Afortunadamente con API 21, conocido por la mayoría de la gente como Android Lollipop, Google ha proporcionado un nuevo componente conocido como la API JobScheduler
para manejar este mismo escenario.
La API JobScheduler
realiza una operación en tu aplicación cuando se cumple un conjunto de condiciones predefinidas. A diferencia de la clase AlarmManager
, la sincronización no es exacta. Además, la API JobScheduler
puede agrupar varias tareas para ejecutarlas juntas. Esto permite que tu aplicación realice la tarea dada sin dejar de considerar la batería del dispositivo a costa del temporizador.
En este artículo, aprenderás más sobre la API JobScheduler
y la clase JobService
utilizándolas para ejecutar una tarea sencilla en segundo plano en una aplicación de Android. El código de este tutorial está disponible en GitHub.
1. Creación del servicio de tareas
Para empezar, querrás crear un nuevo proyecto de Android con una API mínima requerida de 21, porque la API JobScheduler
se agregó en la versión más reciente de Android y, en el momento de escribir este artículo, no es compatible con versiones anteriores a través de una biblioteca de apoyo.
Después de haber pulsado el botón de terminar en el nuevo proyecto, deberías tener una aplicación básica "Hello World". Esto, suponiendo que estás utilizando Android Studio. El primer paso que vas a dar en este proyecto es crear una nueva clase Java. Para simplificar las cosas, vamos a nombrarla JobSchedulerService y extendemos la clase JobService
, la cual requiere que se creen dos métodos onStartJob(JobParameters params)
y onStopJob(JobParameters params)
.
public class JobSchedulerService extends JobService { @Override public boolean onStartJob(JobParameters params) { return false; } @Override public boolean onStopJob(JobParameters params) { return false; } }
onStartJob(JobParameters params)
es el método que debes usar cuando inicies tu tarea, porque es lo que el sistema utiliza para activar las tareas que ya se han programado. Como puedes ver, el método retorna un valor booleano. Si el valor que retornó es false
, el sistema asume que cualquier tarea que se haya ejecutado no tomó mucho tiempo y está lista para cuando el método regrese. Si el valor devuelto es true
, el sistema asume que la tarea va a tardar algún tiempo y la carga recae sobre tí, el desarrollador, para indicarle al sistema cuando se completa la tarea dada llamando al método jobFinished(JobParameters params, boolean needsRescheduled
.
el sistema utiliza el método onStopJob(JobParameters params)
para cancelar las tareas pendientes cuando se recibe una solicitud de cancelación. Es importante tener en cuenta que si el método onStartJob(JobParameters params)
retorna false
, el sistema asume que no hay tareas en ejecución cuando se recibe una solicitud de cancelación. En otras palabras, simplemente no llamará a onStopJob(JobParameters params)
.
Una cosa a tener en cuenta es que el servicio de tareas se ejecuta en el subproceso principal de tu aplicación. Esto significa que debes usar otro subproceso, un controlador o una tarea asincrónica para ejecutar las tareas más largas y no bloquear el subproceso principal. Dado que las técnicas de multiprocesos están fuera del alcance de este tutorial, hagámoslo simple e implementemos un controlador para ejecutar nuestra tarea en la clase JobSchedulerService
.
private Handler mJobHandler = new Handler( new Handler.Callback() { @Override public boolean handleMessage( Message msg ) { Toast.makeText( getApplicationContext(), "JobService task running", Toast.LENGTH_SHORT ) .show(); jobFinished( (JobParameters) msg.obj, false ); return true; } } );
En el controlador, implementa el método handleMessage(Message msg)
que es parte de la instancia Handler
y hace que ejecute la lógica de tu tarea. En este caso, mantendremos las cosas muy simples y publicaremos un mensaje Toast
desde la aplicación, aunque aquí es donde pondrías tu lógica para cosas como la sincronización de datos.
Cuando la tarea está finalizada, debes llamar a jobFinished(JobParameters params, boolean needsRescheduled)
para que el sistema sepa que has terminado con esa tarea y que puede comenzar a poner en cola la próxima operación. Si no lo haces, tus tareas solo se ejecutarán una vez y tu aplicación no podrá realizar las tareas adicionales.
Los dos parámetros que toma el método jobFinished(JobParameters params, boolean needsRescheduled)
son los JobParameters
que se pasaron a la clase JobService
en el método onStartJob(JobParameters params)
y un valor booleano que le permite al sistema saber si debe reprogramar la tarea basado en los requisitos originales de la tarea. Es conveniente entender el valor booleano, porque es la forma como manejas las situaciones en las que tu tarea no puede completarse debido a otros problemas, como una llamada de red fallida.
Con la instancia de Handler
creada, puedes continuar y empezar a implementar los métodos onStartJob(JobParameters params)
y onStopJob(JobParameters params)
para controlar las tareas. Notarás que en el siguiente fragmento de código, el método onStartJob(JobParameters params)
retorna true
. Esto se debe a que vas a usar una instancia de Handler
para controlar tu operación, lo que significa que podría tardar más tiempo en finalizar que el método onStartJob(JobParameters params)
. Al retornar true
, le estás haciendo saber a la aplicación que llamarás manualmente al método jobFinished(JobParameters params, boolean needsRescheduled)
. También observarás que el número 1
se pasa a la instancia de Handler
. Este es el identificador que usarás para hacer referencia a la tarea.
@Override public boolean onStartJob(JobParameters params) { mJobHandler.sendMessage( Message.obtain( mJobHandler, 1, params ) ); return true; } @Override public boolean onStopJob(JobParameters params) { mJobHandler.removeMessages( 1 ); return false; }
Una vez que hayas terminado con la parte de Java de la clase JobSchedulerService
, debes ingresar a AndroidManifest.xml y agregar un nodo para el servicio y que tu aplicación tenga permiso para enlazar y usar esta clase como JobService
.
<service android:name=".JobSchedulerService" android:permission="android.permission.BIND_JOB_SERVICE" />
2. Creación de tareas programadas
Con la clase JobSchedulerService
finalizada, podemos comenzar a ver cómo interactuará tu aplicación con la API JobScheduler
. Lo primero que tendrás que hacer es crear un objeto JobScheduler
, llamado mJobScheduler
en el código de ejemplo, e inicializarlo obteniendo una instancia del servicio del sistema JOB_SCHEDULER_SERVICE
. En la aplicación de ejemplo, esto se realiza en la clase MainActivity
.
mJobScheduler = (JobScheduler) getSystemService( Context.JOB_SCHEDULER_SERVICE );
Cuando quieras crear tu tarea programada, puedes usar la clase JobInfo.Builder
para construir un objeto JobInfo
que se pasa a tu servicio. Para crear un objeto JobInfo
, JobInfo.Builder
acepta dos parámetros. El primero es el identificador de las tareas que ejecutarás y el segundo es el nombre del componente del servicio que usarás con la API JobScheduler
.
JobInfo.Builder builder = new JobInfo.Builder( 1, new ComponentName( getPackageName(), JobSchedulerService.class.getName() ) );
Este generador te permite establecer muchas opciones diferentes para controlar cuándo se ejecutarán las tareas. El siguiente fragmento de código te muestra cómo puedes configurar tu tarea para que se ejecute periódicamente cada tres segundos.
builder.setPeriodic( 3000 );
Otros métodos son:
-
setMinimumLatency(long minLatencyMillis)
: Esta función hace que tu tarea no se inicie hasta que haya pasado el número de milisegundos indicado. Esta es incompatible con la funciónsetPeriodic(long time)
y hará que se produzca una excepción si se usan ambos. -
setOverrideDeadline(long maxExecutionDelayMillis)
: Esta función establecerá una fecha límite en tu tarea. Incluso si no se cumplen otros requisitos, tu tarea se iniciará aproximadamente cuando haya transcurrido el tiempo indicado. Al igual que la funciónsetMinimumLatency(long time)
, esta función es incompatible consetPeriodic(long time)
y hará que se produzca una excepción si se usan ambas.
-
setPersisted(boolean isPersisted)
: Esta función le indica al sistema si la tarea debe seguir existiendo después de reiniciar el dispositivo.
-
setRequiredNetworkType(int networkType)
: esta función le indicará a tu tarea que solo se puede iniciar si el dispositivo está en un tipo de red específico. El valor predeterminado esJobInfo.NETWORK_TYPE_NONE
, lo que significa que la tarea puede ejecutarse tanto si hay conectividad de red como si no la hay. Los otros dos tipos disponibles sonJobInfo.NETWORK_TYPE_ANY
, que requiere algún tipo de conexión de red disponible para que las tareas se ejecuten, yJobInfo.NETWORK_TYPE_UNMETERED
, que requiere que el dispositivo esté en una red que no sea móvil.
-
setRequiresCharging(boolean requiresCharging
: El uso de esta función le indicará a tu aplicación que las tareas no deben iniciarse hasta que el dispositivo haya comenzado a cargarse.
-
setRequiresDeviceIdle(boolean requiresDeviceIdle)
: Esta función le indica a tu tarea que no se inicie a menos que el usuario no esté usando su dispositivo y no lo haya utilizado durante algún tiempo.
Es importante tener en cuenta que las funciones setRequiredNetworkType(int networkType)
, setRequiresCharging(boolean requireCharging)
y setRequiresDeviceIdle(boolean requireIdle)
pueden hacer que tus tareas nunca se inicien a menos que la función setOverrideDeadline(long time)
también esté establecida, lo que permite que tus tareas se ejecuten incluso si no se cumplen las condiciones. Una vez que se establecen las condiciones preferidas, puedes crear el objeto JobInfo
y enviarlo a tu objeto JobScheduler
de la siguiente manera.
if( mJobScheduler.schedule( builder.build() ) <= 0 ) { //If something goes wrong }
Notarás que la operación schedule
retorna un entero. Si se produce un error en el schedule
, devolverá un valor de cero o menos, correspondiente a un código de error. De lo contrario, retornará el identificador de tareas que definimos en JobInfo.Builder
.
Si tu aplicación requiere que detengas una tarea en específico o todas, puedes hacerlo llamando a cancel(int jobId)
o cancelAll()
en el objeto JobScheduler
.
mJobScheduler.cancelAll();
Ahora deberías poder usar la API JobScheduler
con tus propias aplicaciones para realizar tareas por lotes y ejecutar operaciones en segundo plano.
Conclusión
En este artículo, aprendiste a implementar una subclase JobService
que usa un objeto Handler
para ejecutar tareas en segundo plano en tu aplicación. También aprendiste a usar JobInfo.Builder
para establecer los requisitos sobre cuándo debe ejecutarse el servicio. Con estas clases, deberías poder mejorar el funcionamiento de tus propias aplicaciones siendo consciente del consumo de energía.
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post