Refactor to allow for snooze reminders (snooze when user hits the back or home buttons).

This commit is contained in:
2014-03-27 21:15:27 +02:00
parent c2806f2231
commit 1813f3faa6
57 changed files with 4737 additions and 94 deletions

View File

@ -73,6 +73,8 @@
<orderEntry type="library" exported="" name="appcompat-v7-19.0.1" level="project" />
<orderEntry type="library" exported="" name="support-v4-19.0.1" level="project" />
<orderEntry type="library" exported="" name="library-2.4.0" level="project" />
<orderEntry type="module" module-name="SeekArc" exported="" />
<orderEntry type="module" module-name="GlowPadBackport" exported="" />
</component>
</module>

View File

@ -17,11 +17,16 @@ android {
}
}
}
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
compile 'com.android.support:support-v4:19.0.1'
compile 'com.android.support:appcompat-v7:19.0.1'
compile 'com.nineoldandroids:library:2.4.0'
compile fileTree(dir: 'libs', include: ['*.aar'])
compile fileTree(dir: 'libs', include: ['*.jar'])
compile project(':GlowPadBackport')
compile project(':SeekArc')
}

View File

@ -30,6 +30,7 @@
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<service
android:name=".AlarmNotify"
android:label="@string/alarm_notification" >
@ -47,6 +48,6 @@
<!-- permission required to vibrate -->
<uses-permission android:name="android.permission.VIBRATE"/>
<!-- permission required to wake the device -->
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<!--uses-permission android:name="android.permission.WAKE_LOCK"/-->
</manifest>

View File

@ -8,13 +8,13 @@ import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import com.triggertrap.seekarc.SeekArc;
// TODO See GlowPad.
// TODO sound audible alarm -- see AlarmKlaxon.java
@ -22,16 +22,17 @@ import android.widget.Button;
// TODO Snooze? set another alarm for the next half-hour (or grace_period / 2)?
public class AlarmAlertActivity extends Activity {
// TODO correct alert lifetime
private static final int ALERT_LIFE = 1000*10; //1000*60*2; // 2 minutes
private static final long[] vPattern = {500, 500};
private static Boolean userCancelled;
private static Vibrator vibrator;
private static Intent notifyIntent;
public static Boolean alertFinished, userCancelled;
public static Activity alertActivity;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Self-reference so we can run finish() from outside.
alertActivity = this;
requestWindowFeature(Window.FEATURE_NO_TITLE);
Window window = getWindow();
// Set to use the full screen
@ -47,32 +48,15 @@ public class AlarmAlertActivity extends Activity {
setContentView(R.layout.alarm_alert);
notifyIntent = new Intent(getApplicationContext(), AlarmNotify.class);
// Disable any current notifications
// Disable any current notifications (if we're snoozing)
stopService(notifyIntent);
// Turn off the alert activity, and switch to a notification
new Handler().postDelayed(new Runnable() {
public void run() {
// Close the dialogue and switch to notification
// if the Activity has not been closed by the user
if (!userCancelled) {
startService(notifyIntent);
finish();
}
}
}, ALERT_LIFE);
}
@Override
public void onStart() {
super.onStart();
userCancelled = false;
vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(vPattern, 0);
// TODO change button to slide...
// TODO change slide to circle slide? https://github.com/JesusM/HoloCircleSeekBar
/*
Button cancelButton = (Button) findViewById(R.id.cancel_dialog_button);
cancelButton.setOnClickListener (new View.OnClickListener() {
@Override
@ -80,39 +64,38 @@ public class AlarmAlertActivity extends Activity {
cancelGraceAlarm();
}
});
*/
SeekArc cancelArc = (SeekArc) findViewById(R.id.cancel_dialog_seekArc);
cancelArc.setOnSeekArcChangeListener(new SeekArc.OnSeekArcChangeListener() {
volatile Boolean seekFinished = false;
@Override
public void onProgressChanged(SeekArc seekArc, int progress, boolean fromUser) {
if (progress > 98 && !seekFinished && fromUser) {
AlarmReceiver.dismissAlarm(alertActivity);
seekFinished = true;
}
}
@Override
public void onStartTrackingTouch(SeekArc seekArc) {
}
@Override
public void onStopTrackingTouch(SeekArc seekArc) {
}
});
}
/**
* Handle the user pressing the back/return button
* TODO Do we want this to cancel the alarm and grace period?
* TODO Or do we trigger the notification and finish() right away?
* TODO probably most intuitive to cancel the alarms...
* Handle the user pressing the back/return and home buttons
*/
@Override
public void onBackPressed() {
cancelGraceAlarm();
/* OR:
// Ensure that the we don't trigger the notification a second time
userCancelled = true;
startService(notifyIntent);
finish();
*/
AlarmReceiver.setAlarmStatus(AlarmReceiver.ALARM_IGNORED);
AlarmReceiver.snoozeAlarm(this);
}
public void onStop() {
vibrator.cancel();
super.onStop();
}
private void cancelGraceAlarm() {
AlarmManager graceManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent graceIntent = new Intent(getApplicationContext(), GraceReceiver.class);
PendingIntent gracePendingIntent = PendingIntent.getBroadcast(getApplicationContext(), MainActivity.GRACE_REQUEST, graceIntent, 0);
graceManager.cancel(gracePendingIntent);
Log.d("AlarmAlertActivity", "Cancelled grace alarm.");
// Ensure we don't load a notification now
userCancelled = true;
// Close the dialogue (stop vibration &c)
finish();
public void onUserLeaveHint() {
AlarmReceiver.setAlarmStatus(AlarmReceiver.ALARM_IGNORED);
AlarmReceiver.snoozeAlarm(this);
}
}

View File

@ -0,0 +1,130 @@
package za.org.treehouse.hypoalarm;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Vibrator;
import android.telephony.TelephonyManager;
import android.util.Log;
import java.io.IOException;
public class AlarmKlaxon {
private static final long[] vPattern = {500, 500};
// Volume modification for alarms while a phone call is active, from com.android.deskclock.alarms
private static final float IN_CALL_VOLUME = 0.125f;
private static MediaPlayer mediaPlayer = null;
private static TelephonyManager telephonyManager;
private static Vibrator vibrator;
public static void start(final Context context) {
/**
*
* TODO add raw ring tone to use as fallback
* TODO add in-call ring 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)
*
* TODO start telephony listener
*
* TODO snooze 5 minutes on press back button or home button (new runnable)
* TODO remove back/home button and most top icons
* TODO fix glowpad/seekarc
*/
vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.cancel();
vibrator.vibrate(vPattern, 0);
if (true)
return; // TODO remove after testing -- is mediaplayer responsible for delays?
telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
// 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() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.e("AlarmAlertActivity", "Error occurred while playing audio. Stopping alarm.");
stopAudio(context);
return true;
}
});
try {
/*
* TODO find out if we're in a call
if (inTelephoneCall) {
Log.v("Using the in-call alarm");
sMediaPlayer.setVolume(IN_CALL_VOLUME, IN_CALL_VOLUME);
setDataSourceFromResource(context, sMediaPlayer, R.raw.in_call_alarm);
} else {
*/
mediaPlayer.setDataSource(context, alarmNoise);
startAudio(context);
//}
} catch (Exception ex) {
// The alarmNoise 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.
mediaPlayer.reset();
//setDataSourceFromResource(this, mediaPlayer, R.raw.fallbackring);
startAudio(context);
} catch (Exception ex2) {
// At this point we just don't play anything.
Log.e("AlarmAlertActivity", "Failed to play fallback ringtone", ex2);
}
}
}
public static void stop(final Context context) {
vibrator.cancel();
if (true)
return; // TODO remove after testing
stopAudio(context);
}
private static void startAudio(final Context context) throws IOException {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
// do not play alarms if stream volume is 0 (typically because ringer mode is silent).
if (audioManager.getStreamVolume(AudioManager.STREAM_ALARM) != 0) {
mediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mediaPlayer.setLooping(true);
try {
mediaPlayer.prepare();
} catch (Exception e) {
Log.e("AlarmAlertActivity", "Prepare failed. Exiting", e);
return;
}
audioManager.requestAudioFocus(null,
AudioManager.STREAM_ALARM, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
mediaPlayer.start();
}
}
private static void stopAudio(final Context context) {
if (mediaPlayer != null) {
mediaPlayer.stop();
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.abandonAudioFocus(null);
mediaPlayer.release();
mediaPlayer = null;
}
}
// Load ringtone from a resource
private static void setDataSourceFromResource(Context context, MediaPlayer player, int res) throws IOException {
AssetFileDescriptor afd = context.getResources().openRawResourceFd(res);
if (afd != null) {
player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
}
}
}

View File

@ -27,10 +27,10 @@ public class AlarmNotify extends Service {
public void onDestroy() {
// If the notification is cancelled, stop updating.
notificationRunning = false;
Log.d("AlarmNotify", "1: Setting notificationRunning to false");
// Remove the notification in the notification bar
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.cancel(notifyID);
Log.d("AlarmNotify", "Notification stopped.");
}
@Override
@ -38,10 +38,10 @@ public class AlarmNotify extends Service {
final int UPDATE_INTERVAL = 10*1000; // Timer is updated six times a minute
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
Log.d("AlarmNotify", "Notification started.");
//final String phoneNumber = sharedPref.getString(getString(R.string.PhoneNumberPref), null);
final int gracePeriod = sharedPref.getInt(getString(R.string.GracePeriodPref), 60);
// convert gracePeriod to milliseconds and calculate when it'll fire
final long endTime = System.currentTimeMillis() + (gracePeriod * 60 * 1000);
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_grey);
final NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
@ -55,6 +55,8 @@ public class AlarmNotify extends Service {
.setAutoCancel(false)
.setPriority(Notification.PRIORITY_HIGH);
// TODO if alarm alert is snoozing and we cancel, cancel the snooze.
// Set up dismiss action
Intent cancellerIntent = new Intent(getBaseContext(), CancelGraceReceiver.class);
PendingIntent cancellerPendingIntent = PendingIntent.getBroadcast(getBaseContext(), MainActivity.CANCEL_GRACE_REQUEST, cancellerIntent, PendingIntent.FLAG_CANCEL_CURRENT);
@ -69,12 +71,13 @@ public class AlarmNotify extends Service {
/**
* TODO load alert activity (without sound or vibration) on select?
* TODO This would allow the user to test competence
Intent alertActivityIntent = new Intent(this, AlarmAlertActivity.class);
alertActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
notification.setContentIntent(alertActivityIntent);
* something like:
Intent alarmAlertIntent = new Intent(this, AlarmAlertActivity.class);
PendingIntent alarmPendingIntent = PendingIntent.getBroadcast(this, 0, alarmAlertIntent, 0);
notification.setContentIntent(alarmPen`dingIntent);
*/
nm.cancel(notifyID);
nm.notify(notifyID, notification.build());
@ -82,21 +85,22 @@ public class AlarmNotify extends Service {
@Override
public void run() {
notificationRunning = true;
Log.d("AlarmNotify", "2: Setting notificationRunning to true");
int max = 1000;
// Convert endTime from milliseconds to seconds, and translate to time remaining
int secondsLeft = (int) ((endTime - System.currentTimeMillis())) / (1000);
int gracePeriodSeconds = gracePeriod * 60;
// Multiply each int by 1000 for greater progress resolution
int progress = (((gracePeriodSeconds * 1000) - (secondsLeft * 1000)) * max) / (gracePeriodSeconds * 1000);
/* TODO check that graceEndTime is always set.
if (AlarmReceiver.graceEndTime == 0) {
AlarmReceiver.graceEndTime = System.currentTimeMillis() + (gracePeriod * 60 * 1000);
}*/
// Count in milliseconds for greater progress resolution
int milliSecondsLeft = (int) ((AlarmReceiver.graceEndTime - System.currentTimeMillis()));
int gracePeriodMilliSeconds = gracePeriod * 60 * 1000;
int progress = ((gracePeriodMilliSeconds - milliSecondsLeft) * max) / gracePeriodMilliSeconds;
while (progress < max) {
// Stop the thread if cancelled elsewhere
Log.d("AlarmNotify", "notificationRunning is " + notificationRunning);
// Stop the thread if the notification is cancelled elsewhere
if (!notificationRunning) {
return;
}
int minutesLeft = secondsLeft / 60;
int minutesLeft = (milliSecondsLeft / 1000) / 60;
if (Build.VERSION.SDK_INT >= 11) {
notification.setContentText(String.format(getString(R.string.notificationText), MainActivity.MinutesToGracePeriodStr(minutesLeft)));
notification.setProgress(max, progress, false);
@ -104,12 +108,12 @@ public class AlarmNotify extends Service {
nm.notify(notifyID, notification.build());
}
// Prepare secondsLeft and progress for the next loop
secondsLeft = secondsLeft - (UPDATE_INTERVAL / 1000);
milliSecondsLeft = milliSecondsLeft - UPDATE_INTERVAL;
// Multiply each int by 1000 for greater progress resolution
progress = (((gracePeriodSeconds * 1000) - (secondsLeft * 1000)) * max) / (gracePeriodSeconds * 1000);
Log.d("AlarmNotify", "secondsLeft is " + secondsLeft + " and progress is " + progress + " (gracePeriodSeconds is " + gracePeriodSeconds + ")");
// Sleeps the thread, simulating an operation
// that takes time
progress = ((gracePeriodMilliSeconds - milliSecondsLeft) * max) / gracePeriodMilliSeconds;
//Log.d("AlarmNotify", "milliSecondsLeft is " + milliSecondsLeft + " and progress is " + progress + " (gracePeriodMilliSeconds is " + gracePeriodMilliSeconds + ")");
// Sleep until we need to update again
try {
Thread.sleep(UPDATE_INTERVAL);
} catch (InterruptedException e) {

View File

@ -1,34 +1,55 @@
package za.org.treehouse.hypoalarm;
import android.app.AlarmManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.WindowManager;
import android.widget.Toast;
import java.util.Calendar;
/**
* TODO change alarm state if a phone call comes in
*
* TODO display notification if alarm is about to go off (and allow user to cancel it before alarm goes off)
*
* TODO allow snooze state
*/
public class AlarmReceiver extends BroadcastReceiver {
private static final int SNOOZE_TIME = 1000*20; //1000*60*5; // Snooze for 5 minutes if need be
private static final int ALERT_LIFE = 1000*10; //1000*60*2; // 2 minutes
private static SharedPreferences sharedPref;
private static AlarmManager alarmManager, graceManager;
private static PendingIntent alarmPendingIntent, gracePendingIntent;
private static Intent alertActivityIntent, notifyIntent;
public static volatile String alarmStatus; // Register ALARM_DISMISSED and its brethren here
public static final String ALARM_RUNNING = "ALARM_RUNNING";
public static final String ALARM_DISMISSED = "ALARM_DISMISSED";
public static final String ALARM_IGNORED = "ALARM_IGNORED";
public static final String ALARM_SNOOZED = "ALARM_SNOOZED";
public static final String ALARM_SNOOZE_RUNNING = "ALARM_SNOOZE_RUNNING";
public static long graceEndTime;
@Override
public void onReceive(Context context, Intent intent) {
public void onReceive(final Context context, Intent intent) {
sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
Boolean alarmActive = sharedPref.getBoolean(context.getString(R.string.AlarmActivePref), true);
int gracePeriod = sharedPref.getInt(context.getString(R.string.GracePeriodPref), 60);
String alarmTimeStr = sharedPref.getString(context.getString(R.string.AlarmTimePref), null);
if (alarmActive) {
// Set a grace period alarm to send SMS
int gracePeriod = sharedPref.getInt(context.getString(R.string.GracePeriodPref), 60);
// if nothing else happens, assume the alert was ignored.
alarmStatus = ALARM_RUNNING;
// Set a grace period alarm to send SMS
Calendar graceCal = Calendar.getInstance();
graceCal.set(Calendar.SECOND, 0);
graceCal.add(Calendar.MINUTE, gracePeriod);
@ -43,16 +64,20 @@ public class AlarmReceiver extends BroadcastReceiver {
}
Log.d("AlarmReceiver", "Setting grace alarm for " + MainActivity.debugDate(graceCal));
// Allow user to acknowledge alarm and cancel grace alarm
Intent alertActivityIntent = new Intent(context, AlarmAlertActivity.class);
// Calculate when the grace period 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);
context.startActivity(alertActivityIntent);
// 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()
String alarmTimeStr = sharedPref.getString(context.getString(R.string.AlarmTimePref), null);
// Calendar automatically advances the day since alarmTimeStr is now in the past.
// (Calendar will automatically advance the day since today's alarmTimeStr is now in the past.)
Calendar cal = MainActivity.TimeStringToCalendar(alarmTimeStr);
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmPendingIntent = PendingIntent.getBroadcast(context, MainActivity.ALARM_REQUEST, intent, 0);
@ -65,4 +90,88 @@ public class AlarmReceiver extends BroadcastReceiver {
Log.d("AlarmReceiver", "Resetting alarm for " + MainActivity.debugDate(cal));
}
}
public static void startAlert(final Context context) {
Log.d("AlarmReceiver", "Starting alarm; status is " + alarmStatus);
// Turn off any notifications first
context.stopService(notifyIntent);
context.startActivity(alertActivityIntent);
AlarmKlaxon.start(context);
// Turn off the alert activity after a period, and switch to a notification
new Handler().postDelayed(new Runnable() {
public void run() {
// Close the dialogue and switch to notification
// if the Activity has not been closed by the user
// (that is, snoozeAlert and dismissAlert have not been called)
// TODO don't run if we've just snoozed from home/back button, but do run if
// TODO we want to finish the snooze alert activity...
if (alarmStatus.contentEquals(ALARM_DISMISSED) ||
alarmStatus.contentEquals(ALARM_SNOOZED)) {
return;
}
// Stop if we're running the snooze alert
if (alarmStatus.contentEquals(ALARM_SNOOZE_RUNNING)) {
stopAlert(context);
} else {
alarmStatus = ALARM_IGNORED; // This is true, although we are about to switch to ALARM_SNOOZED
snoozeAlarm(context);
}
}
}, ALERT_LIFE);
}
public static void stopAlert(final Context context) {
Log.d("AlarmReceiver", "Stopping alarm; status is " + alarmStatus);
AlarmKlaxon.stop(context);
AlarmAlertActivity.alertActivity.finish();
// Display a notification if the alarm hasn't been dismissed
if (!alarmStatus.contentEquals(ALARM_DISMISSED)) {
context.startService(notifyIntent);
}
}
public static void dismissAlarm(final Context context) {
Log.d("AlarmReceiver", "Dismissing alarm");
alarmStatus = ALARM_DISMISSED;
// Close the alert and all notifications
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);
}
// TODO should the snooze reset the time at which the grace period alarm fires?
public static void snoozeAlarm(final Context context) {
Log.d("AlarmReceiver", "Snoozing alarm");
stopAlert(context);
// Close the alert, stop the klaxon, and start the notification,
// but only if there's time left before the gracePeriod triggers,
// and we haven't snoozed before
if (((System.currentTimeMillis() + SNOOZE_TIME) < graceEndTime) &&
(!alarmStatus.contentEquals(ALARM_SNOOZED)) &&
(!alarmStatus.contentEquals(ALARM_DISMISSED))) {
new Handler().postDelayed(new Runnable() {
public void run() {
Log.d("AlarmReceiver", "Resuming after snooze; status is " + alarmStatus);
// Don't run if the alarm was dismissed before the timer ran out
// (because a notification was acknowledged)
if (!alarmStatus.contentEquals(ALARM_DISMISSED)) {
alarmStatus = ALARM_SNOOZE_RUNNING;
startAlert(context);
}
}
}, SNOOZE_TIME);
// Change alarm status from ignored to snoozed
alarmStatus = ALARM_SNOOZED;
}
}
public static void setAlarmStatus (String status) {
Log.d("AlarmReceiver", "Setting alarm status to " + status);
alarmStatus = status;
}
}

View File

@ -18,6 +18,9 @@ public class CancelGraceReceiver extends BroadcastReceiver {
graceManager.cancel(gracePendingIntent);
Log.d("CancelGraceReceiver", "Cancelled grace alarm");
// Ensure that any snoozes that are pending never happen.
AlarmReceiver.setAlarmStatus(AlarmReceiver.ALARM_DISMISSED);
// Display toast
Toast.makeText(context, context.getString(R.string.alarmCancelToast), Toast.LENGTH_LONG).show();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 67 KiB

View File

@ -2,6 +2,8 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:seekarc="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AlarmNotificationActivity">
@ -9,6 +11,34 @@
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.triggertrap.seekarc.SeekArc
android:id="@+id/cancel_dialog_seekArc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="100dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
seekarc:thumb="@drawable/ic_launcher"
seekarc:clockwise="false"
seekarc:rotation="0"
seekarc:startAngle="35"
seekarc:sweepAngle="295"
seekarc:arcWidth="10dp"
seekarc:progressWidth="20dp"
seekarc:roundEdges="true"
seekarc:touchInside="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="HypoAlarm!"
android:id="@+id/cancel_dialog_title"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_marginTop="25dp" />
<!--
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -36,5 +66,28 @@
android:layout_marginTop="25dp"
android:layout_below="@+id/cancel_dialog_title"
android:layout_centerHorizontal="true" />
-->
<!--
<net.sebastianopoggi.ui.GlowPadBackport.GlowPadView
android:id="@+id/incomingCallWidget"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:background="@android:color/black"
android:visibility="visible"
android:gravity="top"
app:targetDrawables="@array/incoming_call_widget_2way_targets"
app:handleDrawable="@drawable/ic_in_call_touch_handle"
app:innerRadius="@dimen/glowpadview_inner_radius"
app:outerRadius="@dimen/glowpadview_target_placement_radius"
app:outerRingDrawable="@drawable/ic_lockscreen_outerring"
app:snapMargin="@dimen/glowpadview_snap_margin"
app:vibrationDuration="20"
app:feedbackCount="1"
app:glowRadius="@dimen/glowpadview_glow_radius"
app:pointDrawable="@drawable/ic_lockscreen_glowdot"/>
-->
</RelativeLayout>
</FrameLayout>

View File

@ -3,4 +3,30 @@
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<!-- Default target placement radius for GlowPadView. Should be 1/2 of outerring diameter. -->
<dimen name="glowpadview_target_placement_radius">135dip</dimen>
<!-- Default glow radius for GlowPadView -->
<dimen name="glowpadview_glow_radius">75dip</dimen>
<!-- Default distance beyond which GlowPadView snaps to the matching target -->
<dimen name="glowpadview_snap_margin">40dip</dimen>
<!-- Default distance from each snap target that GlowPadView considers a "hit" -->
<dimen name="glowpadview_inner_radius">15dip</dimen>
<!-- Size of lockscreen outerring on unsecure unlock LockScreen -->
<dimen name="keyguard_lockscreen_outerring_diameter">270dp</dimen>
<!-- Circle size for incoming call widget's each item. -->
<dimen name="incoming_call_widget_circle_size">94dp</dimen>
<!-- Margin used for incoming call widget's icon for each item.
This should be same as "(incoming_call_widget_circle_size - icon_size)/2".
Right now answer/decline/reject icons have 38dp width/height.
So, (94 - 38)/2 ==> 28dp -->
<dimen name="incoming_call_widget_asset_margin">28dp</dimen>
</resources>

View File

@ -57,4 +57,11 @@
<string name="alarmCancelled">All HypoAlarms cancelled</string>
<array name="incoming_call_widget_2way_targets">
<item>@drawable/ic_lockscreen_answer</item>
<item>@null</item>
<item>@drawable/ic_lockscreen_decline</item>
<item>@null</item>"
</array>
</resources>

View File

@ -5,4 +5,13 @@
<!-- Customize your theme here. -->
</style>
<style name="SeekArc">
<item name="arcColor">@color/progress_gray_dark</item>
</style>
<style name="SeekArcLight">
<item name="arcColor">@color/progress_gray</item>
</style>
</resources>