web-dev-qa-db-ja.com

ジョブスケジューラがAndroid Nで実行されていない

Job Schedulerは、Android MarshmallowおよびLollipopデバイスで正常に動作していますが、Nexus 5x(Nexus N Preview)で実行されていません。

ジョブをスケジュールするためのコード

        ComponentName componentName = new ComponentName(MainActivity.this, TestJobService.class.getName());
        JobInfo.Builder builder;
        builder = new JobInfo.Builder(JOB_ID, componentName);
        builder.setPeriodic(5000);
        JobInfo jobInfo;
        jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
        jobInfo = builder.build();
        int jobId = jobScheduler.schedule(jobInfo);

サービスはマニフェストで次のように定義されます:

<service Android:name=".TestJobService"
            Android:permission="Android.permission.BIND_JOB_SERVICE" />

Android N(プレビュー)でこの問題を抱えている人はいますか?

40
kaibuki

In Android Nougat thesetPeriodic(long intervalMillis)メソッド呼び出しはsetPeriodic (long intervalMillis, long flexMillis)定期的なジョブをスケジュールします。

ドキュメントに従って:

JobInfo.Builder setPeriodic(長いintervalMillis、長いflexMillis)

指定された間隔とフレックスでこのジョブが繰り返されるように指定します。ジョブは、期間の終わりにフレックス長のウィンドウ内でいつでも実行できます。

intervalMillis long:このジョブが繰り返されるミリ秒間隔。 getMinPeriodMillis()の最小値が強制されます。

flexMillis long:このジョブのミリ秒フレックス。 Flexは、少なくともgetMinFlexMillis()または期間の5%のいずれか高い方にクランプされます。

5秒間にスケジュールされた定期ジョブのサンプル:

_private static final int JOB_ID = 1001;
private static final long REFRESH_INTERVAL  = 5 * 1000; // 5 seconds

JobInfo jobInfo = new JobInfo.Builder(JOB_ID, serviceName)
        .setPeriodic(REFRESH_INTERVAL)
        .setExtras(bundle).build();
_

上記のコードはLollipopとMarshmallowでうまく機能しますが、Nougatで実行すると次のログに気付きます。

_W/JobInfo: Specified interval for 1001 is +5s0ms. Clamped to +15m0s0ms
W/JobInfo: Specified flex for 1001 is +5s0ms. Clamped to +5m0s0ms
_

定期的な更新間隔を5秒に設定しているため、thresholdgetMinPeriodMillis()未満です。 Android NougatはgetMinPeriodMillis()を強制します。

回避策として、次のコードを使用して、ジョブ間隔が15分未満の場合に定期的な間隔でジョブをスケジュールします。

_JobInfo jobInfo;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
  jobInfo = new JobInfo.Builder(JOB_ID, serviceName)
      .setMinimumLatency(REFRESH_INTERVAL)
      .setExtras(bundle).build();
} else {
  jobInfo = new JobInfo.Builder(JOB_ID, serviceName)
      .setPeriodic(REFRESH_INTERVAL)
      .setExtras(bundle).build();
}
_

サンプルJobServiceの例:

_public class SampleService extends JobService {
    @Override public boolean onStartJob(JobParameters params) {
        doSampleJob(params); 
        return true;
    }

    @Override public boolean onStopJob(JobParameters params) {
        return false;
    }

    public void doSampleJob(JobParameters params) {
        // Do some heavy operation
        ...... 
        // At the end inform job manager the status of the job.
        jobFinished(params, false);
    }
}
_
59
blizzard

誰かがまだ状況を克服しようとしている場合、

これは> = Android N(定期ジョブを15分未満に設定する場合))の回避策です

SetMinimumLatencyのみが使用されていることを確認してください。また、時間がかかるタスクを実行している場合、次のジョブは、現在のジョブの終了時刻+ PROVIDED_TIME_INTERVALにスケジュールされます

.SetPeriodic(long millis)は、以下のAPIレベルでうまく機能しますAndroid N

@Override
public boolean onStartJob(final JobParameters jobParameters) {
    Log.d(TAG,"Running service now..");
    //Small or Long Running task with callback
    //Call Job Finished when your job is finished, in callback
    jobFinished(jobParameters, false );

    //Reschedule the Service before calling job finished
    if(Android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
              scheduleRefresh();



    return true;
}

@Override
public boolean onStopJob(JobParameters jobParameters) {
    return false;
}

private void scheduleRefresh() {
  JobScheduler mJobScheduler = (JobScheduler)getApplicationContext()
                    .getSystemService(JOB_SCHEDULER_SERVICE);
  JobInfo.Builder mJobBuilder = 
  new JobInfo.Builder(YOUR_JOB_ID,
                    new ComponentName(getPackageName(), 
                    GetSessionService.class.getName()));

  /* For Android N and Upper Versions */
  if (Android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
      mJobBuilder
                .setMinimumLatency(60*1000) //YOUR_TIME_INTERVAL
                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
  }

PDATE:Dozeモードでジョブを繰り返し実行することを検討しており、JobSchedulerについて考えている場合、FYI:JobSchedulersはDozeモードで実行できません。

JobSchedulerについて話していたので、Dozingについては話しませんでした。 @ Elletlarに感謝します。アプリが居眠りモードにある場合でも実行されると考える人がいるかもしれないことを指摘してくれました。

居眠りモードの場合でも、AlarmManagerは最適なソリューションを提供します。使用できますsetExactAndAllowWhileIdle()定期的なジョブを正確な時間で実行する場合、またはsetAndAllowWhileIdleを使用する場合()柔軟であれば。

setAlarmClock()を使用することもできます。これは、デバイスが常に目覚まし時計の居眠りモードから出て、再び居眠りモードに戻るためです。別の方法は、FCMを使用することです。

13
MRah

Nougatデバイスが直面している問題に対する答えを見つけました。 Nougatデバイスは、15分以内にジョブを再スケジュールする必要がある場合、ジョブをスケジュールできません。

インターバル時間を15分に設定して試してみたところ、15分ごとにジョブがスケジュールされ始めました。

ジョブスケジューラコード:

public static void scheduleJob(Context context) {
    ComponentName serviceComponent = new ComponentName(context, PAJobService.class);
    JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, serviceComponent);
    builder.setPeriodic(15 * 60 * 1000, 5 * 60 *1000);

    JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
    int ret = jobScheduler.schedule(builder.build());
    if (ret == JobScheduler.RESULT_SUCCESS) {
        Log.d(TAG, "Job scheduled successfully");
    } else {
        Log.d(TAG, "Job scheduling failed");
    }
}

ジョブサービス:

public class PAJobService extends JobService {
    private static final String TAG = PRE_TAG + PAJobService.class.getSimpleName();
    private LocationManager mLocationManager;

    public boolean onStartJob(JobParameters params) {
        Log.d(TAG, "onStartJob");
        Toast.makeText(getApplicationContext(), "Job Started", Toast.LENGTH_SHORT).show();
        return false;
    }

    public boolean onStopJob(JobParameters params) {
        Log.d(TAG, "onStopJob");
        return false;
    }
}

要するに、インターバル時間を15分に増やした場合、コードは動作を開始します。

private static final long REFRESH_INTERVAL = 15 * 60 * 1000;

8

15分以内に定期的にコードを実行したい場合は、トリッキーな方法を使用できます。 jobFinished()を次のように設定します

jobFinished(parameters, true);

再試行戦略でコードを再スケジュールします。を使用してカスタムバックオフ条件を定義する

.setBackoffCriteria();

ビルダーで。その後、定期的に実行されます

0
MarGin