2016-03-21 22 views
13

Tôi đang sử dụng mã dưới đây để tạo và sắp xếp một công việc sử dụng Androids JobScheduler API:Android JobScheduler thực hiện nhiều lần

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); 

Tức là một công việc định kỳ thực hiện mỗi 2 giờ và một chính sách quay trở lại tuyến tính thực hiện 20 phút * số không thành công trong trường hợp công việc thất bại.

mã dịch vụ Công việc của tôi được viết như sau:

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", "------------------------------------------"); 
     } 
    } 

} 

Và cuối cùng là dữ liệu ghi nhận như sau:

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 : ------------------------ 

Tại sao onStartJob được gọi hai lần?

Trả lời

11

Sau nhiều thất vọng, tôi đã tìm ra nguyên nhân gây ra sự cố này.

Bạn nên không gọi jobFinished(JobParameters, true) trong một công việc định kỳ. Việc chuyển số true cho needsReschedule sẽ khiến công việc bị trùng lặp trong hàng đợi (bạn có thể dự kiến ​​sẽ ghi đè lên hàng đợi ban đầu, nhưng dường như không phải như vậy). Bạn phải luôn sử dụng jobFinished(JobParameters, false), ngay cả khi nhiệm vụ của bạn không thành công.

Để biết liệu điều này có được tính là sử dụng API không chính xác hay lỗi Android, tôi sẽ để điều đó tùy thuộc vào bạn.

+1

Chà bắt thú vị. Tôi đã có một ứng dụng có công việc được lập lịch 15 phút chạy vài lần trong một vài phút sau khi cài đặt. Nếu những gì bạn nói là đúng, thì nó đã sinh ra một công việc định kỳ mới mỗi khi nó thất bại trong một cuộc gọi mạng. – Tom

0

Kể từ JobScheduler sẽ được sử dụng nhiều hơn với Android Oreo, tôi muốn mô tả một vài vấn đề với ví dụ:

Các onStopJob() phương pháp ghi đè chỉ trả true. Nếu công việc của bạn bị gián đoạn trong khi đang xử lý, tức là bộ sạc đã được rút phích cắm hoặc không có mạng nào được đặt trong JobInfo, chức năng này sẽ được sử dụng để hủy ngay lập tức tác vụ/công việc. Sau đó, nó sẽ trả về true cho biết công việc cần phải được lên lịch lại.

MyJobService phải có tham chiếu private đến MyWorker tác vụ. onStartJob() đặt nó. onStopJob() sử dụng nó để hủy ngay tác vụ.

Chuyển true cho phương thức needsReschedule trong phương thức jobFinished() thường không cần thiết, đặc biệt khi được gọi trong công việc của bạn. Nếu một công việc bị gián đoạn, onStopJob() sẽ được gọi để hủy bỏ nó và trả về true sẽ lên lịch lại nó. Tôi chỉ thấy một ví dụ here trong đó needsReschedule được đặt thành true. Nó nằm trong phạm vi onStartJob() và nếu việc kiểm tra kép các điều kiện tiên quyết không được đáp ứng, jobFinished(args, true) và sau đó return false thay vì true.

Hy vọng điều này sẽ hữu ích!

Các vấn đề liên quan