3

I have created a JobScheduler to intimate user few features in my app based on date and time.

But found out that the Job's are not scheduled at exact time which I am expecting to. Neither the job is getting stopped after the interval. As per my study all the scheduling depends on setOverrideDeadline , setMinimumLatency and durationToSet

Found out delay of 30-55 seconds for start and stop, which is not consistent in every trials.

I have restructured my app features referring this sample

Below are the code samples through which I will be scheduling according to the expected date time. (Put out only essential steps for SO)

String startDate = "2018-01-05";
String endDate = "2018-01-05";
String startTime = "11:10"
String endTime = "11:30"

Converting date time in the following format like given below after combining the start date with start time. similarly end date with end time.

String dateTimeStart = startDate + " " + startTime;//For start date time
String dateTimeEnd = endDate + " " + endTime;//For end date time

Will be using the below logic for calculating start and end time for job in long value.

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
long timeInMilliseconds = 0;
        try {
            Date mDate = sdf.parse(dateTimeStart);
            timeInMilliseconds = mDate.getTime();
        } catch (ParseException e) {
            Log.e(TAG, e.toString());
        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }

Now based on this input , I will create a Unique ID using AtomicInteger for each job and schedule the job as shown below.

public void scheduleJob(int jobID, long startMillSec,long endMilliSec) {

            JobInfo.Builder builder = new JobInfo.Builder(jobID, mServiceComponent);

            PersistableBundle extras = new PersistableBundle();

            long currTimeMillSec= System.currentTimeMillis();

            long minLatency =0;
            //if time already crossed start time, then start time is current time itself
            if(currTimeMillSec>=startMillSec){
                minLatency=0;
            }else{
                minLatency=startMillSec-currTimeMillSec;
            }
            builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE);
            builder.setOverrideDeadline(startMillSec);
            builder.setMinimumLatency(minLatency);
            builder.setRequiresDeviceIdle(false);
            builder.setRequiresCharging(false);
            builder.setPersisted(true);

            long durationToSet=0;
            //if time has passes, keep the delta as the duration, or else keep the full duration received from backend
            if(currTimeMillSec>=startMillSec){
                durationToSet= endMilliSec-currTimeMillSec;
            }else{
                durationToSet=endMilliSec-startMillSec;
            }
            //Set duration for job stopping
            extras.putLong("WORK_DURATION_KEY", durationToSet);
            builder.setExtras(extras);

        JobScheduler tm = (JobScheduler) mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE);
        tm.schedule(builder.build());
    }

Below is my JobService class

public class AppJobScheduler extends JobService 
{
    @Override
    public boolean onStartJob(final JobParameters params) {
        sendMessage(MSG_START, params.getJobId());

        long duration = params.getExtras().getLong(WORK_DURATION_KEY);
        // Uses a handler to delay the execution of jobFinished().
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                sendMessage(MSG_STOP, params.getJobId());
                jobFinished(params, false);
            }
        }, duration);
        return true;
    }
    
    @Override
    public boolean onStopJob(JobParameters params) {
        sendMessage(MSG_STOP, params.getJobId());
        return false;
    }

    private void sendMessage(int messageID, @Nullable Object params) {
        
        Message m = Message.obtain();
        m.what = messageID;
        m.obj = params;
        try {
            mActivityMessenger.send(m);
        } catch (RemoteException e) {
            Log.e(TAG, " Error passing service object back to .");
        }
    }
        
}

Other references followed are reference one and reference two

TylerH
  • 20,799
  • 66
  • 75
  • 101
Sreehari
  • 5,621
  • 2
  • 25
  • 59

0 Answers0