Created UpcomingAlarmReceiver to handle upcoming alarm notifications

This commit is contained in:
Phillip Hsu 2016-05-29 00:50:27 -07:00
parent 37e7d3dd3b
commit f7c788cf46
6 changed files with 83 additions and 8 deletions

View File

@ -9,7 +9,7 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<activity <activity
android:name="com.philliphsu.clock2.MainActivity" android:name=".MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar">
<intent-filter> <intent-filter>
@ -19,17 +19,23 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:name="com.philliphsu.clock2.ringtone.RingtoneActivity" android:name=".ringtone.RingtoneActivity"
android:configChanges="orientation|keyboardHidden|screenSize" android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/title_activity_ringtone" android:label="@string/title_activity_ringtone"
android:theme="@style/FullscreenTheme"> android:theme="@style/FullscreenTheme">
</activity> </activity>
<service <service
android:name="com.philliphsu.clock2.ringtone.RingtoneService" android:name=".ringtone.RingtoneService"
android:enabled="true" android:enabled="true"
android:exported="false"> android:exported="false">
</service> </service>
<receiver
android:name=".UpcomingAlarmReceiver"
android:enabled="true"
android:exported="false">
</receiver>
</application> </application>
</manifest> </manifest>

View File

@ -63,7 +63,7 @@ public class MainActivity extends AppCompatActivity {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
scheduleAlarm(); 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() { .setAction("Dismiss", new View.OnClickListener() {
@Override @Override
public void onClick(View v) { 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 // 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 // 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. // 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 // 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() { private PendingIntent alarmIntent() {
// TODO: Use appropriate subclass instead // TODO: Use appropriate subclass instead
Intent intent = new Intent(this, RingtoneActivity.class) Intent intent = new Intent(this, RingtoneActivity.class)
.setData(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)); .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. // TODO: Use unique request codes per alarm.
// If a PendingIntent with this request code already exists, then we are likely modifying // If a PendingIntent with this request code already exists, then we are likely modifying
// an alarm, so we should cancel the existing intent. // an alarm, so we should cancel the existing intent.
return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); 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);
}
} }

View File

@ -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);
}
}
}

View File

@ -11,6 +11,7 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import com.philliphsu.clock2.R; import com.philliphsu.clock2.R;
import com.philliphsu.clock2.UpcomingAlarmReceiver;
import static com.philliphsu.clock2.util.Preconditions.checkNotNull; 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. * status bar and navigation/system bar) with user interaction.
* *
* TODO: Make this abstract and make appropriate subclasses for Alarms and Timers. * 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 { public class RingtoneActivity extends AppCompatActivity {
/** /**
@ -97,9 +98,14 @@ public class RingtoneActivity extends AppCompatActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ringtone); setContentView(R.layout.activity_ringtone);
// Play the ringtone
Uri ringtone = checkNotNull(getIntent().getData()); Uri ringtone = checkNotNull(getIntent().getData());
Intent intent = new Intent(this, RingtoneService.class).setData(ringtone); Intent intent = new Intent(this, RingtoneService.class).setData(ringtone);
startService(intent); startService(intent);
// Cancel the upcoming alarm notification
Intent intent2 = new Intent(this, UpcomingAlarmReceiver.class)
.setAction(UpcomingAlarmReceiver.ACTION_CANCEL_NOTIFICATION);
sendBroadcast(intent2);
mVisible = true; mVisible = true;
mControlsView = findViewById(R.id.fullscreen_content_controls); mControlsView = findViewById(R.id.fullscreen_content_controls);

View File

@ -111,9 +111,9 @@ public class RingtoneService extends Service {
private void scheduleAutoSilence() { private void scheduleAutoSilence() {
// TODO: Read prefs // TODO: Read prefs
//SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); //SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
int minutes = 2; /*Integer.parseInt(pref.getString( /*int minutes = Integer.parseInt(pref.getString(
getString(R.string.key_silence_after), getString(R.string.key_silence_after),
"15"));*/ "15"));*/
mSilenceHandler.postDelayed(mSilenceRunnable, minutes * 60000); mSilenceHandler.postDelayed(mSilenceRunnable, 10000);
} }
} }

View File

@ -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;
}