Перепланирование расписания Android при сбое с помощью jobFinished (параметры, true)

#android #android-jobscheduler

#Android #android-jobscheduler

Вопрос:

У меня возникли проблемы с API планирования заданий на Android, когда моя работа завершается неудачно, я хочу, чтобы она была перенесена в соответствии с ранее установленной политикой отмены.

Создание задания выглядит так :

 try {
    mJobSchedulerServiceComponent = new ComponentName(this.context, JobSchedulerService.class);
    JobInfo.Builder builder = new JobInfo.Builder(Constant.AUTO_UPLOAD_JOB_ID, mJobSchedulerServiceComponent );
    builder.setPersisted(true);
    builder.setRequiresCharging(true);
    builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
    builder.setBackoffCriteria(10000, JobInfo.BACKOFF_POLICY_LINEAR);
    builder.setOverrideDeadline(600 * 1000);
    builder.setMinimumLatency(60 * 1000);
    PersistableBundle bundle = new PersistableBundle();
    bundle.putString("action", Constant.JOB_SCHEDULER_AUTO_UPLOAD);
    bundle.putString("url", Constant.API_URL_SEND_DATA);
    builder.setExtras(bundle);
    if( mJobScheduler.schedule( builder.build() ) <= 0 ) {
        //If something goes wrong
        logger.e(TAG, "Create auto upload job failed");
    }
} catch (Exception e) {
    logger.e(TAG, "createAutoUploadJob error "   e);
}
  

Служба заданий, обрабатывающая задания, выглядит так :

 public class JobSchedulerService extends JobService {
    private Handler handler;
    protected Config config;
    protected Logger logger;
    protected static final String TAG = "MDM-JobSchedulerService";
    private volatile ServiceThread thread = null;


    @Override
    public void onCreate() {
        super.onCreate();
        logger = Logger.getInstance(this);
        logger.d(TAG, "JobSchedulerService start");
        thread = new ServiceThread(this);
        logger.d(TAG, "Starting thread");
        thread.lock.lock();
        thread.start();
        logger.d(TAG, "waiting for init_done");
        try {
            thread.init_done.await();
        }catch (InterruptedException e){
            logger.i(TAG, "Got exception " e.toString());
        }
        logger.d(TAG, "init_done");
        thread.lock.unlock();

    }
    @Override
    public void onDestroy() {
        super.onDestroy();

        logger.i(TAG, "JobSchedulerService destroyed");
    }
    @Override
    public boolean onStartJob(JobParameters params) {
        /*
        * You'll notice that in the following code snippet, the onStartJob(JobParameters params) method returns true.
        * This is because you're going to use a Handler instance to control your operation, which means that it could
        * take longer to finish than the onStartJob(JobParameters params) method. By returning true, you're letting
        * the application know that you will manually call the jobFinished(JobParameters params, boolean needsRescheduled) method
        * */
        if (handler != null) {
            handler.sendMessage(Message.obtain(handler, params.getJobId(), params));
        }else{
            logger.e(TAG, "handler is null on onStartJob");
        }
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        handler.removeMessages(params.getJobId());
        return true;
    }

    private class ServiceThread extends Thread{
        private Context context;
        protected Database.Helper db;
        public Lock lock;
        public Condition init_done;
        // MAIN TREAD
        public ServiceThread(Context context){
            setContext(context);
            config = Config.getInstance(context);
            logger = Logger.getInstance(context);
            db = Database.Helper.getInstance(context);
            encryptor = new Encryption(context);
            lock = new ReentrantLock();
            init_done = lock.newCondition();

        }
        public void setContext(Context context) {
            this.context = context;
        }

        //SERVICE THREAD
        @Override
        public void run() {
            logger.i(TAG, "Thread started");
            lock.lock();
            Looper.prepare();
            handler = new Handler( new Handler.Callback() {
                @Override
                public boolean handleMessage( Message msg ) {
                    logger.d(TAG, "New message");
                    JobParameters job_params = (JobParameters) msg.obj;
                    boolean success = handleJob(job_params);
                    if(!success) {
                        logger.d(TAG, "Auto upload job will be rescheduled (because upload failed)");
                    }
                    jobFinished( job_params, !success ); // Auto reschedule on failure following backoff policy
                    return true;
                }
            } );
            logger.i(TAG, "Thread init_done");
            init_done.signal();
            lock.unlock();
            Looper.loop();
        }

        private boolean httpPost(String url, String json){
            logger.i(TAG, "Http post to : "   url);
            return false; // Force fail to test rescheduling
        }

        public boolean handleJob(JobParameters params){
            //Thread
            // Return true to tell job successful, so it will not be retyied, false will retry
            PersistableBundle extras = params.getExtras();
            String action = extras.getString("action");
            String json;
            Boolean success;
            logger.d(TAG, "Action = " action);
            switch (action){
                case Constant.JOB_SCHEDULER_AUTO_UPLOAD:
                    success = httpPost(extras.getString("url"), json);
                    if(success){
                        db.storeEvent(System.currentTimeMillis(), Constant.JOB_SCHEDULER_AUTO_UPLOAD, "auto upload success");
                        return true;
                    }
                    db.storeEvent(System.currentTimeMillis(), Constant.JOB_SCHEDULER_AUTO_UPLOAD, "auto upload failed");
                    return false;
            }
            return false;
        }
    }
}
  

Задание запускается правильно при выполнении условий, однако оно никогда не запускается после сбоя, вот некоторые журналы, связанные с предыдущим кодом :

 10-18 15:06:51.857 19261-19261/fr.myapp.mdm D/MDM-JobSchedulerService: JobSchedulerService start
10-18 15:06:51.859 19261-19261/fr.myapp.mdm D/MDM-JobSchedulerService: Starting thread
10-18 15:06:51.860 19261-19261/fr.myapp.mdm D/MDM-JobSchedulerService: waiting for init_done
10-18 15:06:51.862 19261-19653/fr.myapp.mdm I/MDM-JobSchedulerService: Thread started
10-18 15:06:51.862 19261-19653/fr.myapp.mdm I/MDM-JobSchedulerService: Thread init_done
10-18 15:06:51.863 19261-19261/fr.myapp.mdm D/MDM-JobSchedulerService: init_done
10-18 15:06:51.869 19261-19653/fr.myapp.mdm D/MDM-JobSchedulerService: New message
10-18 15:06:51.870 19261-19653/fr.myapp.mdm D/MDM-JobSchedulerService: Action = JOB_SCHEDULER_AUTO_UPLOAD
10-18 15:06:51.870 19261-19653/fr.myapp.mdm I/MDM-JobSchedulerService: Auto upload job starting
10-18 15:06:52.029 19261-19653/fr.myapp.mdm I/MDM-JobSchedulerService: Http post to : http://xxxx
10-18 15:06:52.037 19261-19653/fr.myapp.mdm D/MDM-JobSchedulerService: Auto upload job will be rescheduled (because upload failed)
10-18 15:06:52.047 19261-19261/fr.myapp.mdm I/MDM-JobSchedulerService: JobSchedulerService destroyed
  

Спасибо за вашу помощь