Have tried job dispatcher for scheduling repetitive tasks on Hourly basis. Have written a code snippet for the problem but not sure if this is a correct implementation or not.
Snippet is for scheduling a task at 11 Hour of Monday at every week.
Any correction on this or other possible solution will help a lot.
Calendar c1 = Calendar.getInstance();
c1.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
c1.set(Calendar.HOUR_OF_DAY, 11);
c1.set(Calendar.MINUTE, 0);
c1.set(Calendar.SECOND, 0);
c1.set(Calendar.MILLISECOND, 0);
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(Splash_onboarding.this));
Job myJob = dispatcher.newJobBuilder()
.setService(ScheduledNotificationService.class)
.setTag(dispatcherTag)
.setRecurring(true)
.setLifetime(Lifetime.FOREVER)
.setTrigger(Trigger.executionWindow(Math.round(c1.getTime().getTime() / 1000), (Math.round(c1.getTime().getTime() / 1000)) + 60))
.setReplaceCurrent(true)
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
.build();
dispatcher.mustSchedule(myJob);
I don't think you are implementing Firebase JobDispatcher correctly
Trigger.executionWindow()
In this, you write after how much time your job executes itself after scheduling your job. For more info see this :
https://stackoverflow.com/a/42111723/7384780
You can solve your problem by scheduling your first non-recurring job with executionWindow (get time of next monday) - System.currentTimeMillis() and then starting a recurring job inside JobService with executionWindow of 7 * 24 * 60 * 60.
Related
according to this medium article from Android Developers:
At the moment, if you need to execute a worker at roughly the same time, every day, your best option is to use a OneTimeWorkRequest with an initial delay so that you execute it at the right time:
and then when the work finishes successfully, the idea is to reschedule the work to be run once again and so on. now my question is that if we want a work to be repeated everyday at roughly the same time, why can't we directly use work manager PeriodicWorkRequest? for example suppose the work must be repeated everyday around 5:00 PM. then:
Calendar windowStart = new GregorianCalendar();
windowStart.set(Calendar.HOUR_OF_DAY, 17);
windowStart.set(Calendar.MINUTE, 0);
windowStart.set(Calendar.SECOND, 0);
windowStart.set(Calendar.MILLISECOND, 0);
long delay = windowStart.getTimeInMillis() - System.currentTimeMillis();
if (delay < 0) {
windowStart.add(Calendar.DAY_OF_MONTH, 1);
delay = windowStart.getTimeInMillis() - System.currentTimeMillis();
}
Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build();
PeriodicWorkRequest periodicWorkRequest =
new PeriodicWorkRequest.Builder(Worker.class, 24, TimeUnit.HOURS, 5, TimeUnit.MINUTES)
.setInitialDelay(delay, TimeUnit.MILLISECONDS)
.setConstraints(constraints)
.build();
does this piece of code guarantee that the work will definitely run everyday between 17:00 and 17:05, if the constraints are met?
I am using FirebaseJobDispatcher for posting the data.
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(DetectedActivitiesIntentService.this));
Job myJob = dispatcher.newJobBuilder()
.setService(SendCarProbeDataService.class) // the JobService that will be called
.setTag(tripId)
.setConstraints(Constraint.ON_ANY_NETWORK)
.setExtras(bundle)
.build();
dispatcher.mustSchedule(myJob);
I have noticed that my posting service runs after some duration.
When I research on it, I get to know that there is a JobInfo which have the property to set setMinimumLetancy(0) to run the service as quick as possible.
JobInfo jobInfo = new JobInfo.Builder(tripId, SendCarProbeDataService.class)
.setMinimumLatency(0)
.setConstraints(Constraint.ON_ANY_NETWORK)
.setExtras(bundle).build();
But I need to know the difference between Job and JobInfo and how I use setMinimumLetancy in Job?
with job info you can specify the constraints of the job. if you want to execute your job at specific time then use
.setTrigger(Trigger.executionWindow(x, y))
x is the window starting time
y is the window ending time
eg:.setTrigger(Trigger.executionWindow(10, 20))
the job will execute between the time 10 to 20 seconds...
for immediate execution use
.setTrigger(Trigger.NOW)
Per this example, I see that I can have the job start now using Trigger.NOW or a time of 0,0:
Bundle myExtrasBundle = new Bundle();
myExtrasBundle.putString("some_key", "some_value");
Job myJob = dispatcher.newJobBuilder()
// the JobService that will be called
.setService(MyJobService.class)
// uniquely identifies the job
.setTag("my-unique-tag")
// one-off job
.setRecurring(false)
// don't persist past a device reboot
.setLifetime(Lifetime.UNTIL_NEXT_BOOT)
// start between 0 and 60 seconds from now
.setTrigger(Trigger.executionWindow(0, 60))
// don't overwrite an existing job with the same tag
.setReplaceCurrent(false)
// retry with exponential backoff
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
// constraints that need to be satisfied for the job to run
.setConstraints(
// only run on an unmetered network
Constraint.ON_UNMETERED_NETWORK,
// only run when the device is charging
Constraint.DEVICE_CHARGING
)
.setExtras(myExtrasBundle)
.build();
dispatcher.mustSchedule(myJob);
My question is:
How do I set the job to start now but also repeat every [time interval] (lets call it 15 minutes)?
To make your job repeat periodically call these two methods:
.setRecurring(true) //true mean repeat it
.setTrigger(Trigger.executionWindow(start, end))
start : is know as windowStart, which is the earliest time (in seconds) the job should be considered eligible to run. Calculated from when the job was scheduled (for new jobs)
end : is know as windowEnd, The latest time (in seconds) the job should be run in an ideal world. Calculated in the same way as windowStart.
Job myJob = dispatcher.newJobBuilder()
// the JobService that will be called
.setService(MyJobService.class)
// uniquely identifies the job
.setTag("my-unique-tag")
// one-off job
.setRecurring(true)
// don't persist past a device reboot
.setLifetime(Lifetime.FOREVER)
// start between 0 and 60 seconds from now
.setTrigger(Trigger.executionWindow(0, 60))
// don't overwrite an existing job with the same tag
.setReplaceCurrent(false)
// retry with exponential backoff
.setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
// constraints that need to be satisfied for the job to run
// .setConstraints(
// // only run on an unmetered network
// Constraint.ON_UNMETERED_NETWORK,
// // only run when the device is charging
// Constraint.DEVICE_CHARGING
// )
.setExtras(myExtrasBundle)
.build();
dispatcher.mustSchedule(myJob);
I am trying to use firebase jobdispatcher to support older devices and newer devices for my calendar app, i am referring this link to setup firebase code in my app is there anything needed to schedule job at particular time at daily weekly etc. or there any other alternative for that?
need help in trigger window setting to schedule event at particular time and date recursively. eg daily 4 pm event for 1 week
final int periodicity = (int)TimeUnit.HOURS.toSeconds(12); // Every 12 hours periodicity expressed as seconds
final int toleranceInterval = (int) TimeUnit.HOURS.toSeconds(1); // a small(ish) window of time when triggering is OK
Job myJob = dispatcher.newJobBuilder()
// the JobService that will be called
.setService(MyJobService.class)
// uniquely identifies the job
.setTag("my-unique-tag")
// one-off job
.setRecurring(true)
// persist past a device reboot
.setLifetime(Lifetime.FOREVER)
.setTrigger(Trigger.executionWindow(periodicity, periodicity + toleranceInterval))
// don't overwrite an existing job with the same tag
.setReplaceCurrent(false)
// retry with exponential backoff
.setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
// constraints that need to be satisfied for the job to run
// .setConstraints(
// // only run on an unmetered network
// Constraint.ON_UNMETERED_NETWORK,
// // only run when the device is charging
// Constraint.DEVICE_CHARGING
// )
.setExtras(myExtrasBundle)
.build();
dispatcher.mustSchedule(myJob);
add this line in menifiest file
<service
android:name="your service name"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true"/>
Calculate the time using as per your requirement and set the periodicity and toleranceInterval
int day = (int)TimeUnit.SECONDS.toDays(seconds);
long hours = TimeUnit.SECONDS.toHours(seconds) - (day *24);
long minute = TimeUnit.SECONDS.toMinutes(seconds) - (TimeUnit.SECONDS.toHours(seconds)* 60);
long second = TimeUnit.SECONDS.toSeconds(seconds) - (TimeUnit.SECONDS.toMinutes(seconds) *60);
1: Day calculation is correct does not require explanation.
2: TimeUnit.SECONDS.toHours(seconds) will give you direct conversion from seconds to hours without consideration for days you have already calculated. Minus the hours for days you already got i.e, day*24. You now got remaining hours.
3: Same for minute and second. You need to minus the already got hour and minutes respectively.
i have to download json response from web server on every night,previously i have used AlarmManager for scheduling tasks but i think for this kind of situation JobDispatcher is great because it auto perform task if network available so i don't have to manage this kind of stuf.But i have found many examples of JobDispatcher and JobScheduler in all of them a simple job is scheduled or scheduled for some time delay but there is nothing relevant to my requirements,
if anyone have idea of this please help or provide any link related to this, it will be very helpful.
UPDATE
1. How to make this to work every night,because currently it is only set alarm to midnight for once , how to make it repeted for every night at same time ?
This is how you need to schedule time-based jobs
FirebaseJobDispatcher jobDispatcher = new FirebaseJobDispatcher(
new GooglePlayDriver(this));
Calendar now = Calendar.getInstance();
Calendar midNight = Calendar.getInstance();
midNight.set(Calendar.HOUR, 12);
midNight.set(Calendar.MINUTE, 0);
midNight.set(Calendar.SECOND, 0);
midNight.set(Calendar.MILLISECOND, 0);
midNight.set(Calendar.AM_PM, Calendar.AM);
long diff = now.getTimeInMillis() - midNight.getTimeInMillis();
if (diff < 0) {
midNight.add(Calendar.DAY_OF_MONTH, 1);
diff = midNight.getTimeInMillis() - now.getTimeInMillis();
}
int startSeconds = (int) (diff / 1000); // tell the start seconds
int endSencods = startSeconds + 300; // within Five minutes
Job networkJob = jobDispatcher.newJobBuilder()
.setService(NetworkJob.class)
.setTag(NetworkJob.ID_TAG)
.setRecurring(true)
.setTrigger(Trigger.executionWindow(startSeconds, endSencods))
.setLifetime(Lifetime.FOREVER)
.setReplaceCurrent(true)
.setConstraints(Constraint.ON_ANY_NETWORK)
.build();
jobDispatcher.schedule(networkJob);
I suggest you set your JobDispatcher to start at the next midnight, ie set the start time as the difference between now and the next midnight. Once it starts you can let it start a new Job that starts in 24 hours, ie the service will start a new Job with start time set as 24 hours and make this one recurring.