Job Scheduler在Android Marshmallow和Lollipop设备上按预期工作,但它没有运行和Nexus 5x(Android N预览版)。
安排工作的代码
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(预览版)上遇到此问题?
答案 0 :(得分:58)
在Android Nougat中, setPeriodic(long intervalMillis)
方法调用使用 setPeriodic (long intervalMillis, long flexMillis)
来安排定期作业。
根据文件:
JobInfo.Builder setPeriodic(long intervalMillis,long 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&amp;棉花糖,但是当你在牛轧糖中运行时,你会注意到以下日志:
W/JobInfo: Specified interval for 1001 is +5s0ms. Clamped to +15m0s0ms
W/JobInfo: Specified flex for 1001 is +5s0ms. Clamped to +5m0s0ms
因为我们已将周期性刷新间隔设置为5秒,小于阈值getMinPeriodMillis()
。 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);
}
}
答案 1 :(得分:12)
如果有人仍在努力克服这种情况,
以下是&gt; = Android N的解决方法(如果您要将定期作业设置为低于15分钟)
检查是否仅使用了setMinimumLatency。此外,如果您正在运行需要很长时间的任务,则下一个作业将安排在,当前JOB结束时间+ PROVIDED_TIME_INTERVAL
.SetPeriodic(long millis)适用于Android N以下的API级别
@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);
}
<强>更新强> 如果您在打盹模式中考虑重复工作并考虑JobScheduler, FYI:JobSchedulers不允许在打盹模式下运行。
我没有讨论过Dozing,因为我们谈论的是JobScheduler。谢谢, @Elletlar ,指出有些人可能认为即使应用处于打盹模式也会运行,但实际情况并非如此。
对于打盹模式,AlarmManager仍然提供最佳解决方案。如果要在确切时间段运行定期作业或使用,可以使用 setExactAndAllowWhileIdle() > setAndAllowWhileIdle()如果你很灵活的话。
您还可以使用 setAlarmClock(),因为设备始终从闹钟的打盹模式中退出并再次返回打盹模式。另一种方法是使用FCM。
答案 2 :(得分:8)
我找到了我们与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;
答案 3 :(得分:0)
如果你想在不到15分钟的时间内定期运行代码,那么你可以使用一种棘手的方法。像这样设置jobFinished()
jobFinished(parameters, true);
它将使用重试策略重新安排代码。使用
定义自定义退避标准.setBackoffCriteria();
在构建器中。然后它会定期运行