下面列出了怎么用android.app.job.JobWorkItem的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Dequeue some work.
*/
@Override
public JobIntentService.GenericWorkItem dequeueWork() {
JobWorkItem work;
synchronized (mLock) {
if (mParams == null) {
return null;
}
work = mParams.dequeueWork();
}
if (work != null) {
work.getIntent().setExtrasClassLoader(mService.getClassLoader());
return new WrapperWorkItem(work);
} else {
return null;
}
}
JobWorkItem doDequeueWork(JobCallback cb, int jobId) {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
assertCallerLocked(cb);
if (mVerb == VERB_STOPPING || mVerb == VERB_FINISHED) {
// This job is either all done, or on its way out. Either way, it
// should not dispatch any more work. We will pick up any remaining
// work the next time we start the job again.
return null;
}
final JobWorkItem work = mRunningJob.dequeueWorkLocked();
if (work == null && !mRunningJob.hasExecutingWorkLocked()) {
// This will finish the job.
doCallbackLocked(false, "last work dequeued");
}
return work;
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override
public int enqueue(JobInfo job, JobWorkItem work) throws RemoteException {
if (DEBUG) {
Slog.d(TAG, "Enqueueing job: " + job.toString() + " work: " + work);
}
final int uid = Binder.getCallingUid();
final int userId = UserHandle.getUserId(uid);
enforceValidJobRequest(uid, job);
if (job.isPersisted()) {
throw new IllegalArgumentException("Can't enqueue work for persisted jobs");
}
if (work == null) {
throw new NullPointerException("work is null");
}
validateJobFlags(job, uid);
long ident = Binder.clearCallingIdentity();
try {
return JobSchedulerService.this.scheduleAsPackage(job, work, uid, null, userId,
null);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Dequeue some work.
*/
@Override
public GenericWorkItem dequeueWork() {
JobWorkItem work = null;
synchronized (mLock) {
if (mParams == null) {
return null;
}
try {
work = mParams.dequeueWork();
} catch (Throwable ignore) {
}
}
if (work != null) {
work.getIntent().setExtrasClassLoader(mService.getClassLoader());
return new JobServiceEngineImpl.WrapperWorkItem(work);
} else {
return null;
}
}
/**
* Dequeue some work.
*/
@Override
public GenericWorkItem dequeueWork() {
JobWorkItem work = null;
synchronized (mLock) {
if (mParams == null) {
return null;
}
try {
work = mParams.dequeueWork();
} catch (Throwable ignore) {
}
}
if (work != null) {
work.getIntent().setExtrasClassLoader(mService.getClassLoader());
return new JobServiceEngineImpl.WrapperWorkItem(work);
} else {
return null;
}
}
/**
* Dequeue some work.
*/
@Override
public JobIntentService.GenericWorkItem dequeueWork() {
JobWorkItem work;
synchronized (mLock) {
if (mParams == null) {
return null;
}
try {
work = mParams.dequeueWork();
} catch (SecurityException e) {
// Issue: https://issuetracker.google.com/issues/63622293
// Caller no longer running, last stopped +###ms because: last work dequeued
Log.e(TAG, "Failed to run mParams.dequeueWork()!", e);
return null;
}
}
if (work != null) {
work.getIntent().setExtrasClassLoader(mService.getClassLoader());
return new WrapperWorkItem(work);
} else {
return null;
}
}
/**
* Dequeue some work.
*/
@Override
public JobIntentService.GenericWorkItem dequeueWork() {
JobWorkItem work = null;
synchronized (mLock) {
if (mParams == null) {
return null;
}
try {
work = mParams.dequeueWork();
} catch (SecurityException se) {
//ignore
se.printStackTrace();
}
}
if (work != null) {
work.getIntent().setExtrasClassLoader(mService.getClassLoader());
return new WrapperWorkItem(work);
} else {
return null;
}
}
/**
* Dequeue some work.
*/
@Override
public JobIntentService.GenericWorkItem dequeueWork() {
JobWorkItem work = null;
synchronized (mLock) {
if (mParams == null) {
return null;
}
try {
work = mParams.dequeueWork();
} catch (SecurityException se) {
//ignore
se.printStackTrace();
}
}
if (work != null) {
work.getIntent().setExtrasClassLoader(mService.getClassLoader());
return new WrapperWorkItem(work);
} else {
return null;
}
}
/**
* Dequeue some work.
*/
@Override
public GenericWorkItem dequeueWork() {
JobWorkItem work = null;
synchronized (mLock) {
if (mParams == null) {
return null;
}
try {
work = mParams.dequeueWork();
} catch (Throwable ignore) {
}
}
if (work != null) {
work.getIntent().setExtrasClassLoader(mService.getClassLoader());
return new JobServiceEngineImpl.WrapperWorkItem(work);
} else {
return null;
}
}
/**
* Dequeue some work.
*/
@Override
public GenericWorkItem dequeueWork() {
JobWorkItem work = null;
synchronized (mLock) {
if (mParams == null) {
return null;
}
try {
work = mParams.dequeueWork();
} catch (Throwable ignore) {
}
}
if (work != null) {
work.getIntent().setExtrasClassLoader(mService.getClassLoader());
return new JobServiceEngineImpl.WrapperWorkItem(work);
} else {
return null;
}
}
@Override
void enqueueWork(Intent work) {
if (DEBUG) {
Log.d(TAG, "Enqueueing work: " + work);
}
mJobScheduler.enqueue(mJobInfo, new JobWorkItem(work));
}
public void enqueueWorkLocked(IActivityManager am, JobWorkItem work) {
if (pendingWork == null) {
pendingWork = new ArrayList<>();
}
work.setWorkId(nextPendingWorkId);
nextPendingWorkId++;
if (work.getIntent() != null
&& GrantedUriPermissions.checkGrantFlags(work.getIntent().getFlags())) {
work.setGrants(GrantedUriPermissions.createFromIntent(am, work.getIntent(), sourceUid,
sourcePackageName, sourceUserId, toShortString()));
}
pendingWork.add(work);
updateEstimatedNetworkBytesLocked();
}
public JobWorkItem dequeueWorkLocked() {
if (pendingWork != null && pendingWork.size() > 0) {
JobWorkItem work = pendingWork.remove(0);
if (work != null) {
if (executingWork == null) {
executingWork = new ArrayList<>();
}
executingWork.add(work);
work.bumpDeliveryCount();
}
updateEstimatedNetworkBytesLocked();
return work;
}
return null;
}
public boolean completeWorkLocked(IActivityManager am, int workId) {
if (executingWork != null) {
final int N = executingWork.size();
for (int i = 0; i < N; i++) {
JobWorkItem work = executingWork.get(i);
if (work.getWorkId() == workId) {
executingWork.remove(i);
ungrantWorkItem(am, work);
return true;
}
}
}
return false;
}
private static void ungrantWorkList(IActivityManager am, ArrayList<JobWorkItem> list) {
if (list != null) {
final int N = list.size();
for (int i = 0; i < N; i++) {
ungrantWorkItem(am, list.get(i));
}
}
}
private void dumpJobWorkItem(PrintWriter pw, String prefix, JobWorkItem work, int index) {
pw.print(prefix); pw.print(" #"); pw.print(index); pw.print(": #");
pw.print(work.getWorkId()); pw.print(" "); pw.print(work.getDeliveryCount());
pw.print("x "); pw.println(work.getIntent());
if (work.getGrants() != null) {
pw.print(prefix); pw.println(" URI grants:");
((GrantedUriPermissions)work.getGrants()).dump(pw, prefix + " ");
}
}
private void dumpJobWorkItem(ProtoOutputStream proto, long fieldId, JobWorkItem work) {
final long token = proto.start(fieldId);
proto.write(JobStatusDumpProto.JobWorkItem.WORK_ID, work.getWorkId());
proto.write(JobStatusDumpProto.JobWorkItem.DELIVERY_COUNT, work.getDeliveryCount());
if (work.getIntent() != null) {
work.getIntent().writeToProto(proto, JobStatusDumpProto.JobWorkItem.INTENT);
}
Object grants = work.getGrants();
if (grants != null) {
((GrantedUriPermissions) grants).dump(proto, JobStatusDumpProto.JobWorkItem.URI_GRANTS);
}
proto.end(token);
}
@Override
public int enqueue(JobInfo job, JobWorkItem work) {
try {
return mBinder.enqueue(job, work);
} catch (RemoteException e) {
return JobScheduler.RESULT_FAILURE;
}
}
/**
* Start a service either through the context or enqueued to the JobService to be run in a minute.
* For example, the BroadcastReceivers use this to handle all versions of the API.
*
* @param context - Application context
* @param jobId - job id for the job to start if it is a job
* @param intent - Intent you want to run.
*/
public static void startService(Context context, Integer jobId, Intent intent) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
JobInfo jobInfo = new JobInfo.Builder(jobId,
new ComponentName(context, JobWorkService.class))
// schedule it to run any time between 1 - 5 minutes
.setMinimumLatency(JobWorkService.ONE_MINUTE)
.setOverrideDeadline(5 * JobWorkService.ONE_MINUTE)
.build();
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
if (jobScheduler.getAllPendingJobs().stream().filter(job -> job.getId() == jobId && job.getExtras().equals(intent.getExtras())).count() > 0) {
// already pending job. don't run again
LoggerFactory.getLogger("ServiceScheduler").info("Job already pending");
return;
}
JobWorkItem jobWorkItem = new JobWorkItem(intent);
try {
jobScheduler.enqueue(jobInfo, jobWorkItem);
}
catch (Exception e) {
LoggerFactory.getLogger("ServiceScheduler").error("Problem enqueuing work item ", e);
}
}
else {
context.startService(intent);
}
}
private void completeWork(JobParameters jobParameters, JobWorkItem jobWorkItem) {
Intent intent = jobWorkItem.getIntent();
if (intent != null && intent.hasExtra(INTENT_EXTRA_JWS_PERIODIC)) {
logger.info("Periodic work item completed ");
jobParameters.completeWork(jobWorkItem);
//reschedule(jobWorkItem);
}
else {
logger.info("work item completed");
jobParameters.completeWork(jobWorkItem);
}
}
private void reschedule(JobWorkItem item) {
ServiceScheduler.PendingIntentFactory pendingIntentFactory = new ServiceScheduler
.PendingIntentFactory(getApplicationContext());
ServiceScheduler serviceScheduler = new ServiceScheduler(getApplicationContext(), pendingIntentFactory,
LoggerFactory.getLogger(ServiceScheduler.class));
Intent intent = item.getIntent();
serviceScheduler.schedule(intent, intent.getLongExtra(INTENT_EXTRA_JWS_PERIODIC, -1));
}
@Override
protected Void doInBackground(Void... params) {
boolean cancelled;
JobWorkItem work;
/**
* Iterate over available work. Once dequeueWork() returns null, the
* job's work queue is empty and the job has stopped, so we can let this
* async task complete.
*/
while (!(cancelled=isCancelled()) && (work=mParams.dequeueWork()) != null) {
String txt = work.getIntent().getStringExtra("Key1");
Log.i("JobWorkService", "Processing work: " + work + ", msg: " + txt);
showNotification(txt);
// Process work here... we'll pretend by sleeping.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
hideNotification();
// Tell system we have finished processing the work.
Log.i("JobWorkService", "Done with: " + work);
mParams.completeWork(work);
}
if (cancelled) {
Log.i("JobWorkService", "CANCELLED!");
}
return null;
}
WrapperWorkItem(JobWorkItem jobWork) {
mJobWork = jobWork;
}
@Override
public JobWorkItem dequeueWork(int jobId) {
return doDequeueWork(this, jobId);
}
public int scheduleAsPackage(JobInfo job, JobWorkItem work, int uId, String packageName,
int userId, String tag) {
try {
if (ActivityManager.getService().isAppStartModeDisabled(uId,
job.getService().getPackageName())) {
Slog.w(TAG, "Not scheduling job " + uId + ":" + job.toString()
+ " -- package not allowed to start");
return JobScheduler.RESULT_FAILURE;
}
} catch (RemoteException e) {
}
synchronized (mLock) {
final JobStatus toCancel = mJobs.getJobByUidAndJobId(uId, job.getId());
if (work != null && toCancel != null) {
// Fast path: we are adding work to an existing job, and the JobInfo is not
// changing. We can just directly enqueue this work in to the job.
if (toCancel.getJob().equals(job)) {
toCancel.enqueueWorkLocked(ActivityManager.getService(), work);
// If any of work item is enqueued when the source is in the foreground,
// exempt the entire job.
toCancel.maybeAddForegroundExemption(mIsUidActivePredicate);
return JobScheduler.RESULT_SUCCESS;
}
}
JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId, tag);
// Give exemption if the source is in the foreground just now.
// Note if it's a sync job, this method is called on the handler so it's not exactly
// the state when requestSync() was called, but that should be fine because of the
// 1 minute foreground grace period.
jobStatus.maybeAddForegroundExemption(mIsUidActivePredicate);
if (DEBUG) Slog.d(TAG, "SCHEDULE: " + jobStatus.toShortString());
// Jobs on behalf of others don't apply to the per-app job cap
if (ENFORCE_MAX_JOBS && packageName == null) {
if (mJobs.countJobsForUid(uId) > MAX_JOBS_PER_APP) {
Slog.w(TAG, "Too many jobs for uid " + uId);
throw new IllegalStateException("Apps may not schedule more than "
+ MAX_JOBS_PER_APP + " distinct jobs");
}
}
// This may throw a SecurityException.
jobStatus.prepareLocked(ActivityManager.getService());
if (work != null) {
// If work has been supplied, enqueue it into the new job.
jobStatus.enqueueWorkLocked(ActivityManager.getService(), work);
}
if (toCancel != null) {
// Implicitly replaces the existing job record with the new instance
cancelJobImplLocked(toCancel, jobStatus, "job rescheduled by app");
} else {
startTrackingJobLocked(jobStatus, null);
}
StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED,
uId, null, jobStatus.getBatteryName(),
StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__SCHEDULED,
JobProtoEnums.STOP_REASON_CANCELLED);
// If the job is immediately ready to run, then we can just immediately
// put it in the pending list and try to schedule it. This is especially
// important for jobs with a 0 deadline constraint, since they will happen a fair
// amount, we want to handle them as quickly as possible, and semantically we want to
// make sure we have started holding the wake lock for the job before returning to
// the caller.
// If the job is not yet ready to run, there is nothing more to do -- we are
// now just waiting for one of its controllers to change state and schedule
// the job appropriately.
if (isReadyToBeExecutedLocked(jobStatus)) {
// This is a new job, we can just immediately put it on the pending
// list and try to run it.
mJobPackageTracker.notePending(jobStatus);
addOrderedItem(mPendingJobs, jobStatus, mEnqueueTimeComparator);
maybeRunPendingJobsLocked();
}
}
return JobScheduler.RESULT_SUCCESS;
}
private static void ungrantWorkItem(IActivityManager am, JobWorkItem work) {
if (work.getGrants() != null) {
((GrantedUriPermissions)work.getGrants()).revoke(am);
}
}
WrapperWorkItem(JobWorkItem jobWork) {
mJobWork = jobWork;
}
@Override
void enqueueWork(Intent work) {
if (DEBUG) Log.d(TAG, "Enqueueing work: " + work);
mJobScheduler.enqueue(mJobInfo, new JobWorkItem(work));
}
WrapperWorkItem(JobWorkItem jobWork) {
mJobWork = jobWork;
}
@Override
void enqueueWork(Intent work) {
if (DEBUG) Log.d(TAG, "Enqueueing work: " + work);
mJobScheduler.enqueue(mJobInfo, new JobWorkItem(work));
}