716 lines
32 KiB
Java
716 lines
32 KiB
Java
package za.org.treehouse.hypoalarm;
|
|
|
|
import android.app.AlarmManager;
|
|
import android.app.AlertDialog;
|
|
import android.app.Dialog;
|
|
import android.app.PendingIntent;
|
|
import android.app.TimePickerDialog;
|
|
import android.content.ComponentName;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.Intent;
|
|
import android.content.SharedPreferences;
|
|
import android.content.pm.PackageManager;
|
|
import android.database.Cursor;
|
|
import android.location.Location;
|
|
import android.media.Ringtone;
|
|
import android.media.RingtoneManager;
|
|
import android.net.Uri;
|
|
import android.os.Build;
|
|
import android.os.Bundle;
|
|
import android.preference.PreferenceManager;
|
|
import android.provider.ContactsContract;
|
|
import android.support.v4.app.DialogFragment;
|
|
import android.support.v4.app.Fragment;
|
|
import android.support.v7.app.ActionBarActivity;
|
|
import android.text.InputType;
|
|
import android.text.format.DateFormat;
|
|
import android.util.Log;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.view.inputmethod.InputMethodManager;
|
|
import android.widget.AdapterView;
|
|
import android.widget.ArrayAdapter;
|
|
import android.widget.Button;
|
|
import android.widget.CompoundButton;
|
|
import android.widget.EditText;
|
|
import android.widget.Spinner;
|
|
import android.widget.TimePicker;
|
|
import android.widget.Toast;
|
|
|
|
import com.google.android.gms.common.ConnectionResult;
|
|
import com.google.android.gms.common.GooglePlayServicesClient;
|
|
import com.google.android.gms.common.GooglePlayServicesUtil;
|
|
import com.google.android.gms.location.LocationClient;
|
|
|
|
import java.text.ParseException;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.Calendar;
|
|
import java.util.Date;
|
|
import java.util.Locale;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
|
|
// Settings: alarm time, phone number, custom message, grace period length
|
|
// Set alarm
|
|
// Display alarm notification
|
|
// Display countdown (in seconds) or time till alarm fires (in minutes)
|
|
// Reset alarm
|
|
// Send SMS
|
|
|
|
// Possible settings:
|
|
// More than one phone number?
|
|
// Alerts via Whatsapp and other protocols?
|
|
|
|
public class MainActivity extends ActionBarActivity {
|
|
private static LocationClient locationClient = null;
|
|
public static final int ALARM_REQUEST = 1;
|
|
public static final int GRACE_REQUEST = 2;
|
|
public static final int PRE_NOTIFY_REQUEST = 3;
|
|
public static final int CANCEL_GRACE_REQUEST = 4;
|
|
public static final int CANCEL_ALARM_REQUEST = 5;
|
|
public static final int PHONE_NUMBER_REQUEST = 6;
|
|
public static final int RINGTONE_REQUEST = 7;
|
|
public static final String TIMEPICKER_TAG = "alarmTimePicker";
|
|
public static final String defaultTimeStr = "09:00";
|
|
public static final int defaultGracePeriod = 2;
|
|
public static final Boolean defaultActive = true;
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
setContentView(R.layout.activity_main);
|
|
|
|
if (savedInstanceState == null) {
|
|
getSupportFragmentManager().beginTransaction()
|
|
.add(R.id.container, new MainFragment())
|
|
.commit();
|
|
}
|
|
}
|
|
|
|
// Main screen
|
|
|
|
/**
|
|
* To use a radial timepicker, uncomment this line instead
|
|
public static class MainFragment extends Fragment implements RadialTimePickerDialog.OnTimeSetListener {
|
|
*/
|
|
public static class MainFragment extends Fragment {
|
|
|
|
public MainFragment() {
|
|
}
|
|
|
|
@Override
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
Bundle savedInstanceState) {
|
|
return inflater.inflate(R.layout.fragment_main, container, false);
|
|
}
|
|
|
|
public void onStart() {
|
|
final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
|
|
|
super.onStart();
|
|
|
|
/**
|
|
* To use a radial timepicker, uncomment here:
|
|
final RadialTimePickerDialog timePickerDialog = RadialTimePickerDialog.newInstance(this, 0, 0, DateFormat.is24HourFormat(getActivity()));
|
|
*/
|
|
// Set alarm time
|
|
String alarmTimeStr = verifyTimeString(sharedPref.getString(getString(R.string.AlarmTimePref), defaultTimeStr));
|
|
final Button alarmTimeButton = (Button) getActivity().findViewById(R.id.alarm_time);
|
|
alarmTimeButton.setText(alarmTimeStr);
|
|
alarmTimeButton.setOnClickListener(new View.OnClickListener() {
|
|
@Override
|
|
public void onClick(View view) {
|
|
DialogFragment alarmFragment = new TimePickerFragment();
|
|
alarmFragment.show(getActivity().getSupportFragmentManager(), TIMEPICKER_TAG);
|
|
|
|
/**
|
|
* To use a radial time picker, uncomment here:
|
|
// Use the current set time as the default value for the picker
|
|
String alarmTimeStr = verifyTimeString(sharedPref.getString(getString(R.string.AlarmTimePref), defaultTimeStr));
|
|
timePickerDialog.setStartTime(hour, minute);
|
|
timePickerDialog.setThemeDark(true); // available from version 1.5.3...
|
|
timePickerDialog.show(getActivity().getSupportFragmentManager(), TIMEPICKER_TAG);
|
|
*/
|
|
}
|
|
});
|
|
|
|
// Allow alarm to activate
|
|
Boolean alarmActive = sharedPref.getBoolean(getString(R.string.AlarmActivePref), defaultActive);
|
|
final CompoundButton alarmActiveSwitch = (CompoundButton) getActivity().findViewById(R.id.alarm_active_switch);
|
|
alarmActiveSwitch.setChecked(alarmActive);
|
|
alarmActiveSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
|
@Override
|
|
public void onCheckedChanged(CompoundButton compoundButton, boolean active) {
|
|
SharedPreferences.Editor editor = sharedPref.edit();
|
|
editor.putBoolean(getString(R.string.AlarmActivePref), active);
|
|
editor.commit();
|
|
|
|
if (!active) {
|
|
// Prevent any snoozed alarm from returning
|
|
if (AlarmService.alarmStatus.contentEquals(AlarmService.ALARM_SNOOZE_RUNNING) ||
|
|
AlarmService.alarmStatus.contentEquals(AlarmService.ALARM_SNOOZED) ||
|
|
AlarmService.alarmStatus.contentEquals(AlarmService.ALARM_RUNNING)) {
|
|
AlarmService.setAlarmStatus(AlarmService.ALARM_DISMISSED);
|
|
}
|
|
// Cancel any alarms
|
|
cancelAllAlarms(getActivity());
|
|
Toast.makeText(getActivity(), getString(R.string.alarmCancelled), Toast.LENGTH_SHORT).show();
|
|
} else {
|
|
String alarmTimeStr = verifyTimeString(sharedPref.getString(getString(R.string.AlarmTimePref), defaultTimeStr));
|
|
Calendar cal = TimeStringToCalendar(alarmTimeStr);
|
|
setAlarm(getActivity(), cal);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Activate the time (after setting alarmActive) when starting the app (but don't cancel any existing grace period alarms)
|
|
Calendar cal = TimeStringToCalendar(alarmTimeStr);
|
|
setAlarm(getActivity(), cal);
|
|
|
|
// Set grace period
|
|
int gracePeriod = sharedPref.getInt(getString(R.string.GracePeriodPref), defaultGracePeriod);
|
|
final Spinner gracePeriodSpinner = (Spinner) getActivity().findViewById(R.id.grace_period);
|
|
|
|
gracePeriodSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
|
final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
|
|
|
@Override
|
|
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
|
|
Object value = parent.getItemAtPosition(pos);
|
|
if (value != null) {
|
|
SharedPreferences.Editor editor = sharedPref.edit();
|
|
int minutes = GracePeriodToMinutes(value.toString());
|
|
editor.putInt(getString(R.string.GracePeriodPref), minutes);
|
|
editor.commit();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onNothingSelected(AdapterView<?> parent) {
|
|
}
|
|
});
|
|
// Set value of drop-down list to value of gracePeriodStr
|
|
ArrayAdapter<String> gracePeriodSpinnerAdapter = (ArrayAdapter<String>) gracePeriodSpinner.getAdapter();
|
|
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());
|
|
final 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_TYPE, RingtoneManager.TYPE_ALARM);
|
|
ringtoneIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, ringtoneUri);
|
|
|
|
startActivityForResult(ringtoneIntent, RINGTONE_REQUEST);
|
|
}
|
|
});
|
|
|
|
|
|
// Set phone number
|
|
String phoneNumberStr = sharedPref.getString(getString(R.string.PhoneNumberPref), null);
|
|
final EditText phoneNumberButton = (EditText) getActivity().findViewById(R.id.phone_number);
|
|
phoneNumberButton.setText(phoneNumberStr);
|
|
phoneNumberButton.setOnClickListener(new View.OnClickListener() {
|
|
@Override
|
|
public void onClick(View view) {
|
|
DialogFragment phoneFragment = new PhonePickerFragment();
|
|
phoneFragment.show(getActivity().getSupportFragmentManager(), "phoneNumberPicker");
|
|
}
|
|
});
|
|
|
|
// Set message
|
|
String messageStr = sharedPref.getString(getString(R.string.MessagePref), getString(R.string.defaultMessage));
|
|
final EditText messageButton = (EditText) getActivity().findViewById(R.id.message);
|
|
messageButton.setText(messageStr);
|
|
messageButton.setOnClickListener(new View.OnClickListener() {
|
|
@Override
|
|
public void onClick(View view) {
|
|
final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
|
final InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
|
|
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
|
|
|
|
final EditText messageInput = new EditText(getActivity());
|
|
messageInput.setInputType(InputType.TYPE_CLASS_TEXT |
|
|
InputType.TYPE_TEXT_FLAG_MULTI_LINE |
|
|
InputType.TYPE_TEXT_FLAG_CAP_SENTENCES |
|
|
InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
|
|
if (messageButton.getText() != null) {
|
|
messageInput.setText(messageButton.getText().toString());
|
|
}
|
|
if (messageInput.getText() != null) {
|
|
messageInput.setSelection(messageInput.getText().length());
|
|
}
|
|
alert.setView(messageInput);
|
|
alert.setMessage(getString(R.string.setMessage));
|
|
|
|
alert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int whichButton) {
|
|
String value = messageInput.getText().toString();
|
|
if (value.compareTo("") == 0) {
|
|
value = getString(R.string.defaultMessage);
|
|
}
|
|
SharedPreferences.Editor editor = sharedPref.edit();
|
|
editor.putString(getString(R.string.MessagePref), value);
|
|
editor.commit();
|
|
messageButton.setText(value);
|
|
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
|
|
}
|
|
});
|
|
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int whichButton) {
|
|
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
|
|
// Canceled.
|
|
}
|
|
});
|
|
alert.show();
|
|
messageInput.requestFocus();
|
|
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
|
|
}
|
|
});
|
|
|
|
// Set time change and boot receiver, so alarm restarts on boot
|
|
ComponentName bootReceiver = new ComponentName(getActivity(), AlarmChangeReceiver.class);
|
|
PackageManager pm = getActivity().getPackageManager();
|
|
if (pm != null) {
|
|
pm.setComponentEnabledSetting(bootReceiver,
|
|
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
|
|
PackageManager.DONT_KILL_APP);
|
|
Log.d("MainActivity", "Setting boot receiver");
|
|
}
|
|
|
|
// Get the location now, so that user has to grant permission for location now, not when
|
|
// the text message is sent.
|
|
if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity()) == ConnectionResult.SUCCESS) {
|
|
locationClient = new LocationClient(getActivity(),
|
|
new GooglePlayServicesClient.ConnectionCallbacks() {
|
|
@Override
|
|
public void onConnected(Bundle bundle) {
|
|
Location location = locationClient.getLastLocation();
|
|
if (location == null) {
|
|
Log.e("MainActivity", "No location data available.");
|
|
}
|
|
locationClient.disconnect();
|
|
}
|
|
@Override
|
|
public void onDisconnected() {
|
|
}
|
|
},
|
|
new GooglePlayServicesClient.OnConnectionFailedListener() {
|
|
@Override
|
|
public void onConnectionFailed(ConnectionResult connectionResult) {
|
|
Log.e("MainActivity", "Failed connection to location manager " + connectionResult.toString());
|
|
}
|
|
}
|
|
);
|
|
locationClient.connect();
|
|
} else {
|
|
Log.e("GraceReceiver", "Google Play Services is not available.");
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
|
|
// If we're answering a ringtone dialogue, update the correct button
|
|
if (requestCode == RINGTONE_REQUEST && resultCode == RESULT_OK) {
|
|
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
|
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()));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* To use a radial timepicker, uncomment this function
|
|
*
|
|
@Override
|
|
public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute) {
|
|
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
|
|
|
// Set time preference
|
|
Calendar cal = Calendar.getInstance();
|
|
cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
|
|
cal.set(Calendar.MINUTE, minute);
|
|
cal.set(Calendar.SECOND, 0);
|
|
String alarmStr = CalendarToTimeString(cal);
|
|
|
|
SharedPreferences.Editor editor = sharedPref.edit();
|
|
editor.putString(getString(R.string.AlarmTimePref), alarmStr);
|
|
editor.commit();
|
|
|
|
Button alarm_time = (Button) getActivity().findViewById(R.id.alarm_time);
|
|
alarm_time.setText(alarmStr);
|
|
|
|
// Set actual alarm
|
|
setAlarm(getActivity(), cal);
|
|
|
|
// Display toast
|
|
CharSequence text = getString(R.string.alarmSetToast) + " " + CalendarToTimeString(cal);
|
|
Toast.makeText(getActivity(), text, Toast.LENGTH_SHORT).show();
|
|
}
|
|
*/
|
|
}
|
|
|
|
/**
|
|
* Cancel main alarm, but not grace alarm.
|
|
* This should be run whenever the alarm is set.
|
|
*/
|
|
public static void cancelAlarm(Context context) {
|
|
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
|
|
|
// Cancel any current alarm
|
|
Intent alarmIntent = new Intent(context, AlarmReceiver.class);
|
|
PendingIntent alarmPendingIntent = PendingIntent.getBroadcast(context, ALARM_REQUEST, alarmIntent, 0);
|
|
alarmManager.cancel(alarmPendingIntent);
|
|
|
|
// Cancel any pre-alarm notification that may fire
|
|
Intent preNotifyIntent = new Intent(context, PreAlarmReceiver.class);
|
|
PendingIntent preNotifyPendingIntent = PendingIntent.getBroadcast(context, PRE_NOTIFY_REQUEST, preNotifyIntent, 0);
|
|
alarmManager.cancel(preNotifyPendingIntent);
|
|
|
|
// Stop any existing pre-alarm notification that has already fired
|
|
context.stopService(new Intent(context, PreAlarmNotify.class));
|
|
|
|
Log.d("MainActivity", "Alarm cancelled");
|
|
}
|
|
|
|
/**
|
|
* Cancel grace alarm and notifications
|
|
*/
|
|
public static void cancelGraceAlarm(Context context) {
|
|
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
|
|
|
// Cancel any grace period
|
|
Intent graceIntent = new Intent(context, GraceReceiver.class);
|
|
PendingIntent gracePendingIntent = PendingIntent.getBroadcast(context, GRACE_REQUEST, graceIntent, 0);
|
|
alarmManager.cancel(gracePendingIntent);
|
|
|
|
// Stop any notification of grace period expiry
|
|
context.stopService(new Intent(context, AlarmNotify.class));
|
|
|
|
Log.d("MainActivity", "Grace alarm cancelled");
|
|
}
|
|
/**
|
|
* Cancels main alarm and grace alarm
|
|
* This should only be run when we're disabling the alarm entirely.
|
|
*/
|
|
public static void cancelAllAlarms(Context context) {
|
|
cancelAlarm(context);
|
|
cancelGraceAlarm(context);
|
|
Log.d("MainActivity", "All alarms cancelled");
|
|
}
|
|
|
|
/**
|
|
* Set the alarm.
|
|
*
|
|
* @param context Context
|
|
* @param cal Time at which to fire alarm
|
|
*/
|
|
public static void setAlarm(Context context, Calendar cal) {
|
|
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
|
PendingIntent alarmPendingIntent, preNotifyPendingIntent;
|
|
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
|
|
Boolean alarmActive = sharedPref.getBoolean(context.getString(R.string.AlarmActivePref), defaultActive);
|
|
|
|
cancelAlarm(context);
|
|
|
|
// Advance cal to tomorrow if setting a time earlier than now
|
|
if (cal.before(Calendar.getInstance())) {
|
|
cal.add(Calendar.DAY_OF_MONTH, 1);
|
|
}
|
|
|
|
if (alarmActive) {
|
|
// Initialise alarm, which displays a dialog and system alert, and
|
|
// calls AlarmManager with grace_period as the delay
|
|
// which in turn, sends SMS if dialog is not exited.
|
|
Intent alarmIntent = new Intent(context, AlarmReceiver.class);
|
|
alarmPendingIntent = PendingIntent.getBroadcast(context, ALARM_REQUEST, alarmIntent, 0);
|
|
// Set or reset alarm
|
|
if (Build.VERSION.SDK_INT >= 19) {
|
|
alarmManager.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmPendingIntent);
|
|
} else {
|
|
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmPendingIntent);
|
|
}
|
|
Log.d("MainActivity", "Setting alarm for " + debugDate(cal));
|
|
|
|
// Set an alarm for the pre-alarm notification, an hour before the alarm
|
|
Calendar preNotifyCal = (Calendar) cal.clone();
|
|
preNotifyCal.add(Calendar.MINUTE, -60);
|
|
Intent preNotifyIntent = new Intent(context, PreAlarmReceiver.class);
|
|
preNotifyPendingIntent = PendingIntent.getBroadcast(context, PRE_NOTIFY_REQUEST, preNotifyIntent, 0);
|
|
// Set or reset alarm
|
|
if (Build.VERSION.SDK_INT >= 19) {
|
|
alarmManager.setExact(AlarmManager.RTC_WAKEUP, preNotifyCal.getTimeInMillis(), preNotifyPendingIntent);
|
|
} else {
|
|
alarmManager.set(AlarmManager.RTC_WAKEUP, preNotifyCal.getTimeInMillis(), preNotifyPendingIntent);
|
|
}
|
|
Log.d("MainActivity", "Setting pre-alarm for " + debugDate(preNotifyCal));
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the grace alarm, to fire at the end of the grace period and send a text message.
|
|
*/
|
|
public static void setGraceAlarm(Context context) {
|
|
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
|
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
|
|
Boolean alarmActive = sharedPref.getBoolean(context.getString(R.string.AlarmActivePref), defaultActive);
|
|
int gracePeriod = sharedPref.getInt(context.getString(R.string.GracePeriodPref), defaultGracePeriod);
|
|
|
|
cancelGraceAlarm(context);
|
|
|
|
if (alarmActive) {
|
|
// Set a grace period alarm to send SMS
|
|
Calendar graceCal = Calendar.getInstance();
|
|
graceCal.set(Calendar.SECOND, 0);
|
|
graceCal.add(Calendar.MINUTE, gracePeriod);
|
|
Intent graceIntent = new Intent(context, GraceReceiver.class);
|
|
PendingIntent gracePendingIntent = PendingIntent.getBroadcast(context, GRACE_REQUEST, graceIntent, 0);
|
|
if (Build.VERSION.SDK_INT >= 19) {
|
|
alarmManager.setExact(AlarmManager.RTC_WAKEUP, graceCal.getTimeInMillis(), gracePendingIntent);
|
|
} else {
|
|
alarmManager.set(AlarmManager.RTC_WAKEUP, graceCal.getTimeInMillis(), gracePendingIntent);
|
|
}
|
|
Log.d("MainActivity", "Setting grace alarm for " + debugDate(graceCal));
|
|
}
|
|
}
|
|
|
|
public static class TimePickerFragment extends DialogFragment implements TimePickerDialog.OnTimeSetListener {
|
|
SharedPreferences sharedPref;
|
|
|
|
@Override
|
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
|
// Use the current set time as the default value for the picker
|
|
String alarmTimeStr = verifyTimeString(sharedPref.getString(getString(R.string.AlarmTimePref), defaultTimeStr));
|
|
// For selecting a time, the date doesn't matter, just the hour and minute
|
|
Calendar cal = TimeStringToCalendar(alarmTimeStr);
|
|
int hour = cal.get(Calendar.HOUR_OF_DAY);
|
|
int minute = cal.get(Calendar.MINUTE);
|
|
|
|
// Create a new instance of TimePickerDialog and return it
|
|
return new TimePickerDialog(getActivity(), this, hour, minute, DateFormat.is24HourFormat(getActivity()));
|
|
}
|
|
|
|
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
|
|
// Set time preference
|
|
Calendar cal = Calendar.getInstance();
|
|
cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
|
|
cal.set(Calendar.MINUTE, minute);
|
|
cal.set(Calendar.SECOND, 0);
|
|
String alarmStr = CalendarToTimeString(cal);
|
|
|
|
SharedPreferences.Editor editor = sharedPref.edit();
|
|
editor.putString(getString(R.string.AlarmTimePref), alarmStr);
|
|
editor.commit();
|
|
|
|
Button alarm_time = (Button) getActivity().findViewById(R.id.alarm_time);
|
|
alarm_time.setText(alarmStr);
|
|
|
|
// Set actual alarm
|
|
setAlarm(getActivity(), cal);
|
|
|
|
// Display toast
|
|
CharSequence text = getString(R.string.alarmSetToast) + " " + CalendarToTimeString(cal);
|
|
Toast.makeText(getActivity(), text, Toast.LENGTH_SHORT).show();
|
|
}
|
|
}
|
|
|
|
public static class PhonePickerFragment extends DialogFragment {
|
|
SharedPreferences sharedPref;
|
|
EditText phoneInput;
|
|
|
|
@Override
|
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
|
|
|
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
|
|
alert.setMessage(R.string.setPhoneNumber);
|
|
|
|
LayoutInflater inflater = getActivity().getLayoutInflater();
|
|
// Pass null instead of the parent ViewGroup, as the parent View is a
|
|
// ScrollView, which can only have one direct child
|
|
View dialogView = inflater.inflate(R.layout.phone_dialog, null);
|
|
alert.setView(dialogView);
|
|
|
|
final EditText phoneButton = (EditText) getActivity().findViewById(R.id.phone_number);
|
|
phoneInput = (EditText) dialogView.findViewById(R.id.dialog_phone_number);
|
|
phoneInput.setText(phoneButton.getText().toString());
|
|
phoneInput.setSelection(phoneInput.getText().length());
|
|
final Button contactsButton = (Button) dialogView.findViewById(R.id.dialog_contacts_button);
|
|
|
|
alert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int whichButton) {
|
|
String value = phoneInput.getText().toString();
|
|
SharedPreferences.Editor editor = sharedPref.edit();
|
|
editor.putString(getString(R.string.PhoneNumberPref), value);
|
|
editor.commit();
|
|
phoneButton.setText(value);
|
|
}
|
|
});
|
|
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int whichButton) {
|
|
// Cancelled
|
|
}
|
|
});
|
|
contactsButton.setOnClickListener(new View.OnClickListener() {
|
|
@Override
|
|
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, PHONE_NUMBER_REQUEST);
|
|
}
|
|
});
|
|
return alert.create();
|
|
}
|
|
|
|
@Override
|
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
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
|
|
);
|
|
|
|
if (c != null && c.moveToFirst()) {
|
|
String number = c.getString(0);
|
|
phoneInput.setText(number);
|
|
}
|
|
} finally {
|
|
if (c != null) {
|
|
c.close();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static String verifyTimeString(String timeStr) {
|
|
return CalendarToTimeString(TimeStringToCalendar(timeStr));
|
|
}
|
|
|
|
public static Calendar TimeStringToCalendar(String dateString) {
|
|
Date date;
|
|
Calendar cal;
|
|
final String FORMAT = "HH:mm";
|
|
SimpleDateFormat sdf = new SimpleDateFormat(FORMAT, Locale.getDefault());
|
|
sdf.format(new Date());
|
|
try {
|
|
date = sdf.parse(dateString);
|
|
// date has the correct hour and minute, but the incorrect day,
|
|
// month and year information. To get information out of it, we need to
|
|
// convert it to a Calendar.
|
|
Calendar dateCal = Calendar.getInstance();
|
|
dateCal.setTime(date);
|
|
|
|
// Create a new calendar with the correct day, month and year,
|
|
// and set the hour and minute by hand.
|
|
cal = Calendar.getInstance();
|
|
cal.set(Calendar.HOUR_OF_DAY, dateCal.get(Calendar.HOUR_OF_DAY));
|
|
cal.set(Calendar.MINUTE, dateCal.get(Calendar.MINUTE));
|
|
cal.set(Calendar.SECOND, 0);
|
|
return cal;
|
|
} catch (ParseException e) {
|
|
e.printStackTrace();
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static String CalendarToTimeString(Calendar cal) {
|
|
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) {
|
|
SimpleDateFormat print;
|
|
if (DateFormat.is24HourFormat(context)) {
|
|
print = new SimpleDateFormat("E HH:mm");
|
|
} else {
|
|
print = new SimpleDateFormat("E hh:mm a");
|
|
}
|
|
return print.format(cal.getTime());
|
|
}
|
|
|
|
public static int GracePeriodToMinutes(String gracePeriod) {
|
|
Pattern p = Pattern.compile("(?:(\\d+)\\s+hours?)?\\s*(?:(\\d+)\\s+minutes?)?");
|
|
|
|
Matcher m = p.matcher(gracePeriod);
|
|
if (m.find()) {
|
|
int hours = 0;
|
|
int minutes = 0;
|
|
if (m.group(1) != null) {
|
|
hours = Integer.parseInt(m.group(1));
|
|
}
|
|
if (m.group(2) != null) {
|
|
minutes = Integer.parseInt(m.group(2));
|
|
}
|
|
minutes = minutes + (hours * 60);
|
|
return minutes;
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
public static String MinutesToGracePeriodStr(int minutes) {
|
|
int hours = minutes / 60;
|
|
int remMinutes = minutes % 60;
|
|
|
|
String hourStr = " hours";
|
|
if (hours == 1) {
|
|
hourStr = " hour";
|
|
}
|
|
|
|
String minStr = " minutes";
|
|
if (remMinutes == 1) {
|
|
minStr = " minute";
|
|
}
|
|
|
|
if (hours > 0) {
|
|
if (remMinutes == 0) {
|
|
return hours + hourStr;
|
|
}
|
|
return hours + hourStr + " " + remMinutes + minStr;
|
|
}
|
|
return remMinutes + minStr;
|
|
}
|
|
|
|
public static String debugDate(Calendar cal) {
|
|
SimpleDateFormat print = new SimpleDateFormat("dd-MM-yyyy HH:mm:ssZ");
|
|
return print.format(cal.getTime());
|
|
}
|
|
|
|
@Override
|
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
}
|
|
} |