1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.deskclock.data; 18 19 import android.app.Notification; 20 import android.app.PendingIntent; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.res.Resources; 24 import android.os.SystemClock; 25 import android.support.annotation.DrawableRes; 26 import android.support.annotation.StringRes; 27 import android.support.v4.app.NotificationCompat.Action; 28 import android.support.v4.app.NotificationCompat.Builder; 29 import android.support.v4.content.ContextCompat; 30 import android.support.v7.app.NotificationCompat; 31 import android.widget.RemoteViews; 32 33 import com.android.deskclock.R; 34 import com.android.deskclock.Utils; 35 import com.android.deskclock.events.Events; 36 import com.android.deskclock.stopwatch.StopwatchService; 37 38 import java.util.ArrayList; 39 import java.util.List; 40 41 import static android.view.View.GONE; 42 import static android.view.View.VISIBLE; 43 44 /** 45 * Builds notification to reflect the latest state of the stopwatch and recorded laps. 46 */ 47 class StopwatchNotificationBuilder { 48 build(Context context, NotificationModel nm, Stopwatch stopwatch)49 public Notification build(Context context, NotificationModel nm, Stopwatch stopwatch) { 50 @StringRes final int eventLabel = R.string.label_notification; 51 52 // Intent to load the app when the notification is tapped. 53 final Intent showApp = new Intent(context, StopwatchService.class) 54 .setAction(StopwatchService.ACTION_SHOW_STOPWATCH) 55 .putExtra(Events.EXTRA_EVENT_LABEL, eventLabel); 56 57 final PendingIntent pendingShowApp = PendingIntent.getService(context, 0, showApp, 58 PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT); 59 60 // Compute some values required below. 61 final boolean running = stopwatch.isRunning(); 62 final String pname = context.getPackageName(); 63 final Resources res = context.getResources(); 64 final long base = SystemClock.elapsedRealtime() - stopwatch.getTotalTime(); 65 66 final RemoteViews content = new RemoteViews(pname, R.layout.chronometer_notif_content); 67 content.setChronometer(R.id.chronometer, base, null, running); 68 69 final List<Action> actions = new ArrayList<>(2); 70 71 if (running) { 72 // Left button: Pause 73 final Intent pause = new Intent(context, StopwatchService.class) 74 .setAction(StopwatchService.ACTION_PAUSE_STOPWATCH) 75 .putExtra(Events.EXTRA_EVENT_LABEL, eventLabel); 76 77 @DrawableRes final int icon1 = R.drawable.ic_pause_24dp; 78 final CharSequence title1 = res.getText(R.string.sw_pause_button); 79 final PendingIntent intent1 = Utils.pendingServiceIntent(context, pause); 80 actions.add(new Action.Builder(icon1, title1, intent1).build()); 81 82 // Right button: Add Lap 83 if (DataModel.getDataModel().canAddMoreLaps()) { 84 final Intent lap = new Intent(context, StopwatchService.class) 85 .setAction(StopwatchService.ACTION_LAP_STOPWATCH) 86 .putExtra(Events.EXTRA_EVENT_LABEL, eventLabel); 87 88 @DrawableRes final int icon2 = R.drawable.ic_sw_lap_24dp; 89 final CharSequence title2 = res.getText(R.string.sw_lap_button); 90 final PendingIntent intent2 = Utils.pendingServiceIntent(context, lap); 91 actions.add(new Action.Builder(icon2, title2, intent2).build()); 92 } 93 94 // Show the current lap number if any laps have been recorded. 95 final int lapCount = DataModel.getDataModel().getLaps().size(); 96 if (lapCount > 0) { 97 final int lapNumber = lapCount + 1; 98 final String lap = res.getString(R.string.sw_notification_lap_number, lapNumber); 99 content.setTextViewText(R.id.state, lap); 100 content.setViewVisibility(R.id.state, VISIBLE); 101 } else { 102 content.setViewVisibility(R.id.state, GONE); 103 } 104 } else { 105 // Left button: Start 106 final Intent start = new Intent(context, StopwatchService.class) 107 .setAction(StopwatchService.ACTION_START_STOPWATCH) 108 .putExtra(Events.EXTRA_EVENT_LABEL, eventLabel); 109 110 @DrawableRes final int icon1 = R.drawable.ic_start_24dp; 111 final CharSequence title1 = res.getText(R.string.sw_start_button); 112 final PendingIntent intent1 = Utils.pendingServiceIntent(context, start); 113 actions.add(new Action.Builder(icon1, title1, intent1).build()); 114 115 // Right button: Reset (dismisses notification and resets stopwatch) 116 final Intent reset = new Intent(context, StopwatchService.class) 117 .setAction(StopwatchService.ACTION_RESET_STOPWATCH) 118 .putExtra(Events.EXTRA_EVENT_LABEL, eventLabel); 119 120 @DrawableRes final int icon2 = R.drawable.ic_reset_24dp; 121 final CharSequence title2 = res.getText(R.string.sw_reset_button); 122 final PendingIntent intent2 = Utils.pendingServiceIntent(context, reset); 123 actions.add(new Action.Builder(icon2, title2, intent2).build()); 124 125 // Indicate the stopwatch is paused. 126 content.setTextViewText(R.id.state, res.getString(R.string.swn_paused)); 127 content.setViewVisibility(R.id.state, VISIBLE); 128 } 129 130 final Builder notification = new NotificationCompat.Builder(context) 131 .setLocalOnly(true) 132 .setOngoing(running) 133 .setCustomContentView(content) 134 .setContentIntent(pendingShowApp) 135 .setAutoCancel(stopwatch.isPaused()) 136 .setPriority(Notification.PRIORITY_MAX) 137 .setSmallIcon(R.drawable.stat_notify_stopwatch) 138 .setStyle(new NotificationCompat.DecoratedCustomViewStyle()) 139 .setColor(ContextCompat.getColor(context, R.color.default_background)); 140 141 if (Utils.isNOrLater()) { 142 notification.setGroup(nm.getStopwatchNotificationGroupKey()); 143 } 144 145 for (Action action : actions) { 146 notification.addAction(action); 147 } 148 149 return notification.build(); 150 } 151 } 152