mirror of https://github.com/tasks/tasks
Break up notifications, inject notification mgr
parent
4483a1a5c9
commit
bcfd96cfdb
@ -1,47 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2012 Todoroo Inc
|
|
||||||
*
|
|
||||||
* See the file "LICENSE" for the full license governing this code.
|
|
||||||
*/
|
|
||||||
package com.todoroo.andlib.service;
|
|
||||||
|
|
||||||
import android.app.Notification;
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notification Manager stub
|
|
||||||
*
|
|
||||||
* @author Tim Su <tim@todoroo.com>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public interface NotificationManager {
|
|
||||||
|
|
||||||
public void cancel(int id);
|
|
||||||
|
|
||||||
public void notify(int id, Notification notification);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiation of notification manager that passes through to
|
|
||||||
* Android's notification manager
|
|
||||||
*
|
|
||||||
* @author Tim Su <tim@todoroo.com>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static class AndroidNotificationManager implements NotificationManager {
|
|
||||||
private final android.app.NotificationManager nm;
|
|
||||||
public AndroidNotificationManager(Context context) {
|
|
||||||
nm = (android.app.NotificationManager)
|
|
||||||
context.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cancel(int id) {
|
|
||||||
nm.cancel(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notify(int id, Notification notification) {
|
|
||||||
nm.notify(id, notification);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,86 +1,89 @@
|
|||||||
package com.todoroo.astrid.reminders;
|
package com.todoroo.astrid.reminders;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.test.AndroidTestCase;
|
|
||||||
|
|
||||||
import com.todoroo.andlib.utility.Preferences;
|
import com.todoroo.andlib.test.TodorooTestCase;
|
||||||
|
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.tasks.R;
|
import org.tasks.R;
|
||||||
|
import org.tasks.preferences.Preferences;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static com.todoroo.astrid.reminders.Notifications.isQuietHours;
|
import static com.todoroo.astrid.reminders.ShowNotificationReceiver.isQuietHours;
|
||||||
import static org.tasks.Freeze.freezeAt;
|
import static org.tasks.Freeze.freezeAt;
|
||||||
import static org.tasks.Freeze.thaw;
|
import static org.tasks.Freeze.thaw;
|
||||||
import static org.tasks.TestUtilities.clearPreferences;
|
|
||||||
|
|
||||||
public class NotificationsTest extends AndroidTestCase {
|
public class NotificationsTest extends TodorooTestCase{
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
private static final int MILLIS_PER_HOUR = (int) TimeUnit.HOURS.toMillis(1);
|
private static final int MILLIS_PER_HOUR = (int) TimeUnit.HOURS.toMillis(1);
|
||||||
|
|
||||||
private static final DateTime now =
|
private static final DateTime now = new DateTime(2014, 1, 23, 18, 8, 31, 540);
|
||||||
new DateTime(2014, 1, 23, 18, 8, 31, 540);
|
|
||||||
|
|
||||||
|
private Preferences preferences;
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
clearPreferences(getContext());
|
preferences = new Preferences(getContext());
|
||||||
Preferences.setBoolean(R.string.p_rmd_enable_quiet, true);
|
preferences.clear();
|
||||||
|
preferences.setBoolean(R.string.p_rmd_enable_quiet, true);
|
||||||
freezeAt(now);
|
freezeAt(now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
thaw();
|
thaw();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNotQuietWhenQuietHoursDisabled() {
|
public void testNotQuietWhenQuietHoursDisabled() {
|
||||||
Preferences.setBoolean(R.string.p_rmd_enable_quiet, false);
|
preferences.setBoolean(R.string.p_rmd_enable_quiet, false);
|
||||||
setQuietHoursStart(18);
|
setQuietHoursStart(18);
|
||||||
setQuietHoursEnd(19);
|
setQuietHoursEnd(19);
|
||||||
|
|
||||||
assertFalse(isQuietHours());
|
assertFalse(isQuietHours(preferences));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIsQuietAtStartOfQuietHoursNoTimeWrap() {
|
public void testIsQuietAtStartOfQuietHoursNoTimeWrap() {
|
||||||
setQuietHoursStart(18);
|
setQuietHoursStart(18);
|
||||||
setQuietHoursEnd(19);
|
setQuietHoursEnd(19);
|
||||||
|
|
||||||
assertTrue(isQuietHours());
|
assertTrue(isQuietHours(preferences));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIsNotQuietWhenStartAndEndAreSame() {
|
public void testIsNotQuietWhenStartAndEndAreSame() {
|
||||||
setQuietHoursStart(18);
|
setQuietHoursStart(18);
|
||||||
setQuietHoursEnd(18);
|
setQuietHoursEnd(18);
|
||||||
|
|
||||||
assertFalse(isQuietHours());
|
assertFalse(isQuietHours(preferences));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIsNotQuietAtEndOfQuietHoursNoTimeWrap() {
|
public void testIsNotQuietAtEndOfQuietHoursNoTimeWrap() {
|
||||||
setQuietHoursStart(17);
|
setQuietHoursStart(17);
|
||||||
setQuietHoursEnd(18);
|
setQuietHoursEnd(18);
|
||||||
|
|
||||||
assertFalse(isQuietHours());
|
assertFalse(isQuietHours(preferences));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIsQuietAtStartOfQuietHoursTimeWrap() {
|
public void testIsQuietAtStartOfQuietHoursTimeWrap() {
|
||||||
setQuietHoursStart(18);
|
setQuietHoursStart(18);
|
||||||
setQuietHoursEnd(9);
|
setQuietHoursEnd(9);
|
||||||
|
|
||||||
assertTrue(isQuietHours());
|
assertTrue(isQuietHours(preferences));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIsNotQuietAtEndOfQuietHoursTimeWrap() {
|
public void testIsNotQuietAtEndOfQuietHoursTimeWrap() {
|
||||||
setQuietHoursStart(19);
|
setQuietHoursStart(19);
|
||||||
setQuietHoursEnd(18);
|
setQuietHoursEnd(18);
|
||||||
|
|
||||||
assertFalse(isQuietHours());
|
assertFalse(isQuietHours(preferences));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setQuietHoursStart(int hour) {
|
private void setQuietHoursStart(int hour) {
|
||||||
Preferences.setInt(R.string.p_rmd_quietStart, hour * MILLIS_PER_HOUR);
|
preferences.setInt(R.string.p_rmd_quietStart, hour * MILLIS_PER_HOUR);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setQuietHoursEnd(int hour) {
|
private void setQuietHoursEnd(int hour) {
|
||||||
Preferences.setInt(R.string.p_rmd_quietEnd, hour * MILLIS_PER_HOUR);
|
preferences.setInt(R.string.p_rmd_quietEnd, hour * MILLIS_PER_HOUR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,24 +0,0 @@
|
|||||||
package org.tasks.injection;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import dagger.ObjectGraph;
|
|
||||||
|
|
||||||
public class TestInjector implements Injector {
|
|
||||||
|
|
||||||
ObjectGraph objectGraph;
|
|
||||||
|
|
||||||
public TestInjector(Context context) {
|
|
||||||
objectGraph = ObjectGraph.create(new TestModule(context));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void inject(Object caller) {
|
|
||||||
objectGraph.inject(caller);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ObjectGraph getObjectGraph() {
|
|
||||||
return objectGraph;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,255 @@
|
|||||||
|
package com.todoroo.astrid.reminders;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.media.AudioManager;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.telephony.TelephonyManager;
|
||||||
|
|
||||||
|
import com.todoroo.andlib.utility.AndroidUtilities;
|
||||||
|
import com.todoroo.andlib.utility.DateUtilities;
|
||||||
|
import com.todoroo.astrid.utility.Flags;
|
||||||
|
import com.todoroo.astrid.voice.VoiceOutputService;
|
||||||
|
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
import org.tasks.R;
|
||||||
|
import org.tasks.injection.InjectingBroadcastReceiver;
|
||||||
|
import org.tasks.notifications.NotificationManager;
|
||||||
|
import org.tasks.preferences.Preferences;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.tasks.date.DateTimeUtils.currentTimeMillis;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receives requests to show an Astrid notification if they were not intercepted and handled
|
||||||
|
* by the in-app reminders in AstridActivity.
|
||||||
|
*
|
||||||
|
* @author Sam
|
||||||
|
*/
|
||||||
|
public class ShowNotificationReceiver extends InjectingBroadcastReceiver {
|
||||||
|
|
||||||
|
private static ExecutorService singleThreadVoicePool = Executors.newSingleThreadExecutor();
|
||||||
|
private static long lastNotificationSound = 0L;
|
||||||
|
|
||||||
|
@Inject NotificationManager notificationManager;
|
||||||
|
@Inject Preferences preferences;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
super.onReceive(context, intent);
|
||||||
|
|
||||||
|
int notificationId = intent.getIntExtra(Notifications.EXTRAS_NOTIF_ID, 0);
|
||||||
|
Intent customIntent = intent.getParcelableExtra(Notifications.EXTRAS_CUSTOM_INTENT);
|
||||||
|
int type = intent.getIntExtra(Notifications.EXTRAS_TYPE, 0);
|
||||||
|
String title = intent.getStringExtra(Notifications.EXTRAS_TITLE);
|
||||||
|
String text = intent.getStringExtra(Notifications.EXTRAS_TEXT);
|
||||||
|
int ringTimes = intent.getIntExtra(Notifications.EXTRAS_RING_TIMES, 1);
|
||||||
|
showNotification(context, notificationId, customIntent, type, title, text, ringTimes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if notification should sound
|
||||||
|
*/
|
||||||
|
private static boolean checkLastNotificationSound() {
|
||||||
|
long now = DateUtilities.now();
|
||||||
|
if (now - lastNotificationSound > 10000) {
|
||||||
|
lastNotificationSound = now;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return whether we're in quiet hours
|
||||||
|
*/
|
||||||
|
static boolean isQuietHours(Preferences preferences) {
|
||||||
|
boolean quietHoursEnabled = preferences.getBoolean(R.string.p_rmd_enable_quiet, false);
|
||||||
|
if (quietHoursEnabled) {
|
||||||
|
long quietHoursStart = new DateTime().withMillisOfDay(preferences.getInt(R.string.p_rmd_quietStart)).getMillis();
|
||||||
|
long quietHoursEnd = new DateTime().withMillisOfDay(preferences.getInt(R.string.p_rmd_quietEnd)).getMillis();
|
||||||
|
long now = currentTimeMillis();
|
||||||
|
if (quietHoursStart <= quietHoursEnd) {
|
||||||
|
if (now >= quietHoursStart && now < quietHoursEnd) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else { // wrap across 24/hour boundary
|
||||||
|
if (now >= quietHoursStart || now < quietHoursEnd) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows an Astrid notification. Pulls in ring tone and quiet hour settings
|
||||||
|
* from preferences. You can make it say anything you like.
|
||||||
|
*
|
||||||
|
* @param ringTimes number of times to ring (-1 = nonstop)
|
||||||
|
*/
|
||||||
|
private void showNotification(Context context, int notificationId, Intent intent, int type, String title,
|
||||||
|
String text, int ringTimes) {
|
||||||
|
// don't ring multiple times if random reminder
|
||||||
|
if (type == ReminderService.TYPE_RANDOM) {
|
||||||
|
ringTimes = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// quiet hours? unless alarm clock
|
||||||
|
boolean quietHours = (type == ReminderService.TYPE_ALARM || type == ReminderService.TYPE_DUE) ? false : isQuietHours(preferences);
|
||||||
|
|
||||||
|
PendingIntent pendingIntent = PendingIntent.getActivity(context,
|
||||||
|
notificationId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
|
||||||
|
// create notification object
|
||||||
|
final Notification notification = new Notification(
|
||||||
|
R.drawable.notif_astrid, text, System.currentTimeMillis());
|
||||||
|
notification.setLatestEventInfo(context,
|
||||||
|
title,
|
||||||
|
text,
|
||||||
|
pendingIntent);
|
||||||
|
notification.flags |= Notification.FLAG_AUTO_CANCEL;
|
||||||
|
if (preferences.getBoolean(R.string.p_rmd_persistent, true)) {
|
||||||
|
notification.flags |= Notification.FLAG_NO_CLEAR |
|
||||||
|
Notification.FLAG_SHOW_LIGHTS;
|
||||||
|
notification.ledOffMS = 5000;
|
||||||
|
notification.ledOnMS = 700;
|
||||||
|
notification.ledARGB = Color.YELLOW;
|
||||||
|
} else {
|
||||||
|
notification.defaults = Notification.DEFAULT_LIGHTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioManager audioManager = (AudioManager) context.getSystemService(
|
||||||
|
Context.AUDIO_SERVICE);
|
||||||
|
|
||||||
|
// detect call state
|
||||||
|
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||||
|
int callState = tm.getCallState();
|
||||||
|
|
||||||
|
boolean voiceReminder = preferences.getBoolean(R.string.p_voiceRemindersEnabled, false);
|
||||||
|
|
||||||
|
// if multi-ring is activated and the setting p_rmd_maxvolume allows it, set up the flags for insistent
|
||||||
|
// notification, and increase the volume to full volume, so the user
|
||||||
|
// will actually pay attention to the alarm
|
||||||
|
boolean maxOutVolumeForMultipleRingReminders = preferences.getBoolean(R.string.p_rmd_maxvolume, true);
|
||||||
|
// remember it to set it to the old value after the alarm
|
||||||
|
int previousAlarmVolume = audioManager.getStreamVolume(AudioManager.STREAM_ALARM);
|
||||||
|
if (ringTimes != 1 && (type != ReminderService.TYPE_RANDOM)) {
|
||||||
|
notification.audioStreamType = AudioManager.STREAM_ALARM;
|
||||||
|
if (maxOutVolumeForMultipleRingReminders) {
|
||||||
|
audioManager.setStreamVolume(AudioManager.STREAM_ALARM,
|
||||||
|
audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// insistent rings until notification is disabled
|
||||||
|
if (ringTimes < 0) {
|
||||||
|
notification.flags |= Notification.FLAG_INSISTENT;
|
||||||
|
voiceReminder = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
notification.audioStreamType = AudioManager.STREAM_NOTIFICATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean soundIntervalOk = checkLastNotificationSound();
|
||||||
|
|
||||||
|
// quiet hours = no sound
|
||||||
|
if (quietHours || callState != TelephonyManager.CALL_STATE_IDLE) {
|
||||||
|
notification.sound = null;
|
||||||
|
voiceReminder = false;
|
||||||
|
} else {
|
||||||
|
String notificationPreference = preferences.getStringValue(R.string.p_rmd_ringtone);
|
||||||
|
if (audioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION) == 0) {
|
||||||
|
notification.sound = null;
|
||||||
|
voiceReminder = false;
|
||||||
|
} else if (notificationPreference != null) {
|
||||||
|
if (notificationPreference.length() > 0 && soundIntervalOk) {
|
||||||
|
notification.sound = Uri.parse(notificationPreference);
|
||||||
|
} else {
|
||||||
|
notification.sound = null;
|
||||||
|
}
|
||||||
|
} else if (soundIntervalOk) {
|
||||||
|
notification.defaults |= Notification.DEFAULT_SOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// quiet hours && ! due date or snooze = no vibrate
|
||||||
|
if (quietHours && !(type == ReminderService.TYPE_DUE || type == ReminderService.TYPE_SNOOZE)) {
|
||||||
|
notification.vibrate = null;
|
||||||
|
} else if (callState != TelephonyManager.CALL_STATE_IDLE) {
|
||||||
|
notification.vibrate = null;
|
||||||
|
} else {
|
||||||
|
if (preferences.getBoolean(R.string.p_rmd_vibrate, true)
|
||||||
|
&& audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_NOTIFICATION) && soundIntervalOk) {
|
||||||
|
notification.vibrate = new long[]{0, 1000, 500, 1000, 500, 1000};
|
||||||
|
} else {
|
||||||
|
notification.vibrate = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
singleThreadVoicePool.submit(new NotificationRunnable(ringTimes, notificationId, notification, voiceReminder,
|
||||||
|
maxOutVolumeForMultipleRingReminders, audioManager, previousAlarmVolume, text, notificationManager));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class NotificationRunnable implements Runnable {
|
||||||
|
private final int ringTimes;
|
||||||
|
private final int notificationId;
|
||||||
|
private final Notification notification;
|
||||||
|
private final boolean voiceReminder;
|
||||||
|
private final boolean maxOutVolumeForMultipleRingReminders;
|
||||||
|
private final AudioManager audioManager;
|
||||||
|
private final int previousAlarmVolume;
|
||||||
|
private final String text;
|
||||||
|
private NotificationManager notificationManager;
|
||||||
|
|
||||||
|
public NotificationRunnable(int ringTimes, int notificationId, Notification notification,
|
||||||
|
boolean voiceReminder, boolean maxOutVolume,
|
||||||
|
AudioManager audioManager, int previousAlarmVolume,
|
||||||
|
String text, NotificationManager notificationManager) {
|
||||||
|
this.ringTimes = ringTimes;
|
||||||
|
this.notificationId = notificationId;
|
||||||
|
this.notification = notification;
|
||||||
|
this.voiceReminder = voiceReminder;
|
||||||
|
this.maxOutVolumeForMultipleRingReminders = maxOutVolume;
|
||||||
|
this.audioManager = audioManager;
|
||||||
|
this.previousAlarmVolume = previousAlarmVolume;
|
||||||
|
this.text = text;
|
||||||
|
this.notificationManager = notificationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (int i = 0; i < Math.max(ringTimes, 1); i++) {
|
||||||
|
notificationManager.notify(notificationId, notification);
|
||||||
|
AndroidUtilities.sleepDeep(500);
|
||||||
|
}
|
||||||
|
Flags.set(Flags.REFRESH); // Forces a reload when app launches
|
||||||
|
if ((voiceReminder || maxOutVolumeForMultipleRingReminders)) {
|
||||||
|
AndroidUtilities.sleepDeep(2000);
|
||||||
|
for (int i = 0; i < 50; i++) {
|
||||||
|
AndroidUtilities.sleepDeep(500);
|
||||||
|
if (audioManager.getMode() != AudioManager.MODE_RINGTONE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// first reset the Alarm-volume to the value before it was eventually maxed out
|
||||||
|
if (maxOutVolumeForMultipleRingReminders) {
|
||||||
|
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, previousAlarmVolume, 0);
|
||||||
|
}
|
||||||
|
if (voiceReminder) {
|
||||||
|
VoiceOutputService.getVoiceOutputInstance().queueSpeak(text);
|
||||||
|
}
|
||||||
|
} catch (VerifyError e) {
|
||||||
|
// unavailable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package org.tasks.notifications;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import org.tasks.injection.ForApplication;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class NotificationManager {
|
||||||
|
|
||||||
|
private final android.app.NotificationManager notificationManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public NotificationManager(@ForApplication Context context) {
|
||||||
|
notificationManager = (android.app.NotificationManager)
|
||||||
|
context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancel(long id) {
|
||||||
|
notificationManager.cancel((int) id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notify(int notificationId, Notification notification) {
|
||||||
|
notificationManager.notify(notificationId, notification);
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.2 KiB |
Loading…
Reference in New Issue