TimerReceiver.java revision 184aa695ef173081a692be38d9b23560ad34b789
1815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson/* 2815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson * Copyright (C) 2012 The Android Open Source Project 3815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson * 4815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson * Licensed under the Apache License, Version 2.0 (the "License"); 5815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson * you may not use this file except in compliance with the License. 6815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson * You may obtain a copy of the License at 7815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson * 8815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson * http://www.apache.org/licenses/LICENSE-2.0 9815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson * 10815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson * Unless required by applicable law or agreed to in writing, software 11815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson * distributed under the License is distributed on an "AS IS" BASIS, 12815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson * See the License for the specific language governing permissions and 14815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson * limitations under the License. 15815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson */ 16815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson 17815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelsonpackage com.android.deskclock.timer; 18815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson 19dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelsonimport android.app.AlarmManager; 20733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultasimport android.app.KeyguardManager; 21815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelsonimport android.app.Notification; 22b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzsteinimport android.app.NotificationManager; 23815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelsonimport android.app.PendingIntent; 24815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelsonimport android.content.BroadcastReceiver; 25815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelsonimport android.content.Context; 26815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelsonimport android.content.Intent; 27dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelsonimport android.content.SharedPreferences; 28dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelsonimport android.preference.PreferenceManager; 29815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelsonimport android.util.Log; 30815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson 31733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultasimport com.android.deskclock.AlarmAlertFullScreen; 32dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelsonimport com.android.deskclock.DeskClock; 33b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzsteinimport com.android.deskclock.R; 345cacdd0b56950cf6a5f28e780ed07625a81bde53Isaac Katzenelsonimport com.android.deskclock.TimerRingService; 35dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson 36dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelsonimport java.util.ArrayList; 37dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelsonimport java.util.Iterator; 38dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson 39815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelsonpublic class TimerReceiver extends BroadcastReceiver { 40815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson private static final String TAG = "TimerReceiver"; 41815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson 422d0cd10f351ac3c0d04850f019d8803d100b2a1aSam Blitzstein private static final int IN_USE_NOTIFICATION_ID = 2; 43b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 44dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson ArrayList<TimerObj> mTimers; 45dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson 46dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson @Override 47815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson public void onReceive(final Context context, final Intent intent) { 48b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein int timer; 49b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein String actionType = intent.getAction(); 50815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson 51b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein // Get the updated timers data. 52b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (mTimers == null) { 53b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein mTimers = new ArrayList<TimerObj> (); 54b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 55b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 56b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein TimerObj.getTimersFromSharedPrefs(prefs, mTimers); 57815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson 58815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson 59b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (intent.hasExtra(Timers.TIMER_INTENT_EXTRA)) { 60b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein // Get the alarm out of the Intent 61b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein timer = intent.getIntExtra(Timers.TIMER_INTENT_EXTRA, -1); 62b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (timer == -1) { 63b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein Log.d(TAG, " got intent without Timer data: "+actionType); 64b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 65b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } else if (Timers.NOTIF_IN_USE_SHOW.equals(actionType)){ 66b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein showInUseNotification(context); 67b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein return; 68b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } else if (Timers.NOTIF_IN_USE_CANCEL.equals(actionType)) { 69b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein cancelInUseNotification(context); 70b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein return; 71b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } else { 72b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein // No data to work with, do nothing 73b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein Log.d(TAG, " got intent without Timer data"); 74b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein return; 75b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 76b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 77b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein TimerObj t = Timers.findTimer(mTimers, timer); 78815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson 79b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (intent.getBooleanExtra(Timers.UPDATE_NOTIFICATION, false)) { 80b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (Timers.TIMER_STOP.equals(actionType)) { 81b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (t == null) { 82b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein Log.d(TAG, "timer not found in list - can't stop it."); 83b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein return; 84b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 85b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein t.mState = TimerObj.STATE_DONE; 86b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein t.writeToSharedPref(prefs); 87b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein SharedPreferences.Editor editor = prefs.edit(); 88b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein editor.putBoolean(Timers.FROM_NOTIFICATION, true); 89b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein editor.putLong(Timers.NOTIF_TIME, System.currentTimeMillis()); 90b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein editor.putInt(Timers.NOTIF_ID, timer); 91b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein editor.apply(); 92dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson 93b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein stopRingtoneIfNoTimesup(context); 94dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson 95b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein Intent activityIntent = new Intent(context, DeskClock.class); 96b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 97b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein activityIntent.putExtra(DeskClock.SELECT_TAB_INTENT_EXTRA, DeskClock.TIMER_TAB_INDEX); 98b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein context.startActivity(activityIntent); 99b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 100b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein return; 101b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 102b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 103b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (Timers.TIMES_UP.equals(actionType)) { 104dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson // Find the timer (if it doesn't exists, it was probably deleted). 105dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson if (t == null) { 106dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson Log.d(TAG, " timer not found in list - do nothing"); 107dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson return; 108dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson } 109dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson 110dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson t.mState = TimerObj.STATE_TIMESUP; 111dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson t.writeToSharedPref(prefs); 112733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultas // Play ringtone by using TimerRingService service with a default alarm. 113dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson Log.d(TAG, "playing ringtone"); 114dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson Intent si = new Intent(); 1155cacdd0b56950cf6a5f28e780ed07625a81bde53Isaac Katzenelson si.setClass(context, TimerRingService.class); 116dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson context.startService(si); 117dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson 118b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein // Start notification for buzzing alarm. 119b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein Intent broadcastIntent = new Intent(); 120b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein broadcastIntent.putExtra(Timers.TIMER_INTENT_EXTRA, t.mTimerId); 121b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein broadcastIntent.setAction(Timers.TIMER_STOP); 122b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein broadcastIntent.putExtra(Timers.UPDATE_NOTIFICATION, true); 123b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein PendingIntent pendingBroadcastIntent = PendingIntent.getBroadcast( 124b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein context, 0, broadcastIntent, 0); 125b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein String label = t.mLabel == "" ? context.getString(R.string.timer_notification_label) : 126b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein t.mLabel; 127b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein String contentText = context.getString(R.string.timer_times_up); 128b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein showCollapsedNotification(context, label, contentText, Notification.PRIORITY_MAX, 129184aa695ef173081a692be38d9b23560ad34b789Sam Blitzstein pendingBroadcastIntent, t.mTimerId, true); 1302d0cd10f351ac3c0d04850f019d8803d100b2a1aSam Blitzstein cancelInUseNotification(context); 131b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 132733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultas KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); 133733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultas if (!km.inKeyguardRestrictedInputMode()) { 134733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultas // Start the DeskClock Activity 135733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultas Intent i = new Intent(); 136733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultas i.setClass(context, DeskClock.class); 137733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultas i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 138733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultas i.putExtra(DeskClock.SELECT_TAB_INTENT_EXTRA, DeskClock.TIMER_TAB_INDEX); 139733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultas context.startActivity(i); 140733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultas } else { 141733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultas // Start the TimerAlertFullScreen activity. 142733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultas Intent timersAlert = new Intent(context, TimerAlertFullScreen.class); 143733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultas timersAlert.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_USER_ACTION); 144733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultas context.startActivity(timersAlert); 145733afe52e37148f2f1d36436c1a1eadcad5b471bRobyn Coultas } 146dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson 147b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein // Cancel the inuse notification if none are inuse. 148b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (getNextRunningTimer(mTimers, false, System.currentTimeMillis()) == null) { 149b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein // Found no running timers. 150b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein cancelInUseNotification(context); 151dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson } 152b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 153b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } else if (Timers.TIMER_RESET.equals(actionType) 154b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein || Timers.DELETE_TIMER.equals(actionType) 155b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein || Timers.TIMER_DONE.equals(actionType)) { 156b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein // Stop Ringtone if all timers are not in timesup status 157b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein stopRingtoneIfNoTimesup(context); 158dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson } 159dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson // Update the next "Times up" alarm 160b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein updateNextTimesup(context); 161b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 162b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 163b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein private void stopRingtoneIfNoTimesup(final Context context) { 164b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (Timers.findExpiredTimer(mTimers) == null) { 165b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein // Stop ringtone 166b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein Log.d(TAG, "stopping ringtone"); 167b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein Intent si = new Intent(); 168b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein si.setClass(context, TimerRingService.class); 169b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein context.stopService(si); 170b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 171815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson } 172dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson 173dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson // Scan all timers and find the one that will expire next. 174dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson // Tell AlarmManager to send a "Time's up" message to this receiver when this timer expires. 175dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson // If no timer exists, clear "time's up" message. 176dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson private void updateNextTimesup(Context context) { 177b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein TimerObj t = getNextRunningTimer(mTimers, false, System.currentTimeMillis()); 178b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein long nextTimesup = (t == null) ? -1 : t.getTimesupTime(); 179b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein int timerId = (t == null) ? -1 : t.mTimerId; 180dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson 181dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson Intent intent = new Intent(); 182dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson intent.setAction(Timers.TIMES_UP); 183dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson intent.setClass(context, TimerReceiver.class); 184b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (!mTimers.isEmpty()) { 185b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein intent.putExtra(Timers.TIMER_INTENT_EXTRA, timerId); 186dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson } 187dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson AlarmManager mngr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); 188dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson PendingIntent p = PendingIntent.getBroadcast(context, 189dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson 0, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT); 190b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (t != null) { 191dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson mngr.set(AlarmManager.RTC_WAKEUP, nextTimesup, p); 192dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson Log.d(TAG,"Setting times up to " + nextTimesup); 193dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson } else { 194dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson Log.d(TAG,"canceling times up"); 195dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson mngr.cancel(p); 196dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson } 197dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson } 198dfb182f455aa07eb7319d32df6d9a14492884e2fIsaac Katzenelson 199b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein private void showInUseNotification(final Context context) { 200b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 201b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein boolean appOpen = prefs.getBoolean(Timers.NOTIF_APP_OPEN, false); 202b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein ArrayList<TimerObj> timersInUse = Timers.timersInUse(mTimers); 203b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein int numTimersInUse = timersInUse.size(); 204b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 205b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (appOpen || numTimersInUse == 0) { 206b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein return; 207b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 208b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 209b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein String title, contentText; 210b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein Long nextBroadcastTime = null; 2112d0cd10f351ac3c0d04850f019d8803d100b2a1aSam Blitzstein long now = System.currentTimeMillis(); 212b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (timersInUse.size() == 1) { 213b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein TimerObj timer = timersInUse.get(0); 214b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein String label = timer.mLabel == "" ? context.getString(R.string.timer_notification_label) 215b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein : timer.mLabel; 216b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein title = timer.isTicking() ? label : context.getString(R.string.timer_stopped); 217b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein long timeLeft = timer.isTicking() ? timer.getTimesupTime() - now : timer.mTimeLeft; 218b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein contentText = buildTimeRemaining(context, timeLeft); 219b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (timeLeft > 60) { 220b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein nextBroadcastTime = getBroadcastTime(now, timeLeft); 221b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 222b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } else { 223b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein TimerObj timer = getNextRunningTimer(timersInUse, false, now); 224b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (timer == null) { 225b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein // No running timers. 226b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein title = String.format( 227b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein context.getString(R.string.timers_stopped), numTimersInUse); 228b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein contentText = context.getString(R.string.all_timers_stopped_notif); 229b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } else { 230b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein // We have at least one timer running and other timers stopped. 231b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein title = String.format( 232b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein context.getString(R.string.timers_in_use), numTimersInUse); 233b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein long completionTime = timer.getTimesupTime(); 234b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein long timeLeft = completionTime - now; 235b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein contentText = String.format(context.getString(R.string.next_timer_notif), 236b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein buildTimeRemaining(context, timeLeft)); 237b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (timeLeft <= 60) { 238b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein TimerObj timerWithUpdate = getNextRunningTimer(timersInUse, true, now); 239b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (timerWithUpdate != null) { 240b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein completionTime = timerWithUpdate.getTimesupTime(); 241b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein timeLeft = completionTime - now; 242b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein nextBroadcastTime = getBroadcastTime(now, timeLeft); 243b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 244b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } else { 245b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein nextBroadcastTime = getBroadcastTime(now, timeLeft); 246b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 247b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 248b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 249b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein showCollapsedNotificationWithNext(context, title, contentText, nextBroadcastTime); 250b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 251b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 252b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein private long getBroadcastTime(long now, long timeUntilBroadcast) { 253b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein long seconds = timeUntilBroadcast / 1000; 254b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein seconds = seconds - ( (seconds / 60) * 60 ); 255b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein return now + (seconds * 1000); 256b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 257b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 258b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein private void showCollapsedNotificationWithNext( 259b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein final Context context, String title, String text, Long nextBroadcastTime) { 260b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein Intent activityIntent = new Intent(context, DeskClock.class); 261b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 262b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein activityIntent.putExtra(DeskClock.SELECT_TAB_INTENT_EXTRA, DeskClock.TIMER_TAB_INDEX); 263b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein PendingIntent pendingActivityIntent = PendingIntent.getActivity(context, 0, activityIntent, 264b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT); 265b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein showCollapsedNotification(context, title, text, Notification.PRIORITY_HIGH, 266184aa695ef173081a692be38d9b23560ad34b789Sam Blitzstein pendingActivityIntent, IN_USE_NOTIFICATION_ID, false); 267b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 268b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (nextBroadcastTime == null) { 269b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein return; 270b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 271b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein Intent nextBroadcast = new Intent(); 272b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein nextBroadcast.setAction(Timers.NOTIF_IN_USE_SHOW); 273b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein PendingIntent pendingNextBroadcast = 274b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein PendingIntent.getBroadcast(context, 0, nextBroadcast, 0); 275b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein AlarmManager alarmManager = 276b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 277b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein alarmManager.set(AlarmManager.RTC, nextBroadcastTime, pendingNextBroadcast); 278b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 279b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 280b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein private void showCollapsedNotification(final Context context, String title, String text, 281184aa695ef173081a692be38d9b23560ad34b789Sam Blitzstein int priority, PendingIntent pendingIntent, int notificationId, boolean showTicker) { 282184aa695ef173081a692be38d9b23560ad34b789Sam Blitzstein Notification.Builder builder = new Notification.Builder(context) 283b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein .setAutoCancel(false) 284b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein .setContentTitle(title) 285b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein .setContentText(text) 286b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein .setDeleteIntent(pendingIntent) 287b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein .setOngoing(true) 288b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein .setPriority(priority) 289b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein .setShowWhen(false) 290184aa695ef173081a692be38d9b23560ad34b789Sam Blitzstein .setSmallIcon(R.drawable.stat_notify_timer); 291184aa695ef173081a692be38d9b23560ad34b789Sam Blitzstein if (showTicker) { 292184aa695ef173081a692be38d9b23560ad34b789Sam Blitzstein builder.setTicker(text); 293184aa695ef173081a692be38d9b23560ad34b789Sam Blitzstein } 294184aa695ef173081a692be38d9b23560ad34b789Sam Blitzstein 295184aa695ef173081a692be38d9b23560ad34b789Sam Blitzstein Notification notification = builder.build(); 296b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein notification.contentIntent = pendingIntent; 297b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein NotificationManager notificationManager = 298b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 299b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein notificationManager.notify(notificationId, notification); 300b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 301b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 302b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein private String buildTimeRemaining(Context context, long timeLeft) { 303b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (timeLeft < 0) { 304b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein // We should never be here... 305b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein Log.v(TAG, "Will not show notification for timer already expired."); 306b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein return null; 307b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 308b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 309b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein long hundreds, seconds, minutes, hours; 310b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein seconds = timeLeft / 1000; 311b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein minutes = seconds / 60; 312b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein seconds = seconds - minutes * 60; 313b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein hours = minutes / 60; 314b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein minutes = minutes - hours * 60; 315b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (hours > 99) { 316b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein hours = 0; 317b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 318b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 319b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein String hourSeq = (hours == 0) ? "" : 320b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein ( (hours == 1) ? context.getString(R.string.hour) : 321b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein context.getString(R.string.hours, Long.toString(hours)) ); 322b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein String minSeq = (minutes == 0) ? "" : 323b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein ( (minutes == 1) ? context.getString(R.string.minute) : 324b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein context.getString(R.string.minutes, Long.toString(minutes)) ); 325b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 326b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein boolean dispHour = hours > 0; 327b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein boolean dispMinute = minutes > 0; 328b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein int index = (dispHour ? 1 : 0) | (dispMinute ? 2 : 0); 329b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein String[] formats = context.getResources().getStringArray(R.array.timer_notifications); 330b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein return String.format(formats[index], hourSeq, minSeq); 331b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 332b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 333b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein private TimerObj getNextRunningTimer( 334b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein ArrayList<TimerObj> timers, boolean requireNextUpdate, long now) { 335b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein long nextTimesup = Long.MAX_VALUE; 336b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein boolean nextTimerFound = false; 337b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein Iterator<TimerObj> i = timers.iterator(); 338b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein TimerObj t = null; 339b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein while(i.hasNext()) { 340b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein TimerObj tmp = i.next(); 341b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (tmp.mState == TimerObj.STATE_RUNNING) { 342b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein long timesupTime = tmp.getTimesupTime(); 343b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein long timeLeft = timesupTime - now; 344b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (timesupTime < nextTimesup && (!requireNextUpdate || timeLeft > 60) ) { 345b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein nextTimesup = timesupTime; 346b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein nextTimerFound = true; 347b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein t = tmp; 348b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 349b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 350b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 351b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein if (nextTimerFound) { 352b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein return t; 353b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } else { 354b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein return null; 355b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 356b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 357b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein 358b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein private void cancelInUseNotification(final Context context) { 359b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein NotificationManager notificationManager = 360b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 361b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein notificationManager.cancel(IN_USE_NOTIFICATION_ID); 362b6a815a52fd31a96b51e51ef6275a68bed73c2c5Sam Blitzstein } 363815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelson}