From f7c788cf4676096b51427e4f198013ca86da08a2 Mon Sep 17 00:00:00 2001 From: Phillip Hsu Date: Sun, 29 May 2016 00:50:27 -0700 Subject: [PATCH] Created UpcomingAlarmReceiver to handle upcoming alarm notifications --- app/src/main/AndroidManifest.xml | 12 ++++++-- .../com/philliphsu/clock2/MainActivity.java | 19 ++++++++++-- .../clock2/UpcomingAlarmReceiver.java | 29 +++++++++++++++++++ .../clock2/ringtone/RingtoneActivity.java | 8 ++++- .../clock2/ringtone/RingtoneService.java | 4 +-- .../clock2/RingtoneServiceTest.java | 19 ++++++++++++ 6 files changed, 83 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/com/philliphsu/clock2/UpcomingAlarmReceiver.java create mode 100644 app/src/test/java/com/philliphsu/clock2/RingtoneServiceTest.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index caae57a..bce0a32 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,7 +9,7 @@ android:supportsRtl="true" android:theme="@style/AppTheme"> @@ -19,17 +19,23 @@ + + + \ No newline at end of file diff --git a/app/src/main/java/com/philliphsu/clock2/MainActivity.java b/app/src/main/java/com/philliphsu/clock2/MainActivity.java index bb01ce5..48cc0a5 100644 --- a/app/src/main/java/com/philliphsu/clock2/MainActivity.java +++ b/app/src/main/java/com/philliphsu/clock2/MainActivity.java @@ -63,7 +63,7 @@ public class MainActivity extends AppCompatActivity { @Override public void onClick(View view) { scheduleAlarm(); - Snackbar.make(view, "Alarm set for 1 minute from now", Snackbar.LENGTH_LONG) + Snackbar.make(view, "Alarm set for 1 minute from now", Snackbar.LENGTH_INDEFINITE) .setAction("Dismiss", new View.OnClickListener() { @Override public void onClick(View v) { @@ -180,17 +180,32 @@ public class MainActivity extends AppCompatActivity { // by this one. For most of our uses, the relevant criteria for equality will be the // action, the data, and the class (component). Although not documented, the request code // of a PendingIntent is also considered to determine equality of two intents. + + // WAKEUP alarm types wake the CPU up, but NOT the screen. If that is what you want, you need + // to handle that yourself by using a wakelock, etc.. + // We use a WAKEUP alarm to send the upcoming alarm notification so it goes off even if the + // device is asleep. Otherwise, it will not go off until the device is turned back on. + // todo: use alarm's ring time - (number of hours to be notified in advance, converted to millis) + am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), notifyUpcomingAlarmIntent()); // todo: get alarm's ring time - am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 60000, alarmIntent()); + am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10000, alarmIntent()); } private PendingIntent alarmIntent() { // TODO: Use appropriate subclass instead Intent intent = new Intent(this, RingtoneActivity.class) .setData(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)); + // TODO: Pass in the id of the alarm to the intent. Alternatively, if the upcoming alarm note + // only needs to show the alarm's ring time, just pass in the alarm's ringsAt(). // TODO: Use unique request codes per alarm. // If a PendingIntent with this request code already exists, then we are likely modifying // an alarm, so we should cancel the existing intent. return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); } + + private PendingIntent notifyUpcomingAlarmIntent() { + Intent intent = new Intent(this, UpcomingAlarmReceiver.class); + // TODO: Use unique request codes per alarm. + return PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); + } } diff --git a/app/src/main/java/com/philliphsu/clock2/UpcomingAlarmReceiver.java b/app/src/main/java/com/philliphsu/clock2/UpcomingAlarmReceiver.java new file mode 100644 index 0000000..c49cf49 --- /dev/null +++ b/app/src/main/java/com/philliphsu/clock2/UpcomingAlarmReceiver.java @@ -0,0 +1,29 @@ +package com.philliphsu.clock2; + +import android.app.Notification; +import android.app.NotificationManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.support.v4.app.NotificationCompat; + +public class UpcomingAlarmReceiver extends BroadcastReceiver { + public static final String ACTION_CANCEL_NOTIFICATION + = "com.philliphsu.clock2.action.CANCEL_NOTIFICATION"; + + @Override + public void onReceive(Context context, Intent intent) { + NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + if (ACTION_CANCEL_NOTIFICATION.equals(intent.getAction())) { + nm.cancel("tag", 0); + } else { + Notification note = new NotificationCompat.Builder(context) + .setSmallIcon(R.mipmap.ic_launcher) + .setContentTitle("Upcoming alarm") + .setContentText("Ring time here") + .build(); + // todo actions + nm.notify("tag", 0, note); + } + } +} diff --git a/app/src/main/java/com/philliphsu/clock2/ringtone/RingtoneActivity.java b/app/src/main/java/com/philliphsu/clock2/ringtone/RingtoneActivity.java index 7607dd5..3dce7f4 100644 --- a/app/src/main/java/com/philliphsu/clock2/ringtone/RingtoneActivity.java +++ b/app/src/main/java/com/philliphsu/clock2/ringtone/RingtoneActivity.java @@ -11,6 +11,7 @@ import android.view.MotionEvent; import android.view.View; import com.philliphsu.clock2.R; +import com.philliphsu.clock2.UpcomingAlarmReceiver; import static com.philliphsu.clock2.util.Preconditions.checkNotNull; @@ -19,7 +20,7 @@ import static com.philliphsu.clock2.util.Preconditions.checkNotNull; * status bar and navigation/system bar) with user interaction. * * TODO: Make this abstract and make appropriate subclasses for Alarms and Timers. - * TODO: Use this together with RingtoneService. + * TODO: Implement dismiss and extend logic here. */ public class RingtoneActivity extends AppCompatActivity { /** @@ -97,9 +98,14 @@ public class RingtoneActivity extends AppCompatActivity { super.onCreate(savedInstanceState); setContentView(R.layout.activity_ringtone); + // Play the ringtone Uri ringtone = checkNotNull(getIntent().getData()); Intent intent = new Intent(this, RingtoneService.class).setData(ringtone); startService(intent); + // Cancel the upcoming alarm notification + Intent intent2 = new Intent(this, UpcomingAlarmReceiver.class) + .setAction(UpcomingAlarmReceiver.ACTION_CANCEL_NOTIFICATION); + sendBroadcast(intent2); mVisible = true; mControlsView = findViewById(R.id.fullscreen_content_controls); diff --git a/app/src/main/java/com/philliphsu/clock2/ringtone/RingtoneService.java b/app/src/main/java/com/philliphsu/clock2/ringtone/RingtoneService.java index 2424438..9de5578 100644 --- a/app/src/main/java/com/philliphsu/clock2/ringtone/RingtoneService.java +++ b/app/src/main/java/com/philliphsu/clock2/ringtone/RingtoneService.java @@ -111,9 +111,9 @@ public class RingtoneService extends Service { private void scheduleAutoSilence() { // TODO: Read prefs //SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); - int minutes = 2; /*Integer.parseInt(pref.getString( + /*int minutes = Integer.parseInt(pref.getString( getString(R.string.key_silence_after), "15"));*/ - mSilenceHandler.postDelayed(mSilenceRunnable, minutes * 60000); + mSilenceHandler.postDelayed(mSilenceRunnable, 10000); } } diff --git a/app/src/test/java/com/philliphsu/clock2/RingtoneServiceTest.java b/app/src/test/java/com/philliphsu/clock2/RingtoneServiceTest.java new file mode 100644 index 0000000..38507ce --- /dev/null +++ b/app/src/test/java/com/philliphsu/clock2/RingtoneServiceTest.java @@ -0,0 +1,19 @@ +package com.philliphsu.clock2; + +import com.philliphsu.clock2.ringtone.RingtoneService; + +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +/** + * Created by Phillip Hsu on 5/28/2016. + * + * TODO: Write unit tests... + */ +@RunWith(MockitoJUnitRunner.class) +public class RingtoneServiceTest { + + @Mock RingtoneService mRingtoneService; + +}