kai*_*uki 41 android android-jobscheduler android-7.0-nougat
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);
Run Code Online (Sandbox Code Playgroud)
服务在清单中定义为:
<service android:name=".TestJobService"
android:permission="android.permission.BIND_JOB_SERVICE" />
Run Code Online (Sandbox Code Playgroud)
在Android N(预览版)上是否有任何人遇到此问题?
bli*_*ard 60
在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();
Run Code Online (Sandbox Code Playgroud)
上面的代码在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
Run Code Online (Sandbox Code Playgroud)
因为我们已将周期性刷新间隔设置为小于阈值的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();
}
Run Code Online (Sandbox Code Playgroud)
示例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);
}
}
Run Code Online (Sandbox Code Playgroud)
MRa*_*Rah 13
如果有人仍在努力克服这种情况,
以下是> = 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);
}
Run Code Online (Sandbox Code Playgroud)
更新: 如果您正在考虑在打盹模式下运行重复作业并考虑JobScheduler,那么FYI:JobSchedulers不允许在打盹模式下运行.
我没有讨论过Dozing,因为我们谈论的是JobScheduler.谢谢,@ Elletlar,指出有些人可能会认为它会在应用程序处于打盹模式时运行,而事实并非如此.
对于打盹模式,AlarmManager仍然提供最佳解决方案.您可以使用setExactAndAllowWhileIdle() ,如果你想在精确的时间运行周期作业或使用setAndAllowWhileIdle()如果你是灵活的.
您还可以使用setAlarmClock()作为设备始终从打盹模式中输出闹钟并再次返回打盹模式.另一种方法是使用FCM.
我找到了我们与Nougat设备面临的问题的答案.如果作业需要重新安排的时间少于15分钟,那么Nougat设备无法安排作业.
我通过将Interval时间设为15分钟来尝试,并且每15分钟就开始安排工作.
Job Scheduler代码:
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");
}
}
Run Code Online (Sandbox Code Playgroud)
工作服务:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
简而言之,如果您将间隔时间增加到15分钟,代码就会开始工作.
private static final long REFRESH_INTERVAL = 15 * 60 * 1000;