首页 > 解决方案 > 作业调度程序无法取消系统 uid 的作业

问题描述

尝试取消我的应用程序中的所有作业时,我在 logcat 中收到以下异常

06-26 11:27:54.866 E/JobSchedulerService( 1246): Can't cancel all jobs for system uid
06-26 11:27:54.866 E/JobSchedulerService( 1246): android.util.Log$TerribleFailure: Can't cancel all jobs for system uid
06-26 11:27:54.866 E/JobSchedulerService( 1246):    at android.util.Log.wtf(Log.java:299)
06-26 11:27:54.866 E/JobSchedulerService( 1246):    at android.util.Slog.wtfStack(Slog.java:98)
06-26 11:27:54.866 E/JobSchedulerService( 1246):    at com.android.server.job.JobSchedulerService.cancelJobsForUid(JobSchedulerService.java:788)
06-26 11:27:54.866 E/JobSchedulerService( 1246):    at com.android.server.job.JobSchedulerService$JobSchedulerStub.cancelAll(JobSchedulerService.java:2033)
06-26 11:27:54.866 E/JobSchedulerService( 1246):    at android.app.job.IJobScheduler$Stub.onTransact(IJobScheduler.java:119)
06-26 11:27:54.866 E/JobSchedulerService( 1246):    at android.os.Binder.execTransact(Binder.java:697)

有没有人也遇到过这个错误?我似乎无法在任何地方找到答案。

取消作业的代码很简单,如下所示:

public static void cancelAllJobs(@NonNull Context context) {
    JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
    if (jobScheduler != null) {
        jobScheduler.cancelAll();
        Timber.d("All jobs are canceled.");
    } else {
        Timber.w("Job scheduler is not available.");
    }
}

请注意,我的应用在清单中被声明为系统

android:sharedUserId="android.uid.system"

标签: androidandroid-jobscheduler

解决方案


如果你运行: adb shell dumpsys jobscheduler,你可以看到系统 uid (#1000) 下调度的所有作业。

在具有共享 uid 的应用程序下调度的作业必须确保其作业 id 在使用该共享 uid 的所有包中是唯一的。来自文档:“ID 在相同 uid 的所有客户端中必须是唯一的(不仅仅是同一个包)。” cancelAll() API 将取消调用 uid 下的所有作业,而不仅仅是调用包中的作业。我猜想Android会限制带有系统uid的包取消所有系统uid作业,以确保作业不会被无意取消。

您真的要取消系统 uid 下所有应用程序/包中的所有作业吗?

我有几个应用程序使用带有系统 uid 的作业调度程序,并使用以下代码取消特定作业。

public static void cancelJob(Context mContext, int jobID) {
    JobScheduler scheduler = (JobScheduler)
            mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE);

    for (JobInfo jobInfo : scheduler.getAllPendingJobs()) {
        if (jobInfo.getId() == jobID) {
            scheduler.cancel(jobID);
            Log.i(TAG,"Cancelled Job with ID:" + jobID);
        }
    }
}

我刚刚遇到的另一个好帖子: https ://commonsware.com/blog/2017/06/07/jobscheduler-job-ids-libraries.html


推荐阅读