summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtem Chep <artemchep@gmail.com>2013-01-08 10:36:33 -0500
committerDanny Baumann <dannybaumann@web.de>2013-01-22 11:16:46 +0100
commitd8aa32d1fbbd1fcc186514ec2d37a8c2606f6eba (patch)
treece2decd3c3595113f640034f696dd5789cea2eec
parentfc06d831472c6f56fa02acb6563417117bca6c35 (diff)
downloadandroid_packages_apps_DeskClock-d8aa32d1fbbd1fcc186514ec2d37a8c2606f6eba.tar.gz
android_packages_apps_DeskClock-d8aa32d1fbbd1fcc186514ec2d37a8c2606f6eba.tar.bz2
android_packages_apps_DeskClock-d8aa32d1fbbd1fcc186514ec2d37a8c2606f6eba.zip
Added flip and shake to snooze
both the actions flipping the phone, and shaking the phone can do one of the following operations 1. do nothing 2. snooze the alarm 3. dismiss the alarm has been taken from Artem AchepClock implementation for ICS deskclock source at http://github.com/Achep/android_packages_apps_DeskClock PatchSet2 : Eliminated White Spaces PatchSet3 : Fixed a line issue PatchSet4 : Updated Correct Author PatchSet5 : Really updated Author PatchSet6 : Fixed a few lines, in-line comments PatchSet7 : Cleanup; addressed Danny's comments PatchSet8 : More cleanup PatchSet10: Clean up string resources Change-Id: Ifea8185690b07923b0c7cb3ab9b33ad5da7306e8
-rw-r--r--res/values/strings.xml28
-rw-r--r--res/xml/settings.xml17
-rw-r--r--src/com/android/deskclock/AlarmAlertFullScreen.java177
-rw-r--r--src/com/android/deskclock/SettingsActivity.java26
4 files changed, 243 insertions, 5 deletions
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b3a4cb4d1..5e96d7734 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -195,6 +195,24 @@
<item quantity="other">minutes</item>
</plurals>
+ <!-- Setting title for the flip action setting. -->
+ <string name="flip_action_title">Flip action</string>
+
+ <!-- Dialog title of the flip action setting. -->
+ <string name="flip_action_dialog_title">Flip device to\u2026</string>
+
+ <!-- Setting summary for the flip action setting. -->
+ <string name="flip_action_summary">Flipping the phone down will <xliff:g id="action">%s</xliff:g></string>
+
+ <!-- Setting title for the shake action setting. -->
+ <string name="shake_action_title">Shake action</string>
+
+ <!-- Dialog title for the shake action setting. -->
+ <string name="shake_action_dialog_title">Shake device to\u2026</string>
+
+ <!-- Setting summary for the shake action setting. -->
+ <string name="shake_action_summary">Shaking the phone will <xliff:g id="action">%s</xliff:g></string>
+
<!-- Auto silence preference title -->
<string name="auto_silence_title">Silence after</string>
@@ -264,7 +282,15 @@
<item>Snooze</item>
<item>Dismiss</item>
<item>Do nothing</item>
- </string-array>
+ </string-array>
+
+ <!-- Summary texts for shake and flip actions. Must be ordered by numerical
+ value (do nothing = 0, snooze = 1, dismiss = 2) -->
+ <string-array name="action_summary_entries">
+ <item>do nothing</item>
+ <item>snooze alarm</item>
+ <item>dismiss alarm</item>
+ </string-array>
<!-- Values for the side-button setting. -->
<string-array name="volume_button_setting_values" translatable="false">
diff --git a/res/xml/settings.xml b/res/xml/settings.xml
index 22e0d1712..5d8a356ef 100644
--- a/res/xml/settings.xml
+++ b/res/xml/settings.xml
@@ -39,6 +39,23 @@
<PreferenceCategory
android:title="@string/alarm_settings">
+
+ <ListPreference
+ android:key="flip_action"
+ android:title="@string/flip_action_title"
+ android:dialogTitle="@string/flip_action_dialog_title"
+ android:entries="@array/volume_button_setting_entries"
+ android:entryValues="@array/volume_button_setting_values"
+ android:defaultValue="0" />
+
+ <ListPreference
+ android:key="shake_action"
+ android:title="@string/shake_action_title"
+ android:dialogTitle="@string/shake_action_dialog_title"
+ android:entries="@array/volume_button_setting_entries"
+ android:entryValues="@array/volume_button_setting_values"
+ android:defaultValue="1"/>
+
<ListPreference
android:key="auto_silence"
android:title="@string/auto_silence_title"
diff --git a/src/com/android/deskclock/AlarmAlertFullScreen.java b/src/com/android/deskclock/AlarmAlertFullScreen.java
index 0cf49f89e..76166a9d2 100644
--- a/src/com/android/deskclock/AlarmAlertFullScreen.java
+++ b/src/com/android/deskclock/AlarmAlertFullScreen.java
@@ -26,6 +26,11 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
+import android.content.SharedPreferences;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -53,6 +58,9 @@ public class AlarmAlertFullScreen extends Activity implements GlowPadView.OnTrig
// These defaults must match the values in res/xml/settings.xml
private static final String DEFAULT_SNOOZE = "10";
private static final String DEFAULT_VOLUME_BEHAVIOR = "2";
+ private static final String DEFAULT_FLIP_ACTION = "0";
+ private static final String DEFAULT_SHAKE_ACTION = "1";
+
protected static final String SCREEN_OFF = "screen_off";
protected Alarm mAlarm;
@@ -67,6 +75,13 @@ public class AlarmAlertFullScreen extends Activity implements GlowPadView.OnTrig
private static final long PING_AUTO_REPEAT_DELAY_MSEC = 1200;
private boolean mPingEnabled = true;
+ private int mFlipAction;
+ private int mShakeAction;
+
+ // constants for no action/snooze/dismiss
+ private static final int ALARM_NO_ACTION = 0;
+ private static final int ALARM_SNOOZE = 1;
+ private static final int ALARM_DISMISS = 2;
// Receives the ALARM_KILLED action from the AlarmKlaxon,
// and also ALARM_SNOOZE_ACTION / ALARM_DISMISS_ACTION from other applications
@@ -101,6 +116,105 @@ public class AlarmAlertFullScreen extends Activity implements GlowPadView.OnTrig
}
};
+ private final SensorEventListener mFlipListener = new SensorEventListener() {
+ private static final int FACE_UP_LOWER_LIMIT = -45;
+ private static final int FACE_UP_UPPER_LIMIT = 45;
+ private static final int FACE_DOWN_UPPER_LIMIT = 135;
+ private static final int FACE_DOWN_LOWER_LIMIT = -135;
+ private static final int TILT_UPPER_LIMIT = 45;
+ private static final int TILT_LOWER_LIMIT = -45;
+ private static final int SENSOR_SAMPLES = 3;
+
+ private boolean mWasFaceUp;
+ private boolean[] mSamples = new boolean[SENSOR_SAMPLES];
+ private int mSampleIndex;
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int acc) {
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ // Add a sample overwriting the oldest one. Several samples
+ // are used
+ // to avoid the erroneous values the sensor sometimes
+ // returns.
+ float y = event.values[1];
+ float z = event.values[2];
+
+ if (!mWasFaceUp) {
+ // Check if its face up enough.
+ mSamples[mSampleIndex] = y > FACE_UP_LOWER_LIMIT
+ && y < FACE_UP_UPPER_LIMIT
+ && z > TILT_LOWER_LIMIT && z < TILT_UPPER_LIMIT;
+
+ // The device first needs to be face up.
+ boolean faceUp = true;
+ for (boolean sample : mSamples) {
+ faceUp = faceUp && sample;
+ }
+ if (faceUp) {
+ mWasFaceUp = true;
+ for (int i = 0; i < SENSOR_SAMPLES; i++) {
+ mSamples[i] = false;
+ }
+ }
+ } else {
+ // Check if its face down enough. Note that wanted
+ // values go from FACE_DOWN_UPPER_LIMIT to 180
+ // and from -180 to FACE_DOWN_LOWER_LIMIT
+ mSamples[mSampleIndex] = (y > FACE_DOWN_UPPER_LIMIT || y < FACE_DOWN_LOWER_LIMIT)
+ && z > TILT_LOWER_LIMIT
+ && z < TILT_UPPER_LIMIT;
+
+ boolean faceDown = true;
+ for (boolean sample : mSamples) {
+ faceDown = faceDown && sample;
+ }
+ if (faceDown) {
+ handleAction(mFlipAction);
+ }
+ }
+
+ mSampleIndex = ((mSampleIndex + 1) % SENSOR_SAMPLES);
+ }
+ };
+
+ private final SensorEventListener mShakeListener = new SensorEventListener() {
+ private static final float SENSITIVITY = 16;
+ private static final int BUFFER = 5;
+ private float[] gravity = new float[3];
+ private float average = 0;
+ private int fill = 0;
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int acc) {
+ }
+
+ public void onSensorChanged(SensorEvent event) {
+ final float alpha = 0.8F;
+
+ for (int i = 0; i < 3; i++) {
+ gravity[i] = alpha * gravity[i] + (1 - alpha) * event.values[i];
+ }
+
+ float x = event.values[0] - gravity[0];
+ float y = event.values[1] - gravity[1];
+ float z = event.values[2] - gravity[2];
+
+ if (fill <= BUFFER) {
+ average += Math.abs(x) + Math.abs(y) + Math.abs(z);
+ fill++;
+ } else {
+ if (average / BUFFER >= SENSITIVITY) {
+ handleAction(mShakeAction);
+ }
+ average = 0;
+ fill = 0;
+ }
+ }
+ };
+
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -254,12 +368,12 @@ public class AlarmAlertFullScreen extends Activity implements GlowPadView.OnTrig
return (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
+ private SensorManager getSensorManager() {
+ return (SensorManager) getSystemService(Context.SENSOR_SERVICE);
+ }
+
// Dismiss the alarm.
private void dismiss(boolean killed) {
- if (LOG) {
- Log.v("AlarmAlertFullScreen - dismiss");
- }
-
Log.i(killed ? "Alarm killed" : "Alarm dismissed by user");
// The service told us that the alarm has been killed, do not modify
// the notification or stop the service.
@@ -272,6 +386,45 @@ public class AlarmAlertFullScreen extends Activity implements GlowPadView.OnTrig
finish();
}
+ private void attachListeners() {
+ final SensorManager sm = getSensorManager();
+
+ if (mFlipAction != ALARM_NO_ACTION) {
+ sm.registerListener(mFlipListener,
+ sm.getDefaultSensor(Sensor.TYPE_ORIENTATION),
+ SensorManager.SENSOR_DELAY_NORMAL);
+ }
+
+ if (mShakeAction != ALARM_NO_ACTION) {
+ sm.registerListener(mShakeListener,
+ sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
+ SensorManager.SENSOR_DELAY_GAME);
+ }
+ }
+
+ private void detachListeners() {
+ if (mFlipAction != ALARM_NO_ACTION) {
+ getSensorManager().unregisterListener(mFlipListener);
+ }
+ if (mShakeAction != ALARM_NO_ACTION) {
+ getSensorManager().unregisterListener(mShakeListener);
+ }
+ }
+
+ private void handleAction(int action) {
+ switch (action) {
+ case ALARM_SNOOZE:
+ snooze();
+ break;
+ case ALARM_DISMISS:
+ dismiss(false);
+ break;
+ case ALARM_NO_ACTION:
+ default:
+ break;
+ }
+ }
+
/**
* this is called when a second alarm is triggered while a
* previous alert window is still active.
@@ -302,6 +455,14 @@ public class AlarmAlertFullScreen extends Activity implements GlowPadView.OnTrig
if (LOG) {
Log.v("AlarmAlertFullScreen - onResume");
}
+
+ final SharedPreferences prefs = PreferenceManager.
+ getDefaultSharedPreferences(this);
+ mFlipAction = Integer.parseInt(prefs.getString(
+ SettingsActivity.KEY_FLIP_ACTION, DEFAULT_FLIP_ACTION));
+ mShakeAction = Integer.parseInt(prefs.getString(
+ SettingsActivity.KEY_SHAKE_ACTION, DEFAULT_SHAKE_ACTION));
+
// If the alarm was deleted at some point, disable snooze.
if (Alarms.getAlarm(getContentResolver(), mAlarm.id) == null) {
mGlowPadView.setTargetResources(R.array.dismiss_drawables);
@@ -313,6 +474,8 @@ public class AlarmAlertFullScreen extends Activity implements GlowPadView.OnTrig
if (getResources().getBoolean(R.bool.config_rotateAlarmAlert) || mIsDocked) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
+
+ attachListeners();
}
@Override
@@ -324,6 +487,12 @@ public class AlarmAlertFullScreen extends Activity implements GlowPadView.OnTrig
}
@Override
+ public void onPause() {
+ super.onPause();
+ detachListeners();
+ }
+
+ @Override
public boolean dispatchKeyEvent(KeyEvent event) {
// Do this on key down to handle a few of the system keys.
boolean up = event.getAction() == KeyEvent.ACTION_UP;
diff --git a/src/com/android/deskclock/SettingsActivity.java b/src/com/android/deskclock/SettingsActivity.java
index 2b512e877..021f8bf4e 100644
--- a/src/com/android/deskclock/SettingsActivity.java
+++ b/src/com/android/deskclock/SettingsActivity.java
@@ -47,6 +47,10 @@ public class SettingsActivity extends PreferenceActivity
"show_status_bar_icon";
static final String KEY_ALARM_SNOOZE =
"snooze_duration";
+ static final String KEY_FLIP_ACTION =
+ "flip_action";
+ static final String KEY_SHAKE_ACTION =
+ "shake_action";
static final String KEY_VOLUME_BEHAVIOR =
"volume_button_setting";
static final String KEY_AUTO_SILENCE =
@@ -166,6 +170,14 @@ public class SettingsActivity extends PreferenceActivity
final ListPreference listPref = (ListPreference) pref;
final int idx = listPref.findIndexOfValue((String) newValue);
listPref.setSummary(listPref.getEntries()[idx]);
+ } else if (KEY_FLIP_ACTION.equals(pref.getKey())) {
+ final ListPreference listPref = (ListPreference) pref;
+ String action = (String) newValue;
+ updateActionSummary(listPref, action, R.string.flip_action_summary);
+ } else if (KEY_SHAKE_ACTION.equals(pref.getKey())) {
+ final ListPreference listPref = (ListPreference) pref;
+ String action = (String) newValue;
+ updateActionSummary(listPref, action, R.string.shake_action_summary);
} else if (KEY_SHOW_STATUS_BAR_ICON.equals(pref.getKey())) {
// Check if any alarms are active. If yes and
// we allow showing the alarm icon, the icon will be shown.
@@ -184,6 +196,12 @@ public class SettingsActivity extends PreferenceActivity
}
}
+ private void updateActionSummary(ListPreference listPref, String action, int summaryResId) {
+ int i = Integer.parseInt(action);
+ listPref.setSummary(getString(summaryResId,
+ getResources().getStringArray(R.array.action_summary_entries)[i]));
+ }
+
private void refresh() {
ListPreference listPref = (ListPreference) findPreference(KEY_AUTO_SILENCE);
String delay = listPref.getValue();
@@ -206,6 +224,14 @@ public class SettingsActivity extends PreferenceActivity
listPref.setSummary(listPref.getEntry());
listPref.setOnPreferenceChangeListener(this);
+ listPref = (ListPreference) findPreference(KEY_FLIP_ACTION);
+ updateActionSummary(listPref, listPref.getValue(), R.string.flip_action_summary);
+ listPref.setOnPreferenceChangeListener(this);
+
+ listPref = (ListPreference) findPreference(KEY_SHAKE_ACTION);
+ updateActionSummary(listPref, listPref.getValue(), R.string.shake_action_summary);
+ listPref.setOnPreferenceChangeListener(this);
+
CheckBoxPreference hideStatusbarIcon = (CheckBoxPreference) findPreference(KEY_SHOW_STATUS_BAR_ICON);
hideStatusbarIcon.setOnPreferenceChangeListener(this);