Merge "Add API demo for monitoring media content."
This commit is contained in:
committed by
Android (Google) Code Review
commit
ef77d26ce8
@@ -1253,6 +1253,17 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".content.MediaContentObserver"
|
||||
android:label="@string/activity_media_content_observer">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.SAMPLE_CODE"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service android:name=".content.MediaContentJob"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
<activity android:name=".content.InstallApk" android:label="@string/activity_install_apk"
|
||||
android:enabled="@bool/atLeastHoneycombMR2">
|
||||
<intent-filter>
|
||||
|
||||
54
samples/ApiDemos/res/layout/media_content_observer.xml
Normal file
54
samples/ApiDemos/res/layout/media_content_observer.xml
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<Button android:id="@+id/schedule_job"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:text="Schedule job">
|
||||
</Button>
|
||||
<Button android:id="@+id/cancel_job"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:text="Cancel job">
|
||||
</Button>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:text="Directly observed content changes:" />
|
||||
|
||||
<ScrollView android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
<TextView
|
||||
android:id="@+id/changes_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#ff303030"
|
||||
android:padding="4dp"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
/>
|
||||
</ScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -469,6 +469,8 @@
|
||||
|
||||
<string name="activity_changed_contact">Content/Provider/Changed Contacts</string>
|
||||
|
||||
<string name="activity_media_content_observer">Content/Provider/Media Content Observer</string>
|
||||
|
||||
<string name="activity_install_apk">Content/Packages/Install Apk</string>
|
||||
|
||||
<string name="ir_send">Send IR</string>
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* 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.widget.Toast;
|
||||
|
||||
import com.example.android.apis.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Stub job to execute when there is a change to any media: content URI.
|
||||
*/
|
||||
public class MediaContentJob extends JobService {
|
||||
static final Uri MEDIA_URI = Uri.parse("content://" + MediaStore.AUTHORITY + "/");
|
||||
|
||||
final Handler mHandler = new Handler();
|
||||
final Runnable mWorker = new Runnable() {
|
||||
@Override public void run() {
|
||||
scheduleJob(MediaContentJob.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_job,
|
||||
new ComponentName(context, MediaContentJob.class));
|
||||
builder.addTriggerContentUri(new JobInfo.TriggerContentUri(MEDIA_URI,
|
||||
JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
|
||||
js.schedule(builder.build());
|
||||
}
|
||||
|
||||
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_job) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void cancelJob(Context context) {
|
||||
JobScheduler js = context.getSystemService(JobScheduler.class);
|
||||
js.cancel(R.id.schedule_job);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStartJob(JobParameters params) {
|
||||
mRunningParams = params;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Media 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, 20*1000);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStopJob(JobParameters params) {
|
||||
mHandler.removeCallbacks(mWorker);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* 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.Activity;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.example.android.apis.R;
|
||||
|
||||
public class MediaContentObserver extends Activity {
|
||||
ContentObserver mContentObserver;
|
||||
View mScheduleJob;
|
||||
View mCancelJob;
|
||||
TextView mDataText;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mContentObserver = new ContentObserver(new Handler()) {
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
mDataText.append(uri.toString());
|
||||
mDataText.append("\n");
|
||||
}
|
||||
};
|
||||
|
||||
Log.d("foo", "Observing: " + MediaContentJob.MEDIA_URI);
|
||||
|
||||
// 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);
|
||||
mDataText = (TextView)findViewById(R.id.changes_text);
|
||||
|
||||
mScheduleJob.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
MediaContentJob.scheduleJob(MediaContentObserver.this);
|
||||
updateButtons();
|
||||
}
|
||||
});
|
||||
mCancelJob.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
MediaContentJob.cancelJob(MediaContentObserver.this);
|
||||
updateButtons();
|
||||
}
|
||||
});
|
||||
updateButtons();
|
||||
|
||||
getContentResolver().registerContentObserver(MediaContentJob.MEDIA_URI, true,
|
||||
mContentObserver);
|
||||
}
|
||||
|
||||
void updateButtons() {
|
||||
if (MediaContentJob.isScheduled(this)) {
|
||||
mScheduleJob.setEnabled(false);
|
||||
mCancelJob.setEnabled(true);
|
||||
} else {
|
||||
mScheduleJob.setEnabled(true);
|
||||
mCancelJob.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
getContentResolver().unregisterContentObserver(mContentObserver);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user