private void cancelTask(String tag) {
   mScheduler.cancelTask(tag, TaskSchedulerService.class);
   TaskTracker task = mTasks.getTask(tag);
   if (task != null) {
     task.cancel();
     mTasks.updateTask(task);
   }
   refresh();
 }
 private void addPeriodic(
     long periodSecs, long flexSecs, int connectivity, boolean charging, boolean persistence) {
   if (flexSecs > periodSecs) {
     Toast.makeText(getActivity(), getString(R.string.scheduler_error_flex), Toast.LENGTH_SHORT)
         .show();
     return;
   }
   String tag = Long.toString(SystemClock.currentThreadTimeMillis());
   final TaskTracker taskTracker = TaskTracker.createPeriodic(tag, periodSecs, flexSecs);
   PeriodicTask periodic =
       new PeriodicTask.Builder()
           .setService(TaskSchedulerService.class)
           .setPeriod(periodSecs)
           .setFlex(flexSecs)
           .setTag(tag)
           .setRequiredNetwork(connectivity)
           .setRequiresCharging(charging)
           .setPersisted(persistence)
           .build();
   mScheduler.schedule(periodic);
   mTasks.updateTask(taskTracker);
 }
 private void addOneOff(long winStartSecs, long winEndSecs, int connectivity, boolean charging) {
   if (winStartSecs > winEndSecs) {
     Toast.makeText(getActivity(), getString(R.string.scheduler_error_window), Toast.LENGTH_SHORT)
         .show();
     return;
   }
   String tag = Long.toString(SystemClock.currentThreadTimeMillis());
   final long elapsedNowSeconds = SystemClock.elapsedRealtime() / 1000;
   final TaskTracker taskTracker =
       TaskTracker.createOneoff(
           tag, elapsedNowSeconds + winStartSecs, elapsedNowSeconds + winEndSecs);
   OneoffTask oneOff =
       new OneoffTask.Builder()
           .setService(TaskSchedulerService.class)
           .setTag(tag)
           .setExecutionWindow(winStartSecs, winEndSecs)
           .setRequiredNetwork(connectivity)
           // Persistence not yet support for Oneoffs.
           .setRequiresCharging(charging)
           .build();
   mScheduler.schedule(oneOff);
   mTasks.updateTask(taskTracker);
 }
 @Override
 public void refresh() {
   FrameLayout tasksView = (FrameLayout) getActivity().findViewById(R.id.scheduler_tasks);
   // the view might have been destroyed, in which case we don't do anything
   if (tasksView != null) {
     float density = getActivity().getResources().getDisplayMetrics().density;
     SimpleArrayMap<String, TaskTracker> tasks = mTasks.getTasks();
     LinearLayout tasksList = new LinearLayout(getActivity());
     tasksList.setOrientation(LinearLayout.VERTICAL);
     for (int i = 0; i < tasks.size(); i++) {
       final TaskTracker task = tasks.valueAt(i);
       CardView taskCard =
           (CardView)
               getActivity().getLayoutInflater().inflate(R.layout.widget_task, tasksList, false);
       ImageView taskIcon = (ImageView) taskCard.findViewById(R.id.task_icon);
       taskIcon.setImageResource(R.drawable.check_circle_grey600);
       taskIcon.setPadding(0, 0, (int) (8 * density), 0);
       TextView taskLabel = (TextView) taskCard.findViewById(R.id.task_title);
       TextView taskParams = (TextView) taskCard.findViewById(R.id.task_params);
       if (task.period == 0) {
         taskLabel.setText(getString(R.string.scheduler_oneoff, task.tag));
         taskParams.setText(
             getString(
                 R.string.scheduler_oneoff_params,
                 task.windowStartElapsedSecs,
                 task.windowStopElapsedSecs));
       } else {
         taskLabel.setText(getString(R.string.scheduler_periodic, task.tag));
         taskParams.setText(getString(R.string.scheduler_periodic_params, task.period, task.flex));
       }
       TextView taskCreatedAt = (TextView) taskCard.findViewById(R.id.task_created_at);
       taskCreatedAt.setText(
           getString(
               R.string.scheduler_secs_ago,
               DateUtils.formatElapsedTime(
                   SystemClock.elapsedRealtime() / 1000 - task.createdAtElapsedSecs)));
       TextView lastExecuted = (TextView) taskCard.findViewById(R.id.task_last_exec);
       if (task.executionTimes.isEmpty()) {
         lastExecuted.setText(getString(R.string.scheduler_na));
       } else {
         long lastExecTime = task.executionTimes.get(task.executionTimes.size() - 1);
         lastExecuted.setText(
             getString(
                 R.string.scheduler_secs_ago,
                 DateUtils.formatElapsedTime(
                     SystemClock.elapsedRealtime() / 1000 - lastExecTime)));
       }
       TextView state = (TextView) taskCard.findViewById(R.id.task_state);
       if (task.isCancelled()) {
         state.setText(getString(R.string.scheduler_cancelled));
       } else if (task.isExecuted()) {
         state.setText(getString(R.string.scheduler_executed));
       } else {
         state.setText(getString(R.string.scheduler_pending));
       }
       Button cancel = (Button) taskCard.findViewById(R.id.task_cancel);
       cancel.setVisibility(View.VISIBLE);
       cancel.setText(R.string.scheduler_cancel);
       Button delete = (Button) taskCard.findViewById(R.id.task_delete);
       delete.setVisibility(View.VISIBLE);
       delete.setText(R.string.scheduler_delete);
       if (!task.isCancelled() && (!task.isExecuted() || task.period != 0)) {
         cancel.setOnClickListener(
             new View.OnClickListener() {
               @Override
               public void onClick(View view) {
                 cancelTask(task.tag);
                 refresh();
               }
             });
         cancel.setEnabled(true);
         delete.setEnabled(false);
       } else {
         cancel.setEnabled(false);
         delete.setOnClickListener(
             new View.OnClickListener() {
               @Override
               public void onClick(View view) {
                 mTasks.deleteTask(task.tag);
                 refresh();
               }
             });
         delete.setEnabled(true);
       }
       tasksList.addView(taskCard);
     }
     tasksView.removeAllViews();
     tasksView.addView(tasksList);
   }
 }