2016-03-21 41 views
13

を実行:アンドロイドjobschedulerのは、私はアンドロイドjobschedulerのAPIを使用してジョブを作成し、スケジュールするために以下のコードを使用しています数回

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

すなわち、 2時間ごとに実行される定期ジョブと20分*を実行するリニアバックオフポリシーは、ジョブが失敗した場合に失敗します。

私の仕事のサービスコードは、以下のように書かれている:

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

} 

そして最後にログ出力は以下の通りです:

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

なぜonStartJobと呼ばれている2回?

答えて

11

多くの不満の後、私はこの問題の原因を突き止めました。

定期的に電話する必要があります。 needsRescheduletrueを渡すと、ジョブはキューに複製されます(元のものを上書きすると思われますが、そうでない場合は明らかです)。タスクが失敗した場合でも、常にjobFinished(JobParameters, false)を使用する必要があります。

これが不正なAPIの使用またはAndroidのバグとしてカウントされるかどうかは、お伝えします。

+1

うわー。私はインストールされて数週間後に1分に数回実行される15分のスケジュールされた仕事を持っていたアプリを持っていた。あなたが言うことが真実ならば、それはネットワーク通話に失敗するたびに新しい定期的な仕事を生み出していました。 – Tom

0

jobschedulerのは、Androidオレオとより多くを使用することになるので、私は例をいくつかの問題を説明したかった:

onStopJob()オーバーライドされたメソッドのみtrueを返します。ジョブが処理中に中断された場合、つまり充電器が接続されていないか、JobInfoに設定されているネットワークがない場合、この機能を使用してタスク/ジョブをすぐにキャンセルする必要があります。ジョブを再スケジューリングする必要があることを示すtrueが返されます。

MyJobServiceMyWorkerタスクへの参照を持つ必要があります。 onStartJob()がそれを設定します。 onStopJob()は、タスクを直ちに取り消すためにそれを使用します。

jobFinished()メソッド内でneedsRescheduletrueを渡すことは、通常、タスク内で呼び出されたときは特に必要ありません。ジョブが中断されると、onStopJob()が呼び出されてキャンセルされ、trueを返すとそのジョブが再スケジュールされます。私はneedsRescheduletrueに設定されているhereの1つの例しか見ていません。それはonStartJob()の範囲内であり、前提条件の二重チェックが満たされない場合、trueの代わりにjobFinished(args, true)、次にreturn falseとなります。

希望すると便利です。

関連する問題