blob: fbb817261f0645426cc0804047d32cd3de8279ca [file] [log] [blame]
/*
* 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}.
* <p>
* {@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<JobInfo> 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<MainActivity> 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);
}
}
}