/* * Copyright 2013 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.jobscheduler; import android.app.Activity; import android.app.job.JobInfo; import android.app.job.JobScheduler; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.Messenger; import android.os.PersistableBundle; import android.support.annotation.ColorRes; import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.CheckBox; import android.widget.EditText; import android.widget.RadioButton; import android.widget.TextView; import android.widget.Toast; import com.example.android.jobscheduler.service.MyJobService; import java.lang.ref.WeakReference; import java.util.List; /** * Schedules and configures jobs to be executed by a {@link JobScheduler}. *

* {@link MyJobService} can send messages to this via a {@link Messenger} * that is sent in the Intent that starts the Service. */ public class MainActivity extends Activity { private static final String TAG = MainActivity.class.getSimpleName(); public static final int MSG_UNCOLOR_START = 0; public static final int MSG_UNCOLOR_STOP = 1; public static final int MSG_COLOR_START = 2; public static final int MSG_COLOR_STOP = 3; public static final String MESSENGER_INTENT_KEY = BuildConfig.APPLICATION_ID + ".MESSENGER_INTENT_KEY"; public static final String WORK_DURATION_KEY = BuildConfig.APPLICATION_ID + ".WORK_DURATION_KEY"; private EditText mDelayEditText; private EditText mDeadlineEditText; private EditText mDurationTimeEditText; private RadioButton mWiFiConnectivityRadioButton; private RadioButton mAnyConnectivityRadioButton; private CheckBox mRequiresChargingCheckBox; private CheckBox mRequiresIdleCheckbox; private ComponentName mServiceComponent; private int mJobId = 0; // Handler for incoming messages from the service. private IncomingMessageHandler mHandler; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.sample_main); // Set up UI. mDelayEditText = (EditText) findViewById(R.id.delay_time); mDurationTimeEditText = (EditText) findViewById(R.id.duration_time); mDeadlineEditText = (EditText) findViewById(R.id.deadline_time); mWiFiConnectivityRadioButton = (RadioButton) findViewById(R.id.checkbox_unmetered); mAnyConnectivityRadioButton = (RadioButton) findViewById(R.id.checkbox_any); mRequiresChargingCheckBox = (CheckBox) findViewById(R.id.checkbox_charging); mRequiresIdleCheckbox = (CheckBox) findViewById(R.id.checkbox_idle); mServiceComponent = new ComponentName(this, MyJobService.class); mHandler = new IncomingMessageHandler(this); } @Override protected void onStop() { // A service can be "started" and/or "bound". In this case, it's "started" by this Activity // and "bound" to the JobScheduler (also called "Scheduled" by the JobScheduler). This call // to stopService() won't prevent scheduled jobs to be processed. However, failing // to call stopService() would keep it alive indefinitely. stopService(new Intent(this, MyJobService.class)); super.onStop(); } @Override protected void onStart() { super.onStart(); // Start service and provide it a way to communicate with this class. Intent startServiceIntent = new Intent(this, MyJobService.class); Messenger messengerIncoming = new Messenger(mHandler); startServiceIntent.putExtra(MESSENGER_INTENT_KEY, messengerIncoming); startService(startServiceIntent); } /** * Executed when user clicks on SCHEDULE JOB. */ public void scheduleJob(View v) { JobInfo.Builder builder = new JobInfo.Builder(mJobId++, mServiceComponent); String delay = mDelayEditText.getText().toString(); if (!TextUtils.isEmpty(delay)) { builder.setMinimumLatency(Long.valueOf(delay) * 1000); } String deadline = mDeadlineEditText.getText().toString(); if (!TextUtils.isEmpty(deadline)) { builder.setOverrideDeadline(Long.valueOf(deadline) * 1000); } boolean requiresUnmetered = mWiFiConnectivityRadioButton.isChecked(); boolean requiresAnyConnectivity = mAnyConnectivityRadioButton.isChecked(); if (requiresUnmetered) { builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); } else if (requiresAnyConnectivity) { builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); } builder.setRequiresDeviceIdle(mRequiresIdleCheckbox.isChecked()); builder.setRequiresCharging(mRequiresChargingCheckBox.isChecked()); // Extras, work duration. PersistableBundle extras = new PersistableBundle(); String workDuration = mDurationTimeEditText.getText().toString(); if (TextUtils.isEmpty(workDuration)) { workDuration = "1"; } extras.putLong(WORK_DURATION_KEY, Long.valueOf(workDuration) * 1000); builder.setExtras(extras); // Schedule job Log.d(TAG, "Scheduling job"); JobScheduler tm = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); tm.schedule(builder.build()); } /** * Executed when user clicks on CANCEL ALL. */ public void cancelAllJobs(View v) { JobScheduler tm = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); tm.cancelAll(); Toast.makeText(MainActivity.this, R.string.all_jobs_cancelled, Toast.LENGTH_SHORT).show(); } /** * Executed when user clicks on FINISH LAST TASK. */ public void finishJob(View v) { JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); List allPendingJobs = jobScheduler.getAllPendingJobs(); if (allPendingJobs.size() > 0) { // Finish the last one int jobId = allPendingJobs.get(0).getId(); jobScheduler.cancel(jobId); Toast.makeText( MainActivity.this, String.format(getString(R.string.cancelled_job), jobId), Toast.LENGTH_SHORT).show(); } else { Toast.makeText( MainActivity.this, getString(R.string.no_jobs_to_cancel), Toast.LENGTH_SHORT).show(); } } /** * A {@link Handler} allows you to send messages associated with a thread. A {@link Messenger} * uses this handler to communicate from {@link MyJobService}. It's also used to make * the start and stop views blink for a short period of time. */ private static class IncomingMessageHandler extends Handler { // Prevent possible leaks with a weak reference. private WeakReference mActivity; IncomingMessageHandler(MainActivity activity) { super(/* default looper */); this.mActivity = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) { MainActivity mainActivity = mActivity.get(); if (mainActivity == null) { // Activity is no longer available, exit. return; } View showStartView = mainActivity.findViewById(R.id.onstart_textview); View showStopView = mainActivity.findViewById(R.id.onstop_textview); Message m; switch (msg.what) { /* * Receives callback from the service when a job has landed * on the app. Turns on indicator and sends a message to turn it off after * a second. */ case MSG_COLOR_START: // Start received, turn on the indicator and show text. showStartView.setBackgroundColor(getColor(R.color.start_received)); updateParamsTextView(msg.obj, "started"); // Send message to turn it off after a second. m = Message.obtain(this, MSG_UNCOLOR_START); sendMessageDelayed(m, 1000L); break; /* * Receives callback from the service when a job that previously landed on the * app must stop executing. Turns on indicator and sends a message to turn it * off after two seconds. */ case MSG_COLOR_STOP: // Stop received, turn on the indicator and show text. showStopView.setBackgroundColor(getColor(R.color.stop_received)); updateParamsTextView(msg.obj, "stopped"); // Send message to turn it off after a second. m = obtainMessage(MSG_UNCOLOR_STOP); sendMessageDelayed(m, 2000L); break; case MSG_UNCOLOR_START: showStartView.setBackgroundColor(getColor(R.color.none_received)); updateParamsTextView(null, ""); break; case MSG_UNCOLOR_STOP: showStopView.setBackgroundColor(getColor(R.color.none_received)); updateParamsTextView(null, ""); break; } } private void updateParamsTextView(@Nullable Object jobId, String action) { TextView paramsTextView = (TextView) mActivity.get().findViewById(R.id.task_params); if (jobId == null) { paramsTextView.setText(""); return; } String jobIdText = String.valueOf(jobId); paramsTextView.setText(String.format("Job ID %s %s", jobIdText, action)); } private int getColor(@ColorRes int color) { return mActivity.get().getResources().getColor(color); } } }