我在使用 Android 上的 JobScheduling API 时遇到问题,当我的工作失败时,我希望根据之前设置的回退策略重新安排它。
工作的创建看起来像这样:
try {
mJobSchedulerServiceComponent = new ComponentName(this.context, JobSchedulerService.class);
JobInfo.Builder builder = new JobInfo.Builder(Constant.AUTO_UPLOAD_JOB_ID, mJobSchedulerServiceComponent );
builder.setPersisted(true);
builder.setRequiresCharging(true);
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
builder.setBackoffCriteria(10000, JobInfo.BACKOFF_POLICY_LINEAR);
builder.setOverrideDeadline(600 * 1000);
builder.setMinimumLatency(60 * 1000);
PersistableBundle bundle = new PersistableBundle();
bundle.putString("action", Constant.JOB_SCHEDULER_AUTO_UPLOAD);
bundle.putString("url", Constant.API_URL_SEND_DATA);
builder.setExtras(bundle);
if( mJobScheduler.schedule( builder.build() ) <= 0 ) {
//If something goes wrong
logger.e(TAG, "Create auto upload job failed");
}
} catch (Exception e) {
logger.e(TAG, "createAutoUploadJob error " + e);
}
处理作业的 JobService 如下所示:
public class JobSchedulerService extends JobService {
private Handler handler;
protected Config config;
protected Logger logger;
protected static final String TAG = "MDM-JobSchedulerService";
private volatile ServiceThread thread = null;
@Override
public void onCreate() {
super.onCreate();
logger = Logger.getInstance(this);
logger.d(TAG, "JobSchedulerService start");
thread = new ServiceThread(this);
logger.d(TAG, "Starting thread");
thread.lock.lock();
thread.start();
logger.d(TAG, "waiting for init_done");
try {
thread.init_done.await();
}catch (InterruptedException e){
logger.i(TAG, "Got exception "+e.toString());
}
logger.d(TAG, "init_done");
thread.lock.unlock();
}
@Override
public void onDestroy() {
super.onDestroy();
logger.i(TAG, "JobSchedulerService destroyed");
}
@Override
public boolean onStartJob(JobParameters params) {
/*
* You'll notice that in the following code snippet, the onStartJob(JobParameters params) method returns true.
* This is because you're going to use a Handler instance to control your operation, which means that it could
* take longer to finish than the onStartJob(JobParameters params) method. By returning true, you're letting
* the application know that you will manually call the jobFinished(JobParameters params, boolean needsRescheduled) method
* */
if (handler != null) {
handler.sendMessage(Message.obtain(handler, params.getJobId(), params));
}else{
logger.e(TAG, "handler is null on onStartJob");
}
return true;
}
@Override
public boolean onStopJob(JobParameters params) {
handler.removeMessages(params.getJobId());
return true;
}
private class ServiceThread extends Thread{
private Context context;
protected Database.Helper db;
public Lock lock;
public Condition init_done;
// MAIN TREAD
public ServiceThread(Context context){
setContext(context);
config = Config.getInstance(context);
logger = Logger.getInstance(context);
db = Database.Helper.getInstance(context);
encryptor = new Encryption(context);
lock = new ReentrantLock();
init_done = lock.newCondition();
}
public void setContext(Context context) {
this.context = context;
}
//SERVICE THREAD
@Override
public void run() {
logger.i(TAG, "Thread started");
lock.lock();
Looper.prepare();
handler = new Handler( new Handler.Callback() {
@Override
public boolean handleMessage( Message msg ) {
logger.d(TAG, "New message");
JobParameters job_params = (JobParameters) msg.obj;
boolean success = handleJob(job_params);
if(!success) {
logger.d(TAG, "Auto upload job will be rescheduled (because upload failed)");
}
jobFinished( job_params, !success ); // Auto reschedule on failure following backoff policy
return true;
}
} );
logger.i(TAG, "Thread init_done");
init_done.signal();
lock.unlock();
Looper.loop();
}
private boolean httpPost(String url, String json){
logger.i(TAG, "Http post to : " + url);
return false; // Force fail to test rescheduling
}
public boolean handleJob(JobParameters params){
//Thread
// Return true to tell job successful, so it will not be retyied, false will retry
PersistableBundle extras = params.getExtras();
String action = extras.getString("action");
String json;
Boolean success;
logger.d(TAG, "Action = "+action);
switch (action){
case Constant.JOB_SCHEDULER_AUTO_UPLOAD:
success = httpPost(extras.getString("url"), json);
if(success){
db.storeEvent(System.currentTimeMillis(), Constant.JOB_SCHEDULER_AUTO_UPLOAD, "auto upload success");
return true;
}
db.storeEvent(System.currentTimeMillis(), Constant.JOB_SCHEDULER_AUTO_UPLOAD, "auto upload failed");
return false;
}
return false;
}
}
}
满足条件时作业正常启动,但失败后永远不会启动,以下是与之前代码相关的一些日志:
10-18 15:06:51.857 19261-19261/fr.myapp.mdm D/MDM-JobSchedulerService: JobSchedulerService start
10-18 15:06:51.859 19261-19261/fr.myapp.mdm D/MDM-JobSchedulerService: Starting thread
10-18 15:06:51.860 19261-19261/fr.myapp.mdm D/MDM-JobSchedulerService: waiting for init_done
10-18 15:06:51.862 19261-19653/fr.myapp.mdm I/MDM-JobSchedulerService: Thread started
10-18 15:06:51.862 19261-19653/fr.myapp.mdm I/MDM-JobSchedulerService: Thread init_done
10-18 15:06:51.863 19261-19261/fr.myapp.mdm D/MDM-JobSchedulerService: init_done
10-18 15:06:51.869 19261-19653/fr.myapp.mdm D/MDM-JobSchedulerService: New message
10-18 15:06:51.870 19261-19653/fr.myapp.mdm D/MDM-JobSchedulerService: Action = JOB_SCHEDULER_AUTO_UPLOAD
10-18 15:06:51.870 19261-19653/fr.myapp.mdm I/MDM-JobSchedulerService: Auto upload job starting
10-18 15:06:52.029 19261-19653/fr.myapp.mdm I/MDM-JobSchedulerService: Http post to : http://xxxx
10-18 15:06:52.037 19261-19653/fr.myapp.mdm D/MDM-JobSchedulerService: Auto upload job will be rescheduled (because upload failed)
10-18 15:06:52.047 19261-19261/fr.myapp.mdm I/MDM-JobSchedulerService: JobSchedulerService destroyed
谢谢你的帮助