【问题标题】:Have a job run at certain time of day, everyday with Evernote's android-job在一天中的特定时间运行一项工作,每天使用 Evernote 的 android-job
【发布时间】:2017-07-14 00:14:59
【问题描述】:

他们是让 Evernote 的 android-job 在每天凌晨 1 点到 2 点之间运行作业的模式吗?

我认为在我的Application.onCreateJob.onRunJob 的末尾添加类似的东西可能是有意义的

// use the current time to see how long it will be until 1AM
long timeUntil1Am = getTimeUntil1Am(currentUnixTimeStamp);

new JobRequest.Builder(DemoSyncJob.TAG)
            .setExecutionWindow(timeUntil1Am, timeUntil1Am + 3600_000L)
            .setBackoffCriteria(5_000L, JobRequest.BackoffPolicy.EXPONENTIAL)
            .setRequiresCharging(true)
            .setRequiresDeviceIdle(false)
            .setRequiredNetworkType(JobRequest.NetworkType.CONNECTED)
            .setRequirementsEnforced(true)
            .setPersisted(true)
            .setUpdateCurrent(true)
            .build()
            .schedule();

这将在大约凌晨 1 点从应用程序创建时第一次运行该作业,然后使用 onRunJob 以菊花链方式连接下一次运行时间。

我认为这可行,但我担心该作业会被安排多次,因为每次构建 Application 时都会创建一个新作业。如果我知道工作已经安排好了,我可以避免这种情况,但不确定是否可行。

所以我的问题是使用这种菊花链是一种合理的模式,我如何避免每天多次运行该作业?

【问题讨论】:

标签: android android-job


【解决方案1】:

我使用了类似于@CommonsWare 提到的常见问题解答中的模式

为了让这更容易,我创建了一个包装类来获取每日执行窗口

获取相对于当前时间的开始和结束时间的类

class DailyExecutionWindow {
    final long startMs;
    final long endMs;

    /**
     * Holds the start end time in ms for a job.
     * Will wrap around to next day if currentHour < targetHour.
     * If the current time is exactly now it will be forced to 60 seconds in the future.
     *
     * @param currentHour - current currentHour
     * @param currentMinute - current currentMinute
     * @param targetHour - currentHour we want to start
     * @param targetMinute - currentMinute we want to start
     * @param windowLengthInMinutes - number of minutes for the execution window
     */
    DailyExecutionWindow(int currentHour, int currentMinute, long targetHour, long targetMinute, long windowLengthInMinutes) {
        long hourOffset;
        long minuteOffset;

        if (targetHour == currentHour && targetMinute < currentMinute) {
            hourOffset = TimeUnit.HOURS.toMillis(23);
        } else if (targetHour - currentHour == 1) { // if we are less then an hour ahead, but into the next hour
            // move forward to 0 minute of next hour
            hourOffset = TimeUnit.MINUTES.toMillis(60 - currentMinute);
            currentMinute = 0;
        } else if (targetHour >= currentHour) {
            hourOffset = TimeUnit.HOURS.toMillis(targetHour - currentHour);
        } else {
            hourOffset = TimeUnit.HOURS.toMillis((24 + targetHour) - currentHour);
        }

        if (targetMinute >= currentMinute) {
            minuteOffset = TimeUnit.MINUTES.toMillis(targetMinute - currentMinute);
        } else {
            minuteOffset = TimeUnit.MINUTES.toMillis((60 + targetMinute) - currentMinute);
        }

        this.startMs = Math.max(hourOffset + minuteOffset, 60000);
        this.endMs = this.startMs + TimeUnit.MINUTES.toMillis(windowLengthInMinutes);

    }
}

我的链接 Job 实现

public class UpdateFeedsJob extends Job {

    public static final String TAG = UpdateFeedsJob.class.getName();
    private static final long TARGET_HOUR = 2L;
    private static final long TARGET_MINUTE = 15;
    private static final long WINDOW_LENGTH = 60;
    private static final int WAKE_LOCK_AWAIT_TIME_SECONDS = 60;

    // called in <MyApplication extends Application>.onCreate()
    public static void schedule() {
        schedule(true);
    }

    private static void schedule(boolean updateCurrent) {
        Calendar calendar = Calendar.getInstance();
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);

        DailyExecutionWindow executionWindow =
                new DailyExecutionWindow(hour, minute, TARGET_HOUR, TARGET_MINUTE, WINDOW_LENGTH);

        new JobRequest.Builder(UpdateFeedsJob.TAG)
                .setExecutionWindow(executionWindow.startMs, executionWindow.endMs)
                .setPersisted(true)
                .setUpdateCurrent(updateCurrent)
                .build()
                .schedule();
    }

    @NonNull
    @Override
    protected Result onRunJob(Params params) {
        try {
            // ... do work
            return Result.SUCCESS;
        } finally {
            schedule(false);
        }
        return Result.FAILURE;
    }
}

您可以在我的播客播放器应用程序on github 中看到一个工作示例

【讨论】:

    【解决方案2】:

    已接受答案中的示例看起来不错。请注意,1.2.0 版将有一个 helper class 来每天运行作业。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-01
      • 1970-01-01
      • 2016-06-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多