diff options
| author | Dianne Hackborn <hackbod@google.com> | 2017-04-21 14:20:22 -0700 |
|---|---|---|
| committer | Dianne Hackborn <hackbod@google.com> | 2017-04-21 15:02:25 -0700 |
| commit | 5229a901465825de2a6ed4b5f3637be7a18438ba (patch) | |
| tree | 367dc785b0fcb51a0ef77c4740681bcd4004ef2c /samples/ApiDemos | |
| parent | 91e0bb6afd4859eb23a44c97e8ce4f5ec56006c6 (diff) | |
| download | android_development-5229a901465825de2a6ed4b5f3637be7a18438ba.tar.gz android_development-5229a901465825de2a6ed4b5f3637be7a18438ba.tar.bz2 android_development-5229a901465825de2a6ed4b5f3637be7a18438ba.zip | |
Add sample for enqueuing work in a job.
Basically this is to have sample code to include in the java docs.
Bug: 37544153 API Review: JobWorkItem
Test: none
Change-Id: Ie4ed3ce4af8239010da2647fab00ed2aadb1d348
Diffstat (limited to 'samples/ApiDemos')
5 files changed, 327 insertions, 0 deletions
diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml index 0d626d4f6..d9744047a 100644 --- a/samples/ApiDemos/AndroidManifest.xml +++ b/samples/ApiDemos/AndroidManifest.xml @@ -595,6 +595,18 @@ </intent-filter> </activity> + <service android:name=".app.JobWorkService" + android:permission="android.permission.BIND_JOB_SERVICE"/> + + <activity android:name=".app.JobWorkServiceActivity" + android:label="@string/activity_job_work_service" + android:launchMode="singleTop"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.SAMPLE_CODE" /> + </intent-filter> + </activity> + <service android:name=".app.ForegroundService" /> <service android:name=".app.ForegroundService2" /> diff --git a/samples/ApiDemos/res/layout/job_work_service_activity.xml b/samples/ApiDemos/res/layout/job_work_service_activity.xml new file mode 100644 index 000000000..9862689fb --- /dev/null +++ b/samples/ApiDemos/res/layout/job_work_service_activity.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 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. +--> + +<!-- Demonstrates enqueueing work into a job. + See corresponding Java code com.android.sdk.app.JobWorkServiceActivity.java. --> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" android:padding="4dip" + android:gravity="center_horizontal" + android:layout_width="match_parent" android:layout_height="match_parent"> + + <TextView + android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_weight="0" android:paddingBottom="4dip" + android:textAppearance="?android:attr/textAppearanceMedium" + android:text="@string/job_work_service_controller"/> + + <Button android:id="@+id/enqueue1" + android:layout_width="wrap_content" android:layout_height="wrap_content" + android:text="@string/enqueue1_job"> + <requestFocus /> + </Button> + + <Button android:id="@+id/enqueue2" + android:layout_width="wrap_content" android:layout_height="wrap_content" + android:text="@string/enqueue2_job"> + </Button> + + <Button android:id="@+id/enqueue3" + android:layout_width="wrap_content" android:layout_height="wrap_content" + android:text="@string/enqueue3_job"> + </Button> + + <Button android:id="@+id/kill" + android:layout_width="wrap_content" android:layout_height="wrap_content" + android:text="@string/kill_process"> + </Button> + +</LinearLayout> + diff --git a/samples/ApiDemos/res/values/strings.xml b/samples/ApiDemos/res/values/strings.xml index 37e55f7b5..81df88925 100644 --- a/samples/ApiDemos/res/values/strings.xml +++ b/samples/ApiDemos/res/values/strings.xml @@ -302,6 +302,19 @@ <string name="service_created">Service created.</string> <string name="service_destroyed">Service destroyed.</string> + <string name="job_work_service_label">Job Work Service</string> + + <string name="activity_job_work_service">App/Job/Job Work Service Controller</string> + <string name="job_work_service_controller">This demonstrates how + work can be enqueued and executed by a job, running work in the job until + everything is complete. + </string> + <string name="enqueue1_job">Enqueue \"One\"</string> + <string name="enqueue2_job">Enqueue \"Two\"</string> + <string name="enqueue3_job">Enqueue \"Three\"</string> + <string name="job_service_created">JobService created.</string> + <string name="job_service_destroyed">JobService destroyed.</string> + <string name="foreground_service_started">Service is in the foreground</string> <string name="foreground_service_label">Sample Foreground Service</string> diff --git a/samples/ApiDemos/src/com/example/android/apis/app/JobWorkService.java b/samples/ApiDemos/src/com/example/android/apis/app/JobWorkService.java new file mode 100644 index 000000000..bd101aee2 --- /dev/null +++ b/samples/ApiDemos/src/com/example/android/apis/app/JobWorkService.java @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2017 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.app; + +import android.app.Activity; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.app.job.JobParameters; +import android.app.job.JobService; +import android.app.job.JobWorkItem; +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.Process; +import android.util.Log; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.Toast; + +import com.example.android.apis.R; + +/** + * This is an example of implementing a {@link JobService} that dispatches work enqueued in + * to it. The {@link JobWorkServiceActivity} class shows how to interact with the service. + */ +//BEGIN_INCLUDE(service) +public class JobWorkService extends JobService { + private NotificationManager mNM; + private CommandProcessor mCurProcessor; + + /** + * This is a task to dequeue and process work in the background. + */ + final class CommandProcessor extends AsyncTask<Void, Void, Void> { + private final JobParameters mParams; + + CommandProcessor(JobParameters params) { + mParams = params; + } + + @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("name"); + 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; + } + } + + @Override + public void onCreate() { + mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); + Toast.makeText(this, R.string.service_created, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onDestroy() { + hideNotification(); + Toast.makeText(this, R.string.service_destroyed, Toast.LENGTH_SHORT).show(); + } + + @Override + public boolean onStartJob(JobParameters params) { + // Start task to pull work out of the queue and process it. + mCurProcessor = new CommandProcessor(params); + mCurProcessor.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + + // Allow the job to continue running while we process work. + return true; + } + + @Override + public boolean onStopJob(JobParameters params) { + // Have the processor cancel its current work. + mCurProcessor.cancel(true); + + // Tell the system to reschedule the job -- the only reason we would be here is + // because the job needs to stop for some reason before it has completed all of + // its work, so we would like it to remain to finish that work in the future. + return true; + } + + /** + * Show a notification while this service is running. + */ + private void showNotification(String text) { + // The PendingIntent to launch our activity if the user selects this notification + PendingIntent contentIntent = PendingIntent.getActivity(this, 0, + new Intent(this, JobWorkServiceActivity.class), 0); + + // Set the info for the views that show in the notification panel. + Notification.Builder noteBuilder = new Notification.Builder(this) + .setSmallIcon(R.drawable.stat_sample) // the status icon + .setTicker(text) // the status text + .setWhen(System.currentTimeMillis()) // the time stamp + .setContentTitle(getText(R.string.service_start_arguments_label)) // the label + .setContentText(text) // the contents of the entry + .setContentIntent(contentIntent); // The intent to send when the entry is clicked + + // We show this for as long as our service is processing a command. + noteBuilder.setOngoing(true); + + // Send the notification. + // We use a string id because it is a unique number. We use it later to cancel. + mNM.notify(R.string.job_service_created, noteBuilder.build()); + } + + private void hideNotification() { + mNM.cancel(R.string.service_created); + } +} +//END_INCLUDE(service) diff --git a/samples/ApiDemos/src/com/example/android/apis/app/JobWorkServiceActivity.java b/samples/ApiDemos/src/com/example/android/apis/app/JobWorkServiceActivity.java new file mode 100644 index 000000000..5155466b5 --- /dev/null +++ b/samples/ApiDemos/src/com/example/android/apis/app/JobWorkServiceActivity.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2017 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.app; + +import android.app.Activity; +import android.app.job.JobInfo; +import android.app.job.JobScheduler; +import android.app.job.JobWorkItem; +import android.content.ComponentName; +import android.content.Intent; +import android.os.Bundle; +import android.os.Process; +import android.view.View; +import android.widget.Button; + +import com.example.android.apis.R; + +/** + * Example of interacting with {@link JobWorkService}. + */ +public class JobWorkServiceActivity extends Activity { + JobScheduler mJobScheduler; + JobInfo mJobInfo; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mJobScheduler = (JobScheduler)getSystemService(JOB_SCHEDULER_SERVICE); + mJobInfo = new JobInfo.Builder(R.string.job_service_created, + new ComponentName(this, JobWorkService.class)).setOverrideDeadline(0).build(); + + setContentView(R.layout.job_work_service_activity); + + // Watch for button clicks. + Button button = findViewById(R.id.enqueue1); + button.setOnClickListener(mEnqueue1Listener); + button = findViewById(R.id.enqueue2); + button.setOnClickListener(mEnqueue2Listener); + button = findViewById(R.id.enqueue3); + button.setOnClickListener(mEnqueue3Listener); + button = findViewById(R.id.kill); + button.setOnClickListener(mKillListener); + } + + private View.OnClickListener mEnqueue1Listener = new View.OnClickListener() { + public void onClick(View v) { + mJobScheduler.enqueue(mJobInfo, new JobWorkItem( + new Intent("com.example.android.apis.ONE").putExtra("name", "One"))); + } + }; + + private View.OnClickListener mEnqueue2Listener = new View.OnClickListener() { + public void onClick(View v) { + mJobScheduler.enqueue(mJobInfo, new JobWorkItem( + new Intent("com.example.android.apis.TWO").putExtra("name", "Two"))); + } + }; + + private View.OnClickListener mEnqueue3Listener = new View.OnClickListener() { + public void onClick(View v) { + mJobScheduler.enqueue(mJobInfo, new JobWorkItem( + new Intent("com.example.android.apis.THREE").putExtra("name", "Three"))); + } + }; + + private View.OnClickListener mKillListener = new View.OnClickListener() { + public void onClick(View v) { + // This is to simulate the service being killed while it is + // running in the background. + Process.killProcess(Process.myPid()); + } + }; +} |
