- Allow user to select ringtone

- Display readable alarm time in pre-alarm notification
This commit is contained in:
Timothy Allen 2014-04-14 10:55:54 +02:00
parent fb886aabe9
commit f9204e52f3
10 changed files with 159 additions and 54 deletions

View File

@ -12,6 +12,8 @@ import android.view.WindowManager;
//import com.triggertrap.seekarc.SeekArc;
import net.frakbot.glowpadbackport.GlowPadView;
import java.util.Random;
public class AlarmAlertActivity extends Activity {
private static Intent notifyIntent;
public static Boolean alertFinished, userCancelled;
@ -45,7 +47,6 @@ public class AlarmAlertActivity extends Activity {
notifyIntent = new Intent(getApplicationContext(), AlarmNotify.class);
// Disable any current notifications (if we're snoozing)
stopService(notifyIntent);
}
@Override

View File

@ -1,12 +1,15 @@
package za.org.treehouse.hypoalarm;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
@ -24,11 +27,7 @@ public class AlarmKlaxon {
private static Vibrator vibrator;
public static void start(final Context context) {
/**
*
* TODO allow user to select alarm tone
*
*/
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.cancel();
@ -54,10 +53,6 @@ public class AlarmKlaxon {
};
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
// TODO select alarm tone?
// Use the default alarm tone...
Uri alarmNoise = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
stopAudio(context);
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@ -69,11 +64,15 @@ public class AlarmKlaxon {
}
});
// Get preferred ringtone, or fall back to the default alarm tone
String ringtoneStr = sharedPref.getString(context.getString(R.string.RingtonePref), RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM).toString());
Uri ringtoneUri = Uri.parse(ringtoneStr);
try {
mediaPlayer.setDataSource(context, alarmNoise);
mediaPlayer.setDataSource(context, ringtoneUri);
startAudio(context);
} catch (Exception ex) {
// The alarmNoise may be on the sd card which could be busy right
// The ringtoneUri may be on the sd card which could be busy right
// now. Use the fallback ringtone.
try {
// Reset the media player to clear the error state.

View File

@ -18,10 +18,10 @@ import java.io.IOException;
import java.util.Calendar;
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 ALERT_LIFE = 1000*10; //TODO 1000*60*2; // 2 minutes
private static final int SNOOZE_TIME = 1000*60*5; // Snooze for 5 minutes if need be
private static final int ALERT_LIFE = 1000*60*2; // 2 minutes
private static SharedPreferences sharedPref;
private static AlarmManager alarmManager, graceManager;
private static AlarmManager alarmManager;
private static PendingIntent alarmPendingIntent, gracePendingIntent;
private static Intent alertActivityIntent, notifyIntent;
private static TelephonyManager telephonyManager;
@ -36,6 +36,7 @@ public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, final Intent intent) {
sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
final Boolean alarmActive = sharedPref.getBoolean(context.getString(R.string.AlarmActivePref), true);
final int gracePeriod = sharedPref.getInt(context.getString(R.string.GracePeriodPref), 60);
final String alarmTimeStr = sharedPref.getString(context.getString(R.string.AlarmTimePref), null);
@ -55,14 +56,13 @@ public class AlarmReceiver extends BroadcastReceiver {
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);
alarmManager.cancel(gracePendingIntent);
if (Build.VERSION.SDK_INT >= 19) {
graceManager.setExact(AlarmManager.RTC_WAKEUP, graceCal.getTimeInMillis(), gracePendingIntent);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, graceCal.getTimeInMillis(), gracePendingIntent);
} else {
graceManager.set(AlarmManager.RTC_WAKEUP, graceCal.getTimeInMillis(), gracePendingIntent);
alarmManager.set(AlarmManager.RTC_WAKEUP, graceCal.getTimeInMillis(), gracePendingIntent);
}
Log.d("AlarmReceiver", "Setting grace alarm for " + MainActivity.debugDate(graceCal));
@ -83,7 +83,6 @@ public class AlarmReceiver extends BroadcastReceiver {
Calendar cal = MainActivity.TimeStringToCalendar(alarmTimeStr);
// Advance the calendar to tomorrow
cal.add(Calendar.DAY_OF_MONTH, 1);
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmPendingIntent = PendingIntent.getBroadcast(context, MainActivity.ALARM_REQUEST, intent, 0);
alarmManager.cancel(alarmPendingIntent);
if (Build.VERSION.SDK_INT >= 19) {
@ -141,10 +140,9 @@ public class AlarmReceiver extends BroadcastReceiver {
stopAlert(context);
// Cancel the graceAlarm
AlarmManager graceManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent graceIntent = new Intent(context, GraceReceiver.class);
PendingIntent gracePendingIntent = PendingIntent.getBroadcast(context, MainActivity.GRACE_REQUEST, graceIntent, 0);
graceManager.cancel(gracePendingIntent);
alarmManager.cancel(gracePendingIntent);
}
public static void snoozeAlarm(final Context context) {

View File

@ -42,6 +42,7 @@ public class GraceReceiver extends BroadcastReceiver {
public void onConnected(Bundle bundle) {
Location location = locationClient.getLastLocation();
if (location != null) {
// uri must begin with a space
String uri = " http://maps.google.com?q=" + location.getLatitude() + "," + location.getLongitude();
message += uri;
sendText(context);

View File

@ -12,6 +12,8 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@ -57,18 +59,20 @@ import java.util.regex.Pattern;
// Alerts via Whatsapp and other protocols?
public class MainActivity extends ActionBarActivity {
public static int ALARM_REQUEST = 1;
public static int GRACE_REQUEST = 2;
public static int PRENOTIFY_REQUEST = 3;
public static int CANCEL_GRACE_REQUEST = 4;
public static int CANCEL_ALARM_REQUEST = 5;
public static int ALARM_REQUEST = 1;
public static int GRACE_REQUEST = 2;
public static int PRENOTIFY_REQUEST = 3;
public static int CANCEL_GRACE_REQUEST = 4;
public static int CANCEL_ALARM_REQUEST = 5;
public static int PHONE_NUMBER_REQUEST = 6;
public static int RINGTONE_REQUEST = 7;
private static Switch alarmActiveSwitch;
private static Button alarmTimeButton;
private static Spinner gracePeriodSpinner;
private static EditText phoneNumberButton;
private static EditText messageButton;
public static Boolean HYPOALARM_DEBUG=true;
public static Boolean HYPOALARM_DEBUG = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -90,7 +94,7 @@ public class MainActivity extends ActionBarActivity {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
@ -108,8 +112,8 @@ public class MainActivity extends ActionBarActivity {
alarmActiveSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
AlarmManager alarmManager, graceManager;
PendingIntent alarmPendingIntent, gracePendingIntent;
AlarmManager alarmManager;
PendingIntent alarmPendingIntent, gracePendingIntent, preNotifyPendingIntent;
SharedPreferences.Editor editor = sharedPref.edit();
editor.putBoolean(getString(R.string.AlarmActivePref), b);
@ -121,13 +125,18 @@ public class MainActivity extends ActionBarActivity {
Intent alarmIntent = new Intent(getActivity(), AlarmReceiver.class);
alarmPendingIntent = PendingIntent.getBroadcast(getActivity(), ALARM_REQUEST, alarmIntent, 0);
alarmManager.cancel(alarmPendingIntent);
// Cancel any pre-alarm notification
Intent preNotifyIntent = new Intent(getActivity(), AlarmReceiver.class);
preNotifyPendingIntent = PendingIntent.getBroadcast(getActivity(), PRENOTIFY_REQUEST, alarmIntent, 0);
alarmManager.cancel(preNotifyPendingIntent);
// Cancel any grace period
graceManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
Intent graceIntent = new Intent(getActivity(), GraceReceiver.class);
gracePendingIntent = PendingIntent.getBroadcast(getActivity(), GRACE_REQUEST, graceIntent, 0);
graceManager.cancel(gracePendingIntent);
alarmManager.cancel(gracePendingIntent);
// Stop any notifications
getActivity().stopService(new Intent(getActivity(), AlarmNotify.class));
getActivity().stopService(new Intent(getActivity(), PreAlarmNotify.class));
Log.d("MainActivity", "Alarms cancelled");
Toast.makeText(getActivity().getApplicationContext(), getString(R.string.alarmCancelled), Toast.LENGTH_SHORT).show();
} else {
@ -194,6 +203,27 @@ public class MainActivity extends ActionBarActivity {
int spinnerPosition = gracePeriodSpinnerAdapter.getPosition(MinutesToGracePeriodStr(gracePeriod));
gracePeriodSpinner.setSelection(spinnerPosition);
// Allow user to select ringtone
final Button ringtoneButton = (Button) getActivity().findViewById(R.id.ringtone);
String ringtoneStr = sharedPref.getString(getString(R.string.RingtonePref), RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM).toString());
Uri ringtoneUri = Uri.parse(ringtoneStr);
Ringtone currentRingtone = RingtoneManager.getRingtone(getActivity().getApplicationContext(), ringtoneUri);
ringtoneButton.setText(currentRingtone.getTitle(getActivity().getApplicationContext()));
ringtoneButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent ringtoneIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
ringtoneIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, "Select ringtone:");
ringtoneIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false);
//ringtoneIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
ringtoneIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_ALARM);
//ringtoneIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, currentRingtone);
startActivityForResult(ringtoneIntent, RINGTONE_REQUEST);
}
});
// Set phone number
String phoneNumberStr = sharedPref.getString(getString(R.string.PhoneNumberPref), null);
phoneNumberButton = (EditText) getActivity().findViewById(R.id.phone_number);
@ -261,6 +291,29 @@ public class MainActivity extends ActionBarActivity {
}
});
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("MainActivity", "Request code: " + requestCode);
// If we're answering a ringtone dialogue, update the correct button
if (requestCode == RINGTONE_REQUEST && resultCode == RESULT_OK) {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity().getApplicationContext());
SharedPreferences.Editor editor = sharedPref.edit();
Button ringtoneButton = (Button) getActivity().findViewById(R.id.ringtone);
Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
if (uri == null) {
editor.putString(getString(R.string.RingtonePref), null);
} else {
editor.putString(getString(R.string.RingtonePref), uri.toString());
}
editor.commit();
Ringtone currentRingtone = RingtoneManager.getRingtone(getActivity().getApplicationContext(), uri);
ringtoneButton.setText(currentRingtone.getTitle(getActivity().getApplicationContext()));
}
}
}
// Alarm time picker
@ -348,7 +401,6 @@ public class MainActivity extends ActionBarActivity {
}
public static class PhonePickerFragment extends DialogFragment {
SharedPreferences sharedPref;
EditText phoneButton;
EditText phoneInput;
Button contactsButton;
@ -389,7 +441,7 @@ public class MainActivity extends ActionBarActivity {
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);
startActivityForResult(intent, 1);
startActivityForResult(intent, PHONE_NUMBER_REQUEST);
}
});
return alert.create();
@ -397,15 +449,16 @@ public class MainActivity extends ActionBarActivity {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (data != null) {
if (requestCode == PHONE_NUMBER_REQUEST && resultCode == RESULT_OK && data != null) {
Uri uri = data.getData();
if (uri != null) {
Cursor c = null;
try {
c = getActivity().getContentResolver().query(uri, new String[]{
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.TYPE },
null, null, null);
ContactsContract.CommonDataKinds.Phone.TYPE},
null, null, null
);
if (c != null && c.moveToFirst()) {
String number = c.getString(0);
@ -419,12 +472,12 @@ public class MainActivity extends ActionBarActivity {
}
}
}
}
public static String verifyTimeString(String timeStr) {
return CalendarToTimeString(TimeStringToCalendar(timeStr));
}
public static String HourMinuteToTimeString(int hour, int minute) {
return CalendarToTimeString(TimeStringToCalendar(hour + ":" + minute));
}
@ -432,7 +485,7 @@ public class MainActivity extends ActionBarActivity {
public static Calendar TimeStringToCalendar(String dateString) {
Date date;
Calendar cal;
final String FORMAT="HH:mm"; // z = time zone
final String FORMAT = "HH:mm"; // z = time zone
SimpleDateFormat sdf = new SimpleDateFormat(FORMAT, Locale.getDefault());
sdf.format(new Date());
try {
@ -455,15 +508,28 @@ public class MainActivity extends ActionBarActivity {
return null;
}
}
public static String CalendarToTimeString(Calendar cal) {
final String FORMAT="HH:mm";
final String FORMAT = "HH:mm";
SimpleDateFormat sdf = new SimpleDateFormat(FORMAT, Locale.getDefault());
return sdf.format(cal.getTime());
}
public static String formattedTime(Context context, Calendar cal) {
String pattern;
if (Build.VERSION.SDK_INT >= 18) {
String skeleton = DateFormat.is24HourFormat(context) ? "EHm" : "Ehma";
pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
} else {
pattern = "EHm";
}
return (String) DateFormat.format(pattern, cal);
}
public static String debugDate(Calendar cal) {
SimpleDateFormat print = new SimpleDateFormat("dd-MM-yyyy HH:mm:ssZ");
return print.format(cal.getTime());
}
public static int GracePeriodToMinutes(String gracePeriod) {
Pattern p = Pattern.compile("(?:(\\d+)\\s+hours?)?\\s*(?:(\\d+)\\s+minutes?)?");
@ -483,6 +549,7 @@ public class MainActivity extends ActionBarActivity {
return 0;
}
public static String MinutesToGracePeriodStr(int minutes) {
int hours = minutes / 60;
int remMinutes = minutes % 60;
@ -505,4 +572,9 @@ public class MainActivity extends ActionBarActivity {
}
return remMinutes + minStr;
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
}

View File

@ -12,8 +12,12 @@ import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.text.format.DateFormat;
import android.util.Log;
import java.util.Calendar;
import java.util.Locale;
public class PreAlarmNotify extends Service {
public static final int preNotifyID = 2;
@ -36,14 +40,17 @@ public class PreAlarmNotify extends Service {
Log.d("PreAlarmNotify", "Pre-notification started.");
// Get alarm time, and convert it into something readable.
String alarmTimeStr = sharedPref.getString(getString(R.string.AlarmTimePref), null);
Calendar alarmCal = MainActivity.TimeStringToCalendar(alarmTimeStr);
alarmTimeStr = MainActivity.formattedTime(getApplicationContext(), alarmCal);
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_grey);
final NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= 11) {
final Notification.Builder notification = new Notification.Builder(this)
.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.preNotificationText))
.setContentTitle(getString(R.string.preNotificationTitle))
.setContentText(alarmTimeStr)
.setSmallIcon(R.drawable.alarm_notification)
.setLargeIcon(bm)
.setOnlyAlertOnce(true)

View File

@ -108,6 +108,28 @@
android:layout_column="1" />
</TableRow>
<TableRow
android:layout_marginTop="10dp"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ringtone_text"
android:id="@+id/ringtone_text"
android:layout_column="0" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/ringtone"
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="true"
android:gravity="left"
android:layout_column="1" />
</TableRow>
<TableRow
android:layout_marginTop="10dp"
android:layout_width="fill_parent"

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="glowpad_target">
<item>@null</item>
<item>@null</item>
<item>@null</item>
<item>@drawable/ic_alarm</item>
</array>
</resources>

View File

@ -31,6 +31,8 @@
<string name="phone_number_text">Phone number</string>
<string name="ringtone_text">Alarm Tone</string>
<string name="message_text">Message</string>
<string name="AlarmActivePref">AlarmActive</string>
@ -39,6 +41,8 @@
<string name="GracePeriodPref">GracePeriod</string>
<string name="RingtonePref">Ringtone</string>
<string name="PhoneNumberPref">PhoneNumber</string>
<string name="MessagePref">Message</string>
@ -53,24 +57,16 @@
<string name="alarmCancelToast">HypoAlarm text message cancelled</string>
<!-- defaultMessage must end in a space, for potential location data -->
<string name="defaultMessage">Hi, I haven\'t responded to my alarm today. Please contact me to make sure I\'m awake. </string>
<string name="defaultMessage">Hi, I haven\'t responded to my alarm today. Please contact me to make sure I\'m awake.</string>
<string name="notificationText">A text message will be sent in %1$s</string>
<string name="notificationCancellation">Cancel</string>
<string name="preNotificationText">Upcoming alarm</string>
<string name="preNotificationTitle">Upcoming HypoAlarm</string>
<string name="preNotificationCancellation">Dismiss Now</string>
<string name="alarmCancelled">All HypoAlarms cancelled</string>
<array name="glowpad_target">
<item>@null</item>
<item>@null</item>
<item>@null</item>
<item>@drawable/ic_alarm</item>
</array>
</resources>