- If user is in a phone call, they're already awake, so ignore the alarm and reset it for tomorrow.

This commit is contained in:
Timothy Allen 2014-04-13 23:59:16 +02:00
parent 4c1e6a5a1a
commit 36b796fd13
4 changed files with 34 additions and 51 deletions

View File

@ -50,6 +50,8 @@
<!-- permission required to read contacts --> <!-- permission required to read contacts -->
<uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.READ_CONTACTS" />
<!-- permission required to tell if a phone call is active -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- permission required to set an alarm --> <!-- permission required to set an alarm -->
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" /> <uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<!-- permission required to Send SMS --> <!-- permission required to Send SMS -->

View File

@ -27,10 +27,7 @@ public class AlarmKlaxon {
/** /**
* *
* TODO allow user to select alarm tone * TODO allow user to select alarm tone
* TODO add raw alarm tone to use as fallback * TODO prevent alarm from being ignored or snoozing if a call comes in?
* TODO add in-call alarm tone
* TODO lower volume if in a call
* TODO cancel noise if a call comes in (add TelephonyManager listener which cancels the alert but calls the notification)
* *
*/ */
@ -40,6 +37,7 @@ public class AlarmKlaxon {
telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
initialCallState = telephonyManager.getCallState(); initialCallState = telephonyManager.getCallState();
boolean inTelephoneCall = initialCallState != TelephonyManager.CALL_STATE_IDLE;
phoneStateListener = new PhoneStateListener() { phoneStateListener = new PhoneStateListener() {
@Override @Override
public void onCallStateChanged(int state, String ignored) { public void onCallStateChanged(int state, String ignored) {
@ -49,12 +47,10 @@ public class AlarmKlaxon {
// we don't kill the alarm during a call. // we don't kill the alarm during a call.
if (state != TelephonyManager.CALL_STATE_IDLE && state != initialCallState) { if (state != TelephonyManager.CALL_STATE_IDLE && state != initialCallState) {
stopAudio(context); stopAudio(context);
// TODO stop alarm from snoozing or turning off?
} }
} }
}; };
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
boolean inTelephoneCall = initialCallState != TelephonyManager.CALL_STATE_IDLE;
// TODO select alarm tone? // TODO select alarm tone?
// Use the default alarm tone... // Use the default alarm tone...
@ -65,7 +61,7 @@ public class AlarmKlaxon {
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override @Override
public boolean onError(MediaPlayer mp, int what, int extra) { public boolean onError(MediaPlayer mp, int what, int extra) {
Log.e("AlarmAlertActivity", "Error occurred while playing audio. Stopping alarm."); Log.e("AlarmKlaxon", "Error occurred while playing audio. Stopping alarm.");
stopAudio(context); stopAudio(context);
return true; return true;
} }
@ -90,10 +86,9 @@ public class AlarmKlaxon {
startAudio(context); startAudio(context);
} catch (Exception ex2) { } catch (Exception ex2) {
// At this point we just don't play anything. // At this point we just don't play anything.
Log.e("AlarmAlertActivity", "Failed to play fallback ringtone", ex2); Log.e("AlarmKlaxon", "Failed to play fallback ringtone", ex2);
} }
} }
} }
public static void stop(final Context context) { public static void stop(final Context context) {
@ -138,5 +133,4 @@ public class AlarmKlaxon {
afd.close(); afd.close();
} }
} }
} }

View File

@ -17,11 +17,6 @@ import android.widget.Toast;
import java.io.IOException; import java.io.IOException;
import java.util.Calendar; import java.util.Calendar;
/**
* TODO change alarm state if a phone call comes in
*/
public class AlarmReceiver extends BroadcastReceiver { public class AlarmReceiver extends BroadcastReceiver {
private static final int SNOOZE_TIME = 1000*60; //1000*60*5; // Snooze for 5 minutes if need be private static final int SNOOZE_TIME = 1000*60; //1000*60*5; // Snooze for 5 minutes if need be
private static final int ALERT_LIFE = 1000*10; //TODO 1000*60*2; // 2 minutes private static final int ALERT_LIFE = 1000*10; //TODO 1000*60*2; // 2 minutes
@ -52,44 +47,38 @@ public class AlarmReceiver extends BroadcastReceiver {
// Cancel the pre-alarm notification, if it exists // Cancel the pre-alarm notification, if it exists
context.stopService(new Intent(context, PreAlarmNotify.class)); context.stopService(new Intent(context, PreAlarmNotify.class));
// TODO: delay the alarm if user is in a phone call, until the phone call ends // If dialing, active in a phone call, or on hold, don't bother with the alarm, just reset it for tomorrow
telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
// If in a phone call, delay the alarm until the call ends if (telephonyManager.getCallState() != TelephonyManager.CALL_STATE_OFFHOOK) {
while (telephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
try { // Set a grace period alarm to send SMS
Thread.sleep(1000); Calendar graceCal = Calendar.getInstance();
} catch (InterruptedException e) { graceCal.set(Calendar.SECOND, 0);
Log.e("AlarmReceiver", "Error sleeping: " + e.toString()); graceCal.add(Calendar.MINUTE, gracePeriod);
graceManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent graceIntent = new Intent(context, GraceReceiver.class);
gracePendingIntent = PendingIntent.getBroadcast(context, MainActivity.GRACE_REQUEST, graceIntent, 0);
graceManager.cancel(gracePendingIntent);
if (Build.VERSION.SDK_INT >= 19) {
graceManager.setExact(AlarmManager.RTC_WAKEUP, graceCal.getTimeInMillis(), gracePendingIntent);
} else {
graceManager.set(AlarmManager.RTC_WAKEUP, graceCal.getTimeInMillis(), gracePendingIntent);
} }
Log.d("AlarmReceiver", "Setting grace alarm for " + MainActivity.debugDate(graceCal));
// Calculate when the grace period (converted from minutes to milliseconds) ends
graceEndTime = System.currentTimeMillis() + (gracePeriod * 60 * 1000);
// Set up intents for later use
notifyIntent = new Intent(context, AlarmNotify.class);
alertActivityIntent = new Intent(context, AlarmAlertActivity.class);
alertActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
// Allow user to acknowledge alarm and cancel grace alarm
startAlert(context);
} }
// Set a grace period alarm to send SMS
Calendar graceCal = Calendar.getInstance();
graceCal.set(Calendar.SECOND, 0);
graceCal.add(Calendar.MINUTE, gracePeriod);
graceManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent graceIntent = new Intent(context, GraceReceiver.class);
gracePendingIntent = PendingIntent.getBroadcast(context, MainActivity.GRACE_REQUEST, graceIntent, 0);
graceManager.cancel(gracePendingIntent);
if (Build.VERSION.SDK_INT >= 19) {
graceManager.setExact(AlarmManager.RTC_WAKEUP, graceCal.getTimeInMillis(), gracePendingIntent);
} else {
graceManager.set(AlarmManager.RTC_WAKEUP, graceCal.getTimeInMillis(), gracePendingIntent);
}
Log.d("AlarmReceiver", "Setting grace alarm for " + MainActivity.debugDate(graceCal));
// Calculate when the grace period (converted from minutes to milliseconds) ends
graceEndTime = System.currentTimeMillis() + (gracePeriod * 60 * 1000);
// Set up intents for later use
notifyIntent = new Intent(context, AlarmNotify.class);
alertActivityIntent = new Intent(context, AlarmAlertActivity.class);
alertActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
// Allow user to acknowledge alarm and cancel grace alarm
startAlert(context);
// Reset for tomorrow; as of API 19, setRepeating() is inexact, so we use setExact() // Reset for tomorrow; as of API 19, setRepeating() is inexact, so we use setExact()
Calendar cal = MainActivity.TimeStringToCalendar(alarmTimeStr); Calendar cal = MainActivity.TimeStringToCalendar(alarmTimeStr);
// Advance the calendar to tomorrow // Advance the calendar to tomorrow

View File

@ -56,8 +56,6 @@ import java.util.regex.Pattern;
// More than one phone number? // More than one phone number?
// Alerts via Whatsapp and other protocols? // Alerts via Whatsapp and other protocols?
// TODO: klaxon
public class MainActivity extends ActionBarActivity { public class MainActivity extends ActionBarActivity {
public static int ALARM_REQUEST = 1; public static int ALARM_REQUEST = 1;
public static int GRACE_REQUEST = 2; public static int GRACE_REQUEST = 2;