1*90c8c64dSAndroid Build Coastguard Worker /*
2*90c8c64dSAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*90c8c64dSAndroid Build Coastguard Worker  *
4*90c8c64dSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*90c8c64dSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*90c8c64dSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*90c8c64dSAndroid Build Coastguard Worker  *
8*90c8c64dSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*90c8c64dSAndroid Build Coastguard Worker  *
10*90c8c64dSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*90c8c64dSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*90c8c64dSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*90c8c64dSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*90c8c64dSAndroid Build Coastguard Worker  * limitations under the License.
15*90c8c64dSAndroid Build Coastguard Worker  */
16*90c8c64dSAndroid Build Coastguard Worker 
17*90c8c64dSAndroid Build Coastguard Worker package com.example.android.wearable.timer;
18*90c8c64dSAndroid Build Coastguard Worker 
19*90c8c64dSAndroid Build Coastguard Worker import android.app.Activity;
20*90c8c64dSAndroid Build Coastguard Worker import android.app.AlarmManager;
21*90c8c64dSAndroid Build Coastguard Worker import android.app.Notification;
22*90c8c64dSAndroid Build Coastguard Worker import android.app.NotificationManager;
23*90c8c64dSAndroid Build Coastguard Worker import android.app.PendingIntent;
24*90c8c64dSAndroid Build Coastguard Worker import android.content.Context;
25*90c8c64dSAndroid Build Coastguard Worker import android.content.Intent;
26*90c8c64dSAndroid Build Coastguard Worker import android.content.res.Resources;
27*90c8c64dSAndroid Build Coastguard Worker import android.os.Bundle;
28*90c8c64dSAndroid Build Coastguard Worker import android.provider.AlarmClock;
29*90c8c64dSAndroid Build Coastguard Worker import android.support.wearable.view.WearableListView;
30*90c8c64dSAndroid Build Coastguard Worker import android.util.Log;
31*90c8c64dSAndroid Build Coastguard Worker import android.view.LayoutInflater;
32*90c8c64dSAndroid Build Coastguard Worker import android.view.ViewGroup;
33*90c8c64dSAndroid Build Coastguard Worker import android.widget.TextView;
34*90c8c64dSAndroid Build Coastguard Worker 
35*90c8c64dSAndroid Build Coastguard Worker import com.example.android.wearable.timer.util.Constants;
36*90c8c64dSAndroid Build Coastguard Worker import com.example.android.wearable.timer.util.TimerFormat;
37*90c8c64dSAndroid Build Coastguard Worker 
38*90c8c64dSAndroid Build Coastguard Worker /** This class sets a timer. */
39*90c8c64dSAndroid Build Coastguard Worker public class SetTimerActivity extends Activity implements WearableListView.ClickListener {
40*90c8c64dSAndroid Build Coastguard Worker 
41*90c8c64dSAndroid Build Coastguard Worker     public static final int NUMBER_OF_TIMES = 10;
42*90c8c64dSAndroid Build Coastguard Worker     public static final String TAG = "SetTimerActivity";
43*90c8c64dSAndroid Build Coastguard Worker 
44*90c8c64dSAndroid Build Coastguard Worker     private ListViewItem[] mTimeOptions = new ListViewItem[NUMBER_OF_TIMES];
45*90c8c64dSAndroid Build Coastguard Worker     private WearableListView mWearableListView;
46*90c8c64dSAndroid Build Coastguard Worker 
47*90c8c64dSAndroid Build Coastguard Worker 
48*90c8c64dSAndroid Build Coastguard Worker     @Override
onCreate(Bundle savedInstanceState)49*90c8c64dSAndroid Build Coastguard Worker     public void onCreate(Bundle savedInstanceState) {
50*90c8c64dSAndroid Build Coastguard Worker         super.onCreate(savedInstanceState);
51*90c8c64dSAndroid Build Coastguard Worker 
52*90c8c64dSAndroid Build Coastguard Worker         int paramLength = getIntent().getIntExtra(AlarmClock.EXTRA_LENGTH, 0);
53*90c8c64dSAndroid Build Coastguard Worker         if (Log.isLoggable(TAG, Log.DEBUG)) {
54*90c8c64dSAndroid Build Coastguard Worker             Log.d(TAG, "SetTimerActivity:onCreate=" + paramLength);
55*90c8c64dSAndroid Build Coastguard Worker         }
56*90c8c64dSAndroid Build Coastguard Worker         if (paramLength > 0 && paramLength <= 86400) {
57*90c8c64dSAndroid Build Coastguard Worker             long durationMillis = paramLength * 1000;
58*90c8c64dSAndroid Build Coastguard Worker             setupTimer(durationMillis);
59*90c8c64dSAndroid Build Coastguard Worker             finish();
60*90c8c64dSAndroid Build Coastguard Worker             return;
61*90c8c64dSAndroid Build Coastguard Worker         }
62*90c8c64dSAndroid Build Coastguard Worker 
63*90c8c64dSAndroid Build Coastguard Worker         Resources res = getResources();
64*90c8c64dSAndroid Build Coastguard Worker         for (int i = 0; i < NUMBER_OF_TIMES; i++) {
65*90c8c64dSAndroid Build Coastguard Worker             mTimeOptions[i] = new ListViewItem(
66*90c8c64dSAndroid Build Coastguard Worker                     res.getQuantityString(R.plurals.timer_minutes, i + 1, i + 1),
67*90c8c64dSAndroid Build Coastguard Worker                     (i + 1) * 60 * 1000);
68*90c8c64dSAndroid Build Coastguard Worker         }
69*90c8c64dSAndroid Build Coastguard Worker 
70*90c8c64dSAndroid Build Coastguard Worker         setContentView(R.layout.timer_set_timer);
71*90c8c64dSAndroid Build Coastguard Worker 
72*90c8c64dSAndroid Build Coastguard Worker         // Initialize a simple list of countdown time options.
73*90c8c64dSAndroid Build Coastguard Worker         mWearableListView = (WearableListView) findViewById(R.id.times_list_view);
74*90c8c64dSAndroid Build Coastguard Worker         mWearableListView.setAdapter(new TimerWearableListViewAdapter(this));
75*90c8c64dSAndroid Build Coastguard Worker         mWearableListView.setClickListener(this);
76*90c8c64dSAndroid Build Coastguard Worker     }
77*90c8c64dSAndroid Build Coastguard Worker 
78*90c8c64dSAndroid Build Coastguard Worker     /**
79*90c8c64dSAndroid Build Coastguard Worker      * Sets up an alarm (and an associated notification) to go off after <code>duration</code>
80*90c8c64dSAndroid Build Coastguard Worker      * milliseconds.
81*90c8c64dSAndroid Build Coastguard Worker      */
setupTimer(long duration)82*90c8c64dSAndroid Build Coastguard Worker     private void setupTimer(long duration) {
83*90c8c64dSAndroid Build Coastguard Worker         NotificationManager notifyMgr =
84*90c8c64dSAndroid Build Coastguard Worker                 ((NotificationManager) getSystemService(NOTIFICATION_SERVICE));
85*90c8c64dSAndroid Build Coastguard Worker 
86*90c8c64dSAndroid Build Coastguard Worker         // Delete dataItem and cancel a potential old countdown.
87*90c8c64dSAndroid Build Coastguard Worker         cancelCountdown(notifyMgr);
88*90c8c64dSAndroid Build Coastguard Worker 
89*90c8c64dSAndroid Build Coastguard Worker         // Build notification and set it.
90*90c8c64dSAndroid Build Coastguard Worker         notifyMgr.notify(Constants.NOTIFICATION_TIMER_COUNTDOWN, buildNotification(duration));
91*90c8c64dSAndroid Build Coastguard Worker 
92*90c8c64dSAndroid Build Coastguard Worker         // Register with the alarm manager to display a notification when the timer is done.
93*90c8c64dSAndroid Build Coastguard Worker         registerWithAlarmManager(duration);
94*90c8c64dSAndroid Build Coastguard Worker 
95*90c8c64dSAndroid Build Coastguard Worker         finish();
96*90c8c64dSAndroid Build Coastguard Worker     }
97*90c8c64dSAndroid Build Coastguard Worker 
98*90c8c64dSAndroid Build Coastguard Worker     @Override
onClick(WearableListView.ViewHolder holder)99*90c8c64dSAndroid Build Coastguard Worker     public void onClick(WearableListView.ViewHolder holder) {
100*90c8c64dSAndroid Build Coastguard Worker         long duration = mTimeOptions[holder.getPosition()].duration;
101*90c8c64dSAndroid Build Coastguard Worker         setupTimer(duration);
102*90c8c64dSAndroid Build Coastguard Worker     }
103*90c8c64dSAndroid Build Coastguard Worker 
104*90c8c64dSAndroid Build Coastguard Worker     @Override
onTopEmptyRegionClick()105*90c8c64dSAndroid Build Coastguard Worker     public void onTopEmptyRegionClick() {
106*90c8c64dSAndroid Build Coastguard Worker     }
107*90c8c64dSAndroid Build Coastguard Worker 
registerWithAlarmManager(long duration)108*90c8c64dSAndroid Build Coastguard Worker     private void registerWithAlarmManager(long duration) {
109*90c8c64dSAndroid Build Coastguard Worker         // Get the alarm manager.
110*90c8c64dSAndroid Build Coastguard Worker         AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
111*90c8c64dSAndroid Build Coastguard Worker 
112*90c8c64dSAndroid Build Coastguard Worker         // Create intent that gets fired when timer expires.
113*90c8c64dSAndroid Build Coastguard Worker         Intent intent = new Intent(Constants.ACTION_SHOW_ALARM, null, this,
114*90c8c64dSAndroid Build Coastguard Worker                 TimerNotificationService.class);
115*90c8c64dSAndroid Build Coastguard Worker         PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent,
116*90c8c64dSAndroid Build Coastguard Worker                 PendingIntent.FLAG_UPDATE_CURRENT);
117*90c8c64dSAndroid Build Coastguard Worker 
118*90c8c64dSAndroid Build Coastguard Worker         // Calculate the time when it expires.
119*90c8c64dSAndroid Build Coastguard Worker         long wakeupTime = System.currentTimeMillis() + duration;
120*90c8c64dSAndroid Build Coastguard Worker 
121*90c8c64dSAndroid Build Coastguard Worker         // Schedule an alarm.
122*90c8c64dSAndroid Build Coastguard Worker         alarm.setExact(AlarmManager.RTC_WAKEUP, wakeupTime, pendingIntent);
123*90c8c64dSAndroid Build Coastguard Worker     }
124*90c8c64dSAndroid Build Coastguard Worker 
125*90c8c64dSAndroid Build Coastguard Worker     /**
126*90c8c64dSAndroid Build Coastguard Worker      * Build a notification including different actions and other various setup and return it.
127*90c8c64dSAndroid Build Coastguard Worker      *
128*90c8c64dSAndroid Build Coastguard Worker      * @param duration the duration of the timer.
129*90c8c64dSAndroid Build Coastguard Worker      * @return the notification to display.
130*90c8c64dSAndroid Build Coastguard Worker      */
131*90c8c64dSAndroid Build Coastguard Worker 
buildNotification(long duration)132*90c8c64dSAndroid Build Coastguard Worker     private Notification buildNotification(long duration) {
133*90c8c64dSAndroid Build Coastguard Worker         // Intent to restart a timer.
134*90c8c64dSAndroid Build Coastguard Worker         Intent restartIntent = new Intent(Constants.ACTION_RESTART_ALARM, null, this,
135*90c8c64dSAndroid Build Coastguard Worker                 TimerNotificationService.class);
136*90c8c64dSAndroid Build Coastguard Worker         PendingIntent pendingIntentRestart = PendingIntent
137*90c8c64dSAndroid Build Coastguard Worker                 .getService(this, 0, restartIntent, PendingIntent.FLAG_UPDATE_CURRENT);
138*90c8c64dSAndroid Build Coastguard Worker 
139*90c8c64dSAndroid Build Coastguard Worker         // Intent to delete a timer.
140*90c8c64dSAndroid Build Coastguard Worker         Intent deleteIntent = new Intent(Constants.ACTION_DELETE_ALARM, null, this,
141*90c8c64dSAndroid Build Coastguard Worker                 TimerNotificationService.class);
142*90c8c64dSAndroid Build Coastguard Worker         PendingIntent pendingIntentDelete = PendingIntent
143*90c8c64dSAndroid Build Coastguard Worker                 .getService(this, 0, deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT);
144*90c8c64dSAndroid Build Coastguard Worker 
145*90c8c64dSAndroid Build Coastguard Worker         // Create countdown notification using a chronometer style.
146*90c8c64dSAndroid Build Coastguard Worker         return new Notification.Builder(this)
147*90c8c64dSAndroid Build Coastguard Worker                 .setSmallIcon(R.drawable.ic_cc_alarm)
148*90c8c64dSAndroid Build Coastguard Worker                 .setContentTitle(getString(R.string.timer_time_left))
149*90c8c64dSAndroid Build Coastguard Worker                 .setContentText(TimerFormat.getTimeString(duration))
150*90c8c64dSAndroid Build Coastguard Worker                 .setUsesChronometer(true)
151*90c8c64dSAndroid Build Coastguard Worker                 .setWhen(System.currentTimeMillis() + duration)
152*90c8c64dSAndroid Build Coastguard Worker                 .addAction(R.drawable.ic_cc_alarm, getString(R.string.timer_restart),
153*90c8c64dSAndroid Build Coastguard Worker                         pendingIntentRestart)
154*90c8c64dSAndroid Build Coastguard Worker                 .addAction(R.drawable.ic_cc_alarm, getString(R.string.timer_delete),
155*90c8c64dSAndroid Build Coastguard Worker                         pendingIntentDelete)
156*90c8c64dSAndroid Build Coastguard Worker                 .setDeleteIntent(pendingIntentDelete)
157*90c8c64dSAndroid Build Coastguard Worker                 .setLocalOnly(true)
158*90c8c64dSAndroid Build Coastguard Worker                 .build();
159*90c8c64dSAndroid Build Coastguard Worker     }
160*90c8c64dSAndroid Build Coastguard Worker 
161*90c8c64dSAndroid Build Coastguard Worker     /**
162*90c8c64dSAndroid Build Coastguard Worker      * Cancels an old countdown and deletes the dataItem.
163*90c8c64dSAndroid Build Coastguard Worker      *
164*90c8c64dSAndroid Build Coastguard Worker      * @param notifyMgr the notification manager.
165*90c8c64dSAndroid Build Coastguard Worker      */
cancelCountdown(NotificationManager notifyMgr)166*90c8c64dSAndroid Build Coastguard Worker     private void cancelCountdown(NotificationManager notifyMgr) {
167*90c8c64dSAndroid Build Coastguard Worker         notifyMgr.cancel(Constants.NOTIFICATION_TIMER_EXPIRED);
168*90c8c64dSAndroid Build Coastguard Worker     }
169*90c8c64dSAndroid Build Coastguard Worker 
170*90c8c64dSAndroid Build Coastguard Worker     /** Model class for the listview. */
171*90c8c64dSAndroid Build Coastguard Worker     private static class ListViewItem {
172*90c8c64dSAndroid Build Coastguard Worker 
173*90c8c64dSAndroid Build Coastguard Worker         // Duration in milliseconds.
174*90c8c64dSAndroid Build Coastguard Worker         long duration;
175*90c8c64dSAndroid Build Coastguard Worker         // Label to display.
176*90c8c64dSAndroid Build Coastguard Worker         private String label;
177*90c8c64dSAndroid Build Coastguard Worker 
ListViewItem(String label, long duration)178*90c8c64dSAndroid Build Coastguard Worker         public ListViewItem(String label, long duration) {
179*90c8c64dSAndroid Build Coastguard Worker             this.label = label;
180*90c8c64dSAndroid Build Coastguard Worker             this.duration = duration;
181*90c8c64dSAndroid Build Coastguard Worker         }
182*90c8c64dSAndroid Build Coastguard Worker 
183*90c8c64dSAndroid Build Coastguard Worker         @Override
toString()184*90c8c64dSAndroid Build Coastguard Worker         public String toString() {
185*90c8c64dSAndroid Build Coastguard Worker             return label;
186*90c8c64dSAndroid Build Coastguard Worker         }
187*90c8c64dSAndroid Build Coastguard Worker     }
188*90c8c64dSAndroid Build Coastguard Worker 
189*90c8c64dSAndroid Build Coastguard Worker     private final class TimerWearableListViewAdapter extends WearableListView.Adapter {
190*90c8c64dSAndroid Build Coastguard Worker         private final Context mContext;
191*90c8c64dSAndroid Build Coastguard Worker         private final LayoutInflater mInflater;
192*90c8c64dSAndroid Build Coastguard Worker 
TimerWearableListViewAdapter(Context context)193*90c8c64dSAndroid Build Coastguard Worker         private TimerWearableListViewAdapter(Context context) {
194*90c8c64dSAndroid Build Coastguard Worker             mContext = context;
195*90c8c64dSAndroid Build Coastguard Worker             mInflater = LayoutInflater.from(context);
196*90c8c64dSAndroid Build Coastguard Worker         }
197*90c8c64dSAndroid Build Coastguard Worker 
198*90c8c64dSAndroid Build Coastguard Worker         @Override
onCreateViewHolder(ViewGroup parent, int viewType)199*90c8c64dSAndroid Build Coastguard Worker         public WearableListView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
200*90c8c64dSAndroid Build Coastguard Worker             return new WearableListView.ViewHolder(
201*90c8c64dSAndroid Build Coastguard Worker                     mInflater.inflate(R.layout.timer_list_item, null));
202*90c8c64dSAndroid Build Coastguard Worker         }
203*90c8c64dSAndroid Build Coastguard Worker 
204*90c8c64dSAndroid Build Coastguard Worker         @Override
onBindViewHolder(WearableListView.ViewHolder holder, int position)205*90c8c64dSAndroid Build Coastguard Worker         public void onBindViewHolder(WearableListView.ViewHolder holder, int position) {
206*90c8c64dSAndroid Build Coastguard Worker             TextView view = (TextView) holder.itemView.findViewById(R.id.time_text);
207*90c8c64dSAndroid Build Coastguard Worker             view.setText(mTimeOptions[position].label);
208*90c8c64dSAndroid Build Coastguard Worker             holder.itemView.setTag(position);
209*90c8c64dSAndroid Build Coastguard Worker         }
210*90c8c64dSAndroid Build Coastguard Worker 
211*90c8c64dSAndroid Build Coastguard Worker         @Override
getItemCount()212*90c8c64dSAndroid Build Coastguard Worker         public int getItemCount() {
213*90c8c64dSAndroid Build Coastguard Worker             return NUMBER_OF_TIMES;
214*90c8c64dSAndroid Build Coastguard Worker         }
215*90c8c64dSAndroid Build Coastguard Worker     }
216*90c8c64dSAndroid Build Coastguard Worker 
217*90c8c64dSAndroid Build Coastguard Worker }
218