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>
|
</intent-filter>
|
||||||
</activity>
|
</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"
|
<activity android:name=".content.InstallApk" android:label="@string/activity_install_apk"
|
||||||
android:enabled="@bool/atLeastHoneycombMR2">
|
android:enabled="@bool/atLeastHoneycombMR2">
|
||||||
<intent-filter>
|
<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_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="activity_install_apk">Content/Packages/Install Apk</string>
|
||||||
|
|
||||||
<string name="ir_send">Send IR</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