1 /**
2  * Copyright (c) 2016, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.example.android.apis.content;
18 
19 import android.app.job.JobInfo;
20 import android.app.job.JobParameters;
21 import android.app.job.JobScheduler;
22 import android.app.job.JobService;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.net.Uri;
26 import android.os.Handler;
27 import android.provider.MediaStore;
28 import android.util.Log;
29 import android.widget.Toast;
30 
31 import com.example.android.apis.R;
32 
33 import java.util.List;
34 
35 /**
36  * Example stub job to monitor when there is a change to any media: content URI.
37  */
38 public class MediaContentJob extends JobService {
39     static final Uri MEDIA_URI = Uri.parse("content://" + MediaStore.AUTHORITY + "/");
40 
41     final Handler mHandler = new Handler();
42     final Runnable mWorker = new Runnable() {
43         @Override public void run() {
44             scheduleJob(MediaContentJob.this);
45             jobFinished(mRunningParams, false);
46         }
47     };
48 
49     JobParameters mRunningParams;
50 
scheduleJob(Context context)51     public static void scheduleJob(Context context) {
52         JobScheduler js = context.getSystemService(JobScheduler.class);
53         JobInfo.Builder builder = new JobInfo.Builder(JobIds.MEDIA_CONTENT_JOB,
54                 new ComponentName(context, MediaContentJob.class));
55         builder.addTriggerContentUri(new JobInfo.TriggerContentUri(MEDIA_URI,
56                 JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
57         js.schedule(builder.build());
58         Log.i("MediaContentJob", "JOB SCHEDULED!");
59     }
60 
isScheduled(Context context)61     public static boolean isScheduled(Context context) {
62         JobScheduler js = context.getSystemService(JobScheduler.class);
63         List<JobInfo> jobs = js.getAllPendingJobs();
64         if (jobs == null) {
65             return false;
66         }
67         for (int i=0; i<jobs.size(); i++) {
68             if (jobs.get(i).getId() == JobIds.MEDIA_CONTENT_JOB) {
69                 return true;
70             }
71         }
72         return false;
73     }
74 
cancelJob(Context context)75     public static void cancelJob(Context context) {
76         JobScheduler js = context.getSystemService(JobScheduler.class);
77         js.cancel(JobIds.MEDIA_CONTENT_JOB);
78     }
79 
80     @Override
onStartJob(JobParameters params)81     public boolean onStartJob(JobParameters params) {
82         Log.i("MediaContentJob", "JOB STARTED!");
83         mRunningParams = params;
84         StringBuilder sb = new StringBuilder();
85         sb.append("Media content has changed:\n");
86         if (params.getTriggeredContentAuthorities() != null) {
87             sb.append("Authorities: ");
88             boolean first = true;
89             for (String auth : params.getTriggeredContentAuthorities()) {
90                 if (first) {
91                     first = false;
92                 } else {
93                     sb.append(", ");
94                 }
95                 sb.append(auth);
96             }
97             if (params.getTriggeredContentUris() != null) {
98                 for (Uri uri : params.getTriggeredContentUris()) {
99                     sb.append("\n");
100                     sb.append(uri);
101                 }
102             }
103         } else {
104             sb.append("(No content)");
105         }
106         Toast.makeText(this, sb.toString(), Toast.LENGTH_LONG).show();
107         // We will emulate taking some time to do this work, so we can see batching happen.
108         mHandler.postDelayed(mWorker, 10*1000);
109         return true;
110     }
111 
112     @Override
onStopJob(JobParameters params)113     public boolean onStopJob(JobParameters params) {
114         mHandler.removeCallbacks(mWorker);
115         return false;
116     }
117 }
118