Implemented vibration for alarms

This commit is contained in:
Phillip Hsu 2016-06-14 01:29:12 -07:00
parent 22973eb262
commit 548ca6197e
5 changed files with 32 additions and 8 deletions

View File

@ -2,6 +2,8 @@
<manifest package="com.philliphsu.clock2" <manifest package="com.philliphsu.clock2"
xmlns:android="http://schemas.android.com/apk/res/android"> xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.VIBRATE"/>
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"

View File

@ -37,7 +37,7 @@ public class UpcomingAlarmReceiver extends BroadcastReceiver {
} else { } else {
Alarm alarm = checkNotNull(AlarmsRepository.getInstance(context).getItem(id)); Alarm alarm = checkNotNull(AlarmsRepository.getInstance(context).getItem(id));
if (ACTION_DISMISS_NOW.equals(intent.getAction())) { if (ACTION_DISMISS_NOW.equals(intent.getAction())) {
AlarmUtils.cancelAlarm(context, alarm, true); // TODO: Cancel only, do not reschedule. AlarmUtils.cancelAlarm(context, alarm, true);
} else { } else {
// Prepare notification // Prepare notification
String title; String title;

View File

@ -433,7 +433,7 @@ public class EditAlarmActivity extends BaseActivity implements AlarmNumpad.KeyLi
@Override @Override
public void cancelAlarm(Alarm alarm, boolean showToast) { public void cancelAlarm(Alarm alarm, boolean showToast) {
AlarmUtils.cancelAlarm(this, alarm, showToast); // TODO: Cancel only? AlarmUtils.cancelAlarm(this, alarm, showToast);
if (RingtoneActivity.isAlive()) { if (RingtoneActivity.isAlive()) {
Intent intent = new Intent(this, RingtoneActivity.class) Intent intent = new Intent(this, RingtoneActivity.class)
.setAction(RingtoneActivity.ACTION_UNBIND); .setAction(RingtoneActivity.ACTION_UNBIND);

View File

@ -157,7 +157,7 @@ public class RingtoneActivity extends AppCompatActivity implements RingtoneServi
} }
private void dismiss() { private void dismiss() {
AlarmUtils.cancelAlarm(this, mAlarm, false); AlarmUtils.cancelAlarm(this, mAlarm, false); // TODO do we really need to cancel the intent and alarm?
unbindAndFinish(); unbindAndFinish();
} }

View File

@ -4,7 +4,6 @@ import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.Service; import android.app.Service;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.Ringtone; import android.media.Ringtone;
@ -13,7 +12,9 @@ import android.net.Uri;
import android.os.Binder; import android.os.Binder;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.Vibrator;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.util.Log; import android.util.Log;
@ -43,6 +44,7 @@ public class RingtoneService extends Service { // TODO: abstract this, make subc
private static final String EXTRA_ITEM_ID = "com.philliphsu.clock2.ringtone.extra.ITEM_ID"; private static final String EXTRA_ITEM_ID = "com.philliphsu.clock2.ringtone.extra.ITEM_ID";
private AudioManager mAudioManager; private AudioManager mAudioManager;
@Nullable private Vibrator mVibrator;
private Ringtone mRingtone; private Ringtone mRingtone;
private Alarm mAlarm; private Alarm mAlarm;
private String mNormalRingTime; private String mNormalRingTime;
@ -55,8 +57,14 @@ public class RingtoneService extends Service { // TODO: abstract this, make subc
@Override @Override
public void run() { public void run() {
mAutoSilenced = true; mAutoSilenced = true;
mRingtone.stop(); // don't wait for activity to finish and unbind // don't wait for activity to finish and unbind
AlarmUtils.cancelAlarm(RingtoneService.this, mAlarm, false); // TODO: Is it really crucial for us to stop these immediately? User will probably not notice
// if this alarm gets to the point of auto-silencing.
mRingtone.stop();
if (mVibrator != null) {
mVibrator.cancel();
}
AlarmUtils.cancelAlarm(RingtoneService.this, mAlarm, false); // TODO do we really need to cancel the alarm and intent?
if (mRingtoneCallback != null) { if (mRingtoneCallback != null) {
// Finish the activity, which fires onDestroy() and then unbinds itself from this service. // Finish the activity, which fires onDestroy() and then unbinds itself from this service.
// All clients must be unbound before stopSelf() (and stopService()?) will succeed. // All clients must be unbound before stopSelf() (and stopService()?) will succeed.
@ -86,7 +94,7 @@ public class RingtoneService extends Service { // TODO: abstract this, make subc
if (ACTION_SNOOZE.equals(intent.getAction())) { if (ACTION_SNOOZE.equals(intent.getAction())) {
AlarmUtils.snoozeAlarm(this, alarm); AlarmUtils.snoozeAlarm(this, alarm);
} else if (ACTION_DISMISS.equals(intent.getAction())) { } else if (ACTION_DISMISS.equals(intent.getAction())) {
AlarmUtils.cancelAlarm(this, alarm, false); AlarmUtils.cancelAlarm(this, alarm, false); // TODO do we really need to cancel the intent and alarm?
} else { } else {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -104,6 +112,9 @@ public class RingtoneService extends Service { // TODO: abstract this, make subc
Log.d(TAG, "onDestroy()"); Log.d(TAG, "onDestroy()");
mRingtone.stop(); mRingtone.stop();
mAudioManager.abandonAudioFocus(null); // no listener was set mAudioManager.abandonAudioFocus(null); // no listener was set
if (mVibrator != null) {
mVibrator.cancel();
}
mSilenceHandler.removeCallbacks(mSilenceRunnable); mSilenceHandler.removeCallbacks(mSilenceRunnable);
if (mAutoSilenced) { if (mAutoSilenced) {
// Post notification that alarm was missed, or timer expired. // Post notification that alarm was missed, or timer expired.
@ -152,7 +163,10 @@ public class RingtoneService extends Service { // TODO: abstract this, make subc
.build(); .build();
startForeground(R.id.ringtone_service_notification, note); // TOneverDO: Pass 0 as the first argument startForeground(R.id.ringtone_service_notification, note); // TOneverDO: Pass 0 as the first argument
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
if (mAlarm.vibrates()) {
mVibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
}
// Request audio focus first, so we don't play our ringtone on top of any // Request audio focus first, so we don't play our ringtone on top of any
// other apps that currently have playback. // other apps that currently have playback.
int result = mAudioManager.requestAudioFocus( int result = mAudioManager.requestAudioFocus(
@ -166,6 +180,14 @@ public class RingtoneService extends Service { // TODO: abstract this, make subc
// Deprecated, but the alternative AudioAttributes requires API 21 // Deprecated, but the alternative AudioAttributes requires API 21
mRingtone.setStreamType(AudioManager.STREAM_ALARM); mRingtone.setStreamType(AudioManager.STREAM_ALARM);
mRingtone.play(); mRingtone.play();
if (mVibrator != null) {
mVibrator.vibrate(new long[] { // apply pattern
0, // millis to wait before turning vibrator on
500, // millis to keep vibrator on before turning off
500, // millis to wait before turning back on
500 // millis to keep on before turning off
}, 2 /* start repeating at this index of the array, after one cycle */);
}
scheduleAutoSilence(); scheduleAutoSilence();
} }
} }