jobscheduler example java android android-jobscheduler

java - jobscheduler android example



Android JobScheduler ejecutando varias veces (2)

Estoy usando el siguiente código para crear y programar un trabajo utilizando la API de Androids JobScheduler:

Log.d("hanif", "Scheduling periodic job 2 hrs with 20 mins backoff linear"); JobInfo jobInfo = new JobInfo.Builder(JOB_ID, new ComponentName(getApplicationContext(), MyJobService.class)) .setPeriodic(TimeUnit.HOURS.toMillis(2)) .setRequiresCharging(true) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) .setBackoffCriteria(TimeUnit.MINUTES.toMillis(20), JobInfo.BACKOFF_POLICY_LINEAR) .build(); JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); scheduler.schedule(jobInfo);

Es decir, un trabajo periódico que se ejecuta cada 2 horas y una política de anulación lineal que ejecuta un número de 20 min * falla en caso de que el trabajo falle.

El código de mi servicio de trabajo se escribe a continuación:

public class MyJobService extends JobService { @Override public boolean onStartJob(JobParameters jobParameters) { Log.d("hanif", "onStartJob"); new MyWorker(getApplicationContext(), this, jobParameters).execute(); return true; } @Override public boolean onStopJob(JobParameters jobParameters) { Log.d("hanif", "onStopJob"); return true; } private static class MyWorker extends AsyncTask<Void, Void, Boolean> { private final Context mContext; private final MyJobService mJobService; private final JobParameters mJobParams; public MyWorker(Context context, MyJobService myJobService, JobParameters jobParameters) { mContext = context; mJobService = myJobService; mJobParams = jobParameters; } @Override protected Boolean doInBackground(Void... voids) { Log.d("hanif", "Work start!"); for (int i=0; i<999999999; i++) {} int counter = Prefs.getCounter(mContext); Log.d("hanif", "Work done! counter: " + counter); if (counter == 3) { Log.d("hanif", "DO RESCHEDULE"); Prefs.resetCounter(mContext); return true; } Log.d("hanif", "DO NOT RESCHEDULE"); Prefs.increaseCounter(mContext); return false; } @Override public void onPostExecute(Boolean reschedule) { if (reschedule) { mJobService.jobFinished(mJobParams, true); } else { mJobService.jobFinished(mJobParams, false); } Log.d("hanif", "------------------------------------------"); } } }

Y, finalmente, la salida del registro es la siguiente:

03-27 12:57:11.677 7383 7383 D hanif : Scheduling periodic job 2 hrs with 20 mins backoff linear 03-27 12:57:31.904 7383 7383 D hanif : onStartJob 03-27 12:57:31.909 7383 8623 D hanif : Work start! 03-27 12:57:42.110 7383 8623 D hanif : Work done! counter: 0 03-27 12:57:42.111 7383 8623 D hanif : DO NOT RESCHEDULE 03-27 12:57:42.125 7383 7383 D hanif : ------------------------ 03-27 14:58:50.786 7383 7383 D hanif : onStartJob 03-27 14:58:50.789 7383 21490 D hanif : Work start! 03-27 14:59:00.952 7383 21490 D hanif : Work done! counter: 1 03-27 14:59:00.953 7383 21490 D hanif : DO NOT RESCHEDULE 03-27 14:59:00.962 7383 7383 D hanif : ------------------------ 03-27 16:57:12.021 7383 7383 D hanif : onStartJob 03-27 16:57:12.045 7383 32028 D hanif : Work start! 03-27 16:57:22.229 7383 32028 D hanif : Work done! counter: 2 03-27 16:57:22.230 7383 32028 D hanif : DO NOT RESCHEDULE 03-27 16:57:22.238 7383 7383 D hanif : ------------------------ 03-27 18:57:11.984 7383 7383 D hanif : onStartJob 03-27 18:57:11.989 7383 13217 D hanif : Work start! 03-27 18:57:22.123 7383 13217 D hanif : Work done! counter: 3 03-27 18:57:22.124 7383 13217 D hanif : DO RESCHEDULE 03-27 18:57:22.130 7383 7383 D hanif : ------------------------ 03-27 19:20:57.468 7383 7383 D hanif : onStartJob 03-27 19:20:57.482 7383 1913 D hanif : Work start! 03-27 19:21:07.723 7383 1913 D hanif : Work done! counter: 0 03-27 19:21:07.724 7383 1913 D hanif : DO NOT RESCHEDULE 03-27 19:21:07.733 7383 7383 D hanif : ------------------------ 03-27 19:21:57.669 7383 7383 D hanif : onStartJob <--- Why is this called again? 03-27 19:21:57.675 7383 3025 D hanif : Work start! 03-27 19:22:07.895 7383 3025 D hanif : Work done! counter: 1 03-27 19:22:07.896 7383 3025 D hanif : DO NOT RESCHEDULE 03-27 19:22:07.906 7383 7383 D hanif : ------------------------ 03-27 21:40:53.419 7383 7383 D hanif : onStartJob 03-27 21:40:53.423 7383 31526 D hanif : Work start! 03-27 21:41:03.857 7383 31526 D hanif : Work done! counter: 2 03-27 21:41:03.858 7383 31526 D hanif : DO NOT RESCHEDULE 03-27 21:41:03.867 7383 7383 D hanif : ------------------------

¿Por qué se llama a onStartJob dos veces?


Dado que JobScheduler se usará mucho más con Android Oreo, quería describir algunos problemas con el ejemplo:

El método anulado onStopJob() solo devuelve true . Si su trabajo se interrumpe mientras se está procesando, es decir, el cargador está desenchufado o si no hay una red como está configurada en JobInfo, esta función también debe usarse para cancelar inmediatamente la tarea / trabajo. Entonces debería devolver true indica que el trabajo debe ser reprogramado.

MyJobService debe tener una referencia private a la tarea MyWorker . onStartJob() establece. onStopJob() usa para cancelar inmediatamente la tarea.

Por lo general, no es necesario pasar la true para el needsReschedule dentro del método jobFinished() , especialmente cuando se llama dentro de su tarea. Si se interrumpe un trabajo, se llamará a onStopJob () para cancelarlo y devolverlo a verdadero lo reprogramará. Solo he visto un ejemplo here donde needsReschedule se establece en true . Está dentro de onStartJob() y si no se cumple la doble comprobación de las condiciones previas, jobFinished(args, true) y luego return false lugar de true .

¡Espero que esto ayude!


Después de mucha frustración, descubrí qué causa este problema.

No debe llamar a jobFinished(JobParameters, true) en un trabajo periódico. Pasar true para needsReschedule hará que el trabajo se duplique en la cola (se esperaría que sobrescribiera al original, pero aparentemente ese no es el caso). Siempre debe usar jobFinished(JobParameters, false) , incluso si su tarea falla.

En cuanto a si se trata de un uso de API incorrecto o un error de Android, lo dejaré en tus manos.