Android 当应用程序在 Android M (6) 打开时,仅作业计划程序 运行 个作业

Android Job Scheduler only running jobs when app is open on Android M (6)

我正在尝试在我的 Xamarin Forms 应用程序的后台将 Android 作业计划程序添加到 运行 作业,但它似乎只在我打开该应用程序时 运行。

作业已正确安排,但应用程序关闭时未触发。当需要调用外部 API 作业以获取一些数据,然后需要使用该数据更新本地 SQLite 数据库时应该发生什么。

我正在 Android 6 (M) 的 OnePlus 2 上进行测试。

下面是我的作业服务实现。

[Service(Name = "com.sample.JobSchedulerService", Permission = "android.permission.BIND_JOB_SERVICE")]
public class JobSchedulerService : JobService
{
    private readonly Service _service;

    public JobSchedulerService()
    {
        _service = new Service();
    }
    public override bool OnStartJob(JobParameters jobParams)
    {
        Task.Run(() =>
        {
            var updated = _service.UpdateDataAsync(54, -2);
            JobFinished(jobParams, !updated.Result);
        });

        return true;
    }

    public override bool OnStopJob(JobParameters jobParams)
    {
        return true;
    }
}

下面是安排我的工作的代码。

[assembly: Xamarin.Forms.Dependency(typeof(DownloadJob))]
namespace IslamReminders.Droid.Services
{
public class DownloadJob : IDownloadJob
{
    public void ScheduleJob(int jobId, long notificationRepeatMilliseconds)
    {
        var jobBuilder = JobScheduleHelpers.CreateJobBuilderUsingJobId<JobSchedulerService>(Application.Context, jobId)
                             .SetPeriodic(notificationRepeatMilliseconds)
                             .SetPersisted(true)
                             .Build();

        var jobScheduler = (JobScheduler)Application.Context.GetSystemService(Context.JobSchedulerService);
        var scheduleResult = jobScheduler.Schedule(jobBuilder);
    }
}
}

下面是调用 DownloadJob 以从 App.cs OnStart 安排作业的代码。

protected override void OnStart()
    {
        // Handle when your app starts
        var jobs = _dataAccess.GetJobs();

        if (jobs.Any(x => !x.IsActive))
        {
            var inactiveJobs = jobs.Where(x => x.IsActive == false);

            foreach (var job in inactiveJobs)
            {
                var notificationTimes = _dataAccess.GetNotificationTimesForJob(job.NotificationId);

                foreach (var notificationTime in notificationTimes)
                    DependencyService.Get<IDownloadJob>().ScheduleJob(job.Id, (long)notificationTime.NotificationRepeat.TotalMilliseconds);

                job.IsActive = true;
                _dataAccess.UpdateJob(job);
            }
        }
    }

我认为我已正确设置所有内容,但在应用程序关闭时无法正常工作。如有任何帮助,我们将不胜感激。

我最终更改了我的实现以使用 AlarmManager,因为这更适合我想要实现的目标,因为我需要在每天午夜后 运行 完成工作。

但是,我最终 运行 遇到了完全相同的问题,因为当应用程序关闭时我的工作不会 运行。当应用程序打开或处于后台时,代码会 运行 正常。

然后我做了一些进一步的分析,发现问题实际上与我试图使用 DependencyService 获取数据库路径有关。我收到的错误如下:

You MUST call Xamarin.Forms.Init(); prior to using it

应用程序关闭时它不工作的原因是因为 Xamarin.Forms 那时从未初始化,因此无法使用 DependencyService。我解决这个问题的方法是在广播接收器(或 JobSchedulerService)中获取数据库的路径,并将其传递给我的共享代码,然后按预期工作。

我没有使用 Job Scheduler 对此进行测试,因为我决定更改我的实现,但我相信这可能一直是 Job Scheduler 的问题。

希望这个解释可以帮助可能 运行 遇到类似问题的人。