Add sample for observing only photos changes.
Change-Id: I954fb466fb21d73f88b1dd1bc86eac617a628073
This commit is contained in:
@@ -1275,6 +1275,9 @@
|
||||
<service android:name=".content.MediaContentJob"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
<service android:name=".content.PhotosContentJob"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
<activity android:name=".content.InstallApk" android:label="@string/activity_install_apk"
|
||||
android:enabled="@bool/atLeastHoneycombMR2">
|
||||
<intent-filter>
|
||||
|
||||
@@ -21,13 +21,25 @@
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<Button android:id="@+id/schedule_job"
|
||||
<Button android:id="@+id/schedule_media_job"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:text="Schedule job">
|
||||
android:text="Schedule media job">
|
||||
</Button>
|
||||
<Button android:id="@+id/cancel_job"
|
||||
<Button android:id="@+id/cancel_media_job"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:text="Cancel job">
|
||||
android:text="Cancel media job">
|
||||
</Button>
|
||||
</LinearLayout>
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<Button android:id="@+id/schedule_photos_job"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:text="Schedule photos job">
|
||||
</Button>
|
||||
<Button android:id="@+id/cancel_photos_job"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:text="Cancel photos job">
|
||||
</Button>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.example.android.apis.R;
|
||||
@@ -49,11 +50,12 @@ public class MediaContentJob extends JobService {
|
||||
|
||||
public static void scheduleJob(Context context) {
|
||||
JobScheduler js = context.getSystemService(JobScheduler.class);
|
||||
JobInfo.Builder builder = new JobInfo.Builder(R.id.schedule_job,
|
||||
JobInfo.Builder builder = new JobInfo.Builder(R.id.schedule_media_job,
|
||||
new ComponentName(context, MediaContentJob.class));
|
||||
builder.addTriggerContentUri(new JobInfo.TriggerContentUri(MEDIA_URI,
|
||||
JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
|
||||
js.schedule(builder.build());
|
||||
Log.i("MediaContentJob", "JOB SCHEDULED!");
|
||||
}
|
||||
|
||||
public static boolean isScheduled(Context context) {
|
||||
@@ -63,7 +65,7 @@ public class MediaContentJob extends JobService {
|
||||
return false;
|
||||
}
|
||||
for (int i=0; i<jobs.size(); i++) {
|
||||
if (jobs.get(i).getId() == R.id.schedule_job) {
|
||||
if (jobs.get(i).getId() == R.id.schedule_media_job) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -72,11 +74,12 @@ public class MediaContentJob extends JobService {
|
||||
|
||||
public static void cancelJob(Context context) {
|
||||
JobScheduler js = context.getSystemService(JobScheduler.class);
|
||||
js.cancel(R.id.schedule_job);
|
||||
js.cancel(R.id.schedule_media_job);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStartJob(JobParameters params) {
|
||||
Log.i("MediaContentJob", "JOB STARTED!");
|
||||
mRunningParams = params;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Media content has changed:\n");
|
||||
@@ -102,7 +105,7 @@ public class MediaContentJob extends JobService {
|
||||
}
|
||||
Toast.makeText(this, sb.toString(), Toast.LENGTH_LONG).show();
|
||||
// We will emulate taking some time to do this work, so we can see batching happen.
|
||||
mHandler.postDelayed(mWorker, 20*1000);
|
||||
mHandler.postDelayed(mWorker, 10*1000);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,10 @@ import com.example.android.apis.R;
|
||||
|
||||
public class MediaContentObserver extends Activity {
|
||||
ContentObserver mContentObserver;
|
||||
View mScheduleJob;
|
||||
View mCancelJob;
|
||||
View mScheduleMediaJob;
|
||||
View mCancelMediaJob;
|
||||
View mSchedulePhotosJob;
|
||||
View mCancelPhotosJob;
|
||||
TextView mDataText;
|
||||
|
||||
@Override
|
||||
@@ -49,24 +51,40 @@ public class MediaContentObserver extends Activity {
|
||||
// See res/any/layout/resources.xml for this view layout definition.
|
||||
setContentView(R.layout.media_content_observer);
|
||||
|
||||
mScheduleJob = findViewById(R.id.schedule_job);
|
||||
mCancelJob = findViewById(R.id.cancel_job);
|
||||
mScheduleMediaJob = findViewById(R.id.schedule_media_job);
|
||||
mCancelMediaJob = findViewById(R.id.cancel_media_job);
|
||||
mSchedulePhotosJob = findViewById(R.id.schedule_photos_job);
|
||||
mCancelPhotosJob = findViewById(R.id.cancel_photos_job);
|
||||
mDataText = (TextView)findViewById(R.id.changes_text);
|
||||
|
||||
mScheduleJob.setOnClickListener(new View.OnClickListener() {
|
||||
mScheduleMediaJob.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
MediaContentJob.scheduleJob(MediaContentObserver.this);
|
||||
updateButtons();
|
||||
}
|
||||
});
|
||||
mCancelJob.setOnClickListener(new View.OnClickListener() {
|
||||
mCancelMediaJob.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
MediaContentJob.cancelJob(MediaContentObserver.this);
|
||||
updateButtons();
|
||||
}
|
||||
});
|
||||
mSchedulePhotosJob.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
PhotosContentJob.scheduleJob(MediaContentObserver.this);
|
||||
updateButtons();
|
||||
}
|
||||
});
|
||||
mCancelPhotosJob.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
PhotosContentJob.cancelJob(MediaContentObserver.this);
|
||||
updateButtons();
|
||||
}
|
||||
});
|
||||
updateButtons();
|
||||
|
||||
getContentResolver().registerContentObserver(MediaContentJob.MEDIA_URI, true,
|
||||
@@ -75,11 +93,18 @@ public class MediaContentObserver extends Activity {
|
||||
|
||||
void updateButtons() {
|
||||
if (MediaContentJob.isScheduled(this)) {
|
||||
mScheduleJob.setEnabled(false);
|
||||
mCancelJob.setEnabled(true);
|
||||
mScheduleMediaJob.setEnabled(false);
|
||||
mCancelMediaJob.setEnabled(true);
|
||||
} else {
|
||||
mScheduleJob.setEnabled(true);
|
||||
mCancelJob.setEnabled(false);
|
||||
mScheduleMediaJob.setEnabled(true);
|
||||
mCancelMediaJob.setEnabled(false);
|
||||
}
|
||||
if (PhotosContentJob.isScheduled(this)) {
|
||||
mSchedulePhotosJob.setEnabled(false);
|
||||
mCancelPhotosJob.setEnabled(true);
|
||||
} else {
|
||||
mSchedulePhotosJob.setEnabled(true);
|
||||
mCancelPhotosJob.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Copyright (c) 2016, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example.android.apis.content;
|
||||
|
||||
import android.app.job.JobInfo;
|
||||
import android.app.job.JobParameters;
|
||||
import android.app.job.JobScheduler;
|
||||
import android.app.job.JobService;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.example.android.apis.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Stub job to execute when there is a change to photos in the media provider.
|
||||
*/
|
||||
public class PhotosContentJob extends JobService {
|
||||
final Handler mHandler = new Handler();
|
||||
final Runnable mWorker = new Runnable() {
|
||||
@Override public void run() {
|
||||
scheduleJob(PhotosContentJob.this);
|
||||
jobFinished(mRunningParams, false);
|
||||
}
|
||||
};
|
||||
|
||||
JobParameters mRunningParams;
|
||||
|
||||
public static void scheduleJob(Context context) {
|
||||
JobScheduler js = context.getSystemService(JobScheduler.class);
|
||||
JobInfo.Builder builder = new JobInfo.Builder(R.id.schedule_photos_job,
|
||||
new ComponentName(context, PhotosContentJob.class));
|
||||
builder.addTriggerContentUri(new JobInfo.TriggerContentUri(
|
||||
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
|
||||
JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
|
||||
js.schedule(builder.build());
|
||||
Log.i("PhotosContentJob", "JOB SCHEDULED!");
|
||||
}
|
||||
|
||||
public static boolean isScheduled(Context context) {
|
||||
JobScheduler js = context.getSystemService(JobScheduler.class);
|
||||
List<JobInfo> jobs = js.getAllPendingJobs();
|
||||
if (jobs == null) {
|
||||
return false;
|
||||
}
|
||||
for (int i=0; i<jobs.size(); i++) {
|
||||
if (jobs.get(i).getId() == R.id.schedule_photos_job) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void cancelJob(Context context) {
|
||||
JobScheduler js = context.getSystemService(JobScheduler.class);
|
||||
js.cancel(R.id.schedule_photos_job);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStartJob(JobParameters params) {
|
||||
Log.i("PhotosContentJob", "JOB STARTED!");
|
||||
mRunningParams = params;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Photos content has changed:\n");
|
||||
if (params.getTriggeredContentAuthorities() != null) {
|
||||
sb.append("Authorities: ");
|
||||
boolean first = true;
|
||||
for (String auth : params.getTriggeredContentAuthorities()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append(auth);
|
||||
}
|
||||
if (params.getTriggeredContentUris() != null) {
|
||||
for (Uri uri : params.getTriggeredContentUris()) {
|
||||
sb.append("\n");
|
||||
sb.append(uri);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sb.append("(No content)");
|
||||
}
|
||||
Toast.makeText(this, sb.toString(), Toast.LENGTH_LONG).show();
|
||||
// We will emulate taking some time to do this work, so we can see batching happen.
|
||||
mHandler.postDelayed(mWorker, 10*1000);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStopJob(JobParameters params) {
|
||||
mHandler.removeCallbacks(mWorker);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user