何时调用 JobScheduler.schedule()

When to call JobScheduler.schedule()

我想实现的是一个每小时从服务器获取数据的后台服务。我希望此服务可以在启动后定期 运行。因此,我选择使用JobScheduler来实现这个功能。

val jobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler val builder = JobInfo.Builder(1, ComponentName(this, PullDataJob::class.java)) .setPeriodic(1000L * 60 * 60) // one hour .setRequiredNetworkType(NETWORK_TYPE_ANY) .setPersisted(true) jobScheduler.schedule(builder.build())

这是我目前的代码,放在onCreate()里面。但是我发现如果我把JobScheduler.schedule()放在onCreate()里,每次打开应用都会自动执行这个服务

即使用户在系统启动后从未打开该应用程序,也可以定期将上述代码放置在什么位置 运行?

您的作业是定期执行的(每小时一次),所以一旦它是 运行 第一次,JobScheduler.schedule() 应该 永远不会 被再次调用。

完成这个很容易,一旦你第一次调用 JobScheduler.schedule(),注册它已经被安排的事实,只有 运行 当你确定你的工作有以前从未 运行。

    public static final String IS_JOB_FIRST_RUN = "job scheduled";

...

    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
    if (preferences.getBoolean(IS_JOB_FIRST_RUN, true)) {

       // your code
       JobScheduler.schedule();
       preferences.edit().putBoolean(IS_JOB_FIRST_RUN, false).apply();
    }

哈基姆是对的,你应该只安排一次。 如果您两次使用相同的 JobId 安排作业,文档说明如下:

Will replace any currently scheduled job with the same ID with the new information in the JobInfo. If a job with the given ID is currently running, it will be stopped.

但我会以不同于 hakeem 的方式解决问题。您不应将此信息保存在 Sharedpreference 中,而应使用 JobScheduler 来确定是否已安排具有您的 ID 的作业。这样你会更加健壮,并且会重新安排工作,以防发生一些奇怪的事情并且你的工作不再被安排。

代码:

public static boolean isJobServiceOn( Context context ) {
        JobScheduler scheduler = (JobScheduler) context.getSystemService( Context.JOB_SCHEDULER_SERVICE ) ;

        boolean hasBeenScheduled = false ;

        for ( JobInfo jobInfo : scheduler.getAllPendingJobs() ) {
            if ( jobInfo.getId() == RETRIEVE_DATA_JOB_ID ) {
                hasBeenScheduled = true ;
                break ;
            }
        }

        return hasBeenScheduled ;
    }

安排作业时,您可以使用此功能来确定我当前是否安排了作业。