Adding "Remind me later" option in Android notification - android

I am working on a simple Water Reminder app. One of the final things that are left to implement is adding "Remind me later" option when the reminder notification pops. I've searched in many similar questions and articles but I didn't find solution. The thing is that I dont even know what i'm supposed to do...Start some activity, or send something to broadcast receiver or something else. I don't even know how to start trying different approaches. I will be very thankfull if someone helps me! Below is the code. What can I add to the code to implement this function?
public class ReminderManager {
public void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Uri soundUri = Uri.parse(Constants.PATH_TO_NOTIFICATION_RINGTONE);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.build();
NotificationChannel notificationChannel = new NotificationChannel
(Constants.NOTIFICATION_CHANNEL_ID, "WaterReminderChannel", NotificationManager.IMPORTANCE_HIGH);
notificationChannel.setSound(soundUri, audioAttributes);
notificationChannel.setDescription("Channel for Water Reminder");
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(notificationChannel);
}
}
public void setReminder() {
Intent intent = new Intent(context, ReminderBroadcastReceiver.class);
PendingIntent pendingIntentForBroadcast = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + MainActivity.reminderTime, pendingIntentForBroadcast);
}
public class ReminderBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent i) {
if (MainActivity.reminderTime > 0 && !MainActivity.dayFinished) {
Intent intent = new Intent(context, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
Uri soundUri = Uri.parse(Constants.PATH_TO_NOTIFICATION_RINGTONE);
Notification notification = new NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.mipmap.water)
.setContentTitle("Water Reminder")
.setContentText("It's time to drink something!")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setSound(soundUri)
.setDefaults(Notification.DEFAULT_VIBRATE)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.build();
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(1, notification);
}
}

If I understand you correctly, I believe the simplest way to handle this is to use Notification “action buttons.” See https://developer.android.com/training/notify-user/build-notification for more detail.

Thanks. Your information helped me to solve the problem. I've made it and want to share my code because it's very simple and maybe will save someone's time instead of searching alot of complicated solutions like I did.
So, below is the code that set alarm for specified by the user time, then after that time occurs the BroadcastReceiver gets triggered even when the phone is in idle state thanks to "AlarmManagerCompat.setExactAndAllowWhileIdle" (works for older and newer Android versions). Then the receiver checks by which action is triggered - SNOOZE or REMINDER. If it's SNOOZE, it calls the setReminder() method of my custom ReminderManager class to reset the alarm and then calls notificationManager.cancelAll() to remove the previous notification banner. If it's REMINDER then it calls the showNotification() method which build the notification and show it to the user (I don't find the need to build the notification before the time when the AlarmManager is set to trigger the receiver).
In my ReminderManager class I have createNotificationChannel() method which is needed for newer Android versions and I call it in onCreate of MainActivity. The setReminder() method is called from places that it needs the reminder to be set (when the user sets notification and from the BroadcastReciever as described above) and the showNotification() method is called from BroadcastReciever as described above.
public class BroadcastReceiver extends android.content.BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ReminderManager reminderManager = new ReminderManager(context);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
if (intent.getAction().equals(Constants.SNOOZE_ACTION)) {
reminderManager.setReminder();
notificationManager.cancelAll();
} else if (intent.getAction().equals(Constants.REMINDER_ACTION)) {
reminderManager.showNotification();
}
}
}
public class ReminderManager {
private final Context context;
public ReminderManager(Context context) {
this.context = context;
}
public void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.build();
NotificationChannel notificationChannel = new NotificationChannel
(Constants.NOTIFICATION_CHANNEL_ID, "WaterReminderChannel",
NotificationManager.IMPORTANCE_HIGH);
notificationChannel.setSound
(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), audioAttributes);
notificationChannel.setDescription("Channel for Water Reminder");
NotificationManager notificationManager =
context.getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(notificationChannel);
}
}
public void setReminder() {
Intent intent = new Intent(context, BroadcastReceiver.class);
intent.setAction(Constants.REMINDER_ACTION);
PendingIntent pendingIntentForBroadcast =
PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP,
System.currentTimeMillis()
+ MainActivity.reminderTime, pendingIntentForBroadcast);
}
public void showNotification() {
Intent maniActivityIntent = new Intent(context, MainActivity.class);
PendingIntent mainActivityPendingIntent =
PendingIntent.getActivity(context, 0, maniActivityIntent, 0);
Intent snoozeIntent = new Intent(context, BroadcastReceiver.class);
snoozeIntent.setAction(Constants.SNOOZE_ACTION);
PendingIntent snoozePendingIntent =
PendingIntent.getBroadcast(context, 0, snoozeIntent, 0);
Notification notification = new NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.mipmap.water)
.setContentTitle("Water Reminder")
.setContentText("It's time to drink something!")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setDefaults(Notification.DEFAULT_VIBRATE)
.setContentIntent(mainActivityPendingIntent)
.addAction(android.R.drawable.ic_lock_idle_alarm, "Remind me later", snoozePendingIntent)
.setAutoCancel(true)
.build();
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(0, notification);
}
}

Related

Android app - play (notification) sound every hour, even when the app is not in the foreground

How can my app play a short sound every hour, even when it is not running in the foreground?
Try-1: I tried a handler, but this does not help.
Try-2: as #Marcin, suggested, I tried the AlarmManager. No sound is played when the mobile is inactive. When I open the app, then it plays the sound.
Try-3: Add a notification channel with high priority on it. This plays the sound at least once, even when the mobile is standby. Swiping the notification away won't play the sound again. Setting the notification autoCancel to false won't help.
private void setAlarm() {
alarmManager = (AlarmManager) getSystemService( Context.ALARM_SERVICE);
Intent intent = new Intent( this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast( this, 0, intent, FLAG_IMMUTABLE);
alarmManager.setInexactRepeating( AlarmManager.RTC_WAKEUP,
LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(),
60000L, pendingIntent);
createNotificationChannel();
}
private void createNotificationChannel() {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "My ReminderChannel";
String description = "Channel for the Alarm manager";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel( "myandroid", name, importance);
channel.setDescription( description);
NotificationManager notificationManager = getSystemService( NotificationManager.class);
notificationManager.createNotificationChannel( channel);
}
}
The AlarmReceiver is:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent( context, MainActivity.class);
intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity( context, 0, i, PendingIntent.FLAG_IMMUTABLE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "myandroid")
.setSmallIcon(R.drawable.add_checklist_item)
.setContentTitle("Wakeup")
.setContentText("Descsription")
.setAutoCancel(true)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent( pendingIntent);
NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context);
notificationManagerCompat.notify(12345, builder.build());
playRingtone();
}
public void playRingtone() {
try {
MediaPlayer mp = MediaPlayer.create(MainActivity.mainActivity, R.raw.tock);
mp.start();
mp.setOnCompletionListener(MediaPlayer::release);
} catch (Exception e) {
e.printStackTrace();
}
}
}
In the AndroidManifest.xml is:
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<receiver android:name="com.example.myapp.AlarmReceiver"/>
</application>
Of course I don't want my silent app draining my battery.
Use workmanager.
here is the link.

On click on button of notification without opening app

I am using alarm manager to send a notification at particular time using this code:-
Intent intent = new Intent(RemindersList.this, NotifierAlarm.class);
intent.putExtra("Message",message);
PendingIntent intent1 = PendingIntent.getBroadcast(RemindersList.this, reminders.getId(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), intent1);
Toast.makeText(RemindersList.this, "Inserted Successfully", Toast.LENGTH_SHORT).show();
In manifest receiver is :-
<receiver android:name="com.example.package.NotifierAlarm" />
and the NotifierAlarm class is :-
public class NotifierAlarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Uri alarmsound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
Intent intent1 = new Intent(context, MainActivity.class);
intent1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context);
taskStackBuilder.addParentStack(MainActivity.class);
taskStackBuilder.addNextIntent(intent1);
PendingIntent intent2 = taskStackBuilder.getPendingIntent(1, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "9");
NotificationChannel channel = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
channel = new NotificationChannel("channel_01", "ch", NotificationManager.IMPORTANCE_HIGH);
}
Notification notification =
builder.setContentTitle("New Notification")
.setContentText("msg")
.setAutoCancel(true)
.setSound(alarmsound)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentIntent(intent2)
.setChannelId("my_channel_01")
.setVisibility(VISIBILITY_PRIVATE)
.build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(1, notification);
Here I want to add a button in notification with associative on click so that when user click on that button then some specific code should run without opening the app and then notification disappears
that is i want something like Done/completed button of event
I think you can remove PendingIntent in your NotificationComat, then the app will not navigation to MainActivity anymore.
And also, it is encourage for user to swipe left/right to dismiss the notification like any other Android user does.

Android notifications not showing

I'm trying to make a daily notification which will be show at a specific time.
Unfortunately it doesn't show.
I tried to follow couples tuto (also from developer.android.com) and checked similar questions that have already been asked. To save hour I'm using Hawk library.
Intent intent = new Intent(getContext(), AlarmReceiver.class);
int notificationId = 1;
intent.putExtra("notificationId", notificationId);
PendingIntent alarmIntent = PendingIntent.getBroadcast(getContext(), 0,
intent,PendingIntent.FLAG_NO_CREATE);
AlarmManager alarm = (AlarmManager) getContext().getSystemService(getContext().ALARM_SERVICE);
switch (view.getId()) {
int hour = timePicker.getCurrentHour();
int minute = timePicker.getCurrentMinute();
// Create time
....
//set alarm
alarm.setRepeating(AlarmManager.RTC_WAKEUP, alarmStartTime, AlarmManager.INTERVAL_DAY, alarmIntent);
Hawk.put("notification_hour", alarmStartTime);
break;
case R.id.cancel_button:
//cancel notification
break;
}
}
and here AlarmReceiver class
public class AlarmReceiver extends BroadcastReceiver {
public AlarmReceiver () {
}
#Override
public void onReceive(Context context, Intent intent) {
sendNotification(context, intent);
}
private void sendNotification(Context con, Intent intent) {
int notificationId = intent . getIntExtra ("notificationId", 1);
String message = " message";
Intent mainIntent = new Intent(con, MainActivity.class);
PendingIntent contentIntent = PendingIntent . getActivity (con, 0, mainIntent, 0);
NotificationManager myNotificationManager =(NotificationManager) con . getSystemService (Context.NOTIFICATION_SERVICE);
Notification.Builder builder = new Notification.Builder(con);
builder.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle("Reminder")
.setContentText(message)
.setWhen(System.currentTimeMillis())
.setAutoCancel(true)
.setContentIntent(contentIntent)
.setPriority(Notification.PRIORITY_MAX)
.setDefaults(Notification.DEFAULT_ALL);
myNotificationManager.notify(notificationId, builder.build());
}
}
In OREO, they have redesigned notifications to provide an easier and more consistent way to manage notification behavior and settings. Some of these changes include:
Notification channels: Android 8.0 introduces notification channels that allow you to create a user-customizable channel for each type of notification you want to display.
Notification dots: Android 8.0 introduces support for displaying dots, or badges, on app launcher icons. Notification dots reflect the presence of notifications that the user has not yet dismissed or acted on.
Snoozing: Users can snooze notifications, which causes them to disappear for a period of time before reappearing. Notifications reappear with the same level of importance they first appeared with.
Messaging style: In Android 8.0, notifications that use the MessagingStyle class display more content in their collapsed form. You should use theMessagingStyle class for notifications that are messaging-related.
Here, we have created the NotificationHelper class that require the Context as the constructor params. NOTIFICATION_CHANNEL_ID variable has been initialize in order to set the channel_id to NotificationChannel.
The method createNotification(…) requires title and message parameters in order to set the title and content text of the notification. In order to handle the notification click event we have created the pendingIntent object, that redirect towards SomeOtherActivity.class.
Notification channels allow you to create a user-customizable channel for each type of notification you want to display. So, if the android version is greater or equals to 8.0, we have to create the NotificationChannel object and set it to createNotificationChannel(…) setter property of NotificationManager.
public class NotificationHelper {
private Context mContext;
private NotificationManager mNotificationManager;
private NotificationCompat.Builder mBuilder;
public static final String NOTIFICATION_CHANNEL_ID = "10001";
public NotificationHelper(Context context) {
mContext = context;
}
/**
* Create and push the notification
*/
public void createNotification(String title, String message)
{
/**Creates an explicit intent for an Activity in your app**/
Intent resultIntent = new Intent(mContext , SomeOtherActivity.class);
resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent resultPendingIntent = PendingIntent.getActivity(mContext,
0 /* Request code */, resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder = new NotificationCompat.Builder(mContext);
mBuilder.setSmallIcon(R.mipmap.ic_launcher);
mBuilder.setContentTitle(title)
.setContentText(message)
.setAutoCancel(false)
.setSound(Settings.System.DEFAULT_NOTIFICATION_URI)
.setContentIntent(resultPendingIntent);
mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O)
{
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "NOTIFICATION_CHANNEL_NAME", importance);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
assert mNotificationManager != null;
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
mNotificationManager.createNotificationChannel(notificationChannel);
}
assert mNotificationManager != null;
mNotificationManager.notify(0 /* Request Code */, mBuilder.build());
}
Just include a NotificationChannel and set a channel id to it.

Android notification SetWhen not working

I'm trying to change the time stamp shown for an Android notification, but I'm always getting the current time instead. Right now I'm creating my notification like this:
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(context.getApplicationContext(), CHANNEL_ID)
...
notificationBuilder.setShowWhen(true)
notificationBuilder.setWhen(exactNotificationTime);
I thought this would be sufficient, but I'm still getting the current time displayed; my phone is a Huawei with Android 6.0 (API level 23). My project is configured with minSdkVersion = 23 and targetSdkVersion = 27.
You need to add time in millisecond in setWhen()
notificationBuilder.setWhen(System.currentTimeMillis())
instead of currentTimeMillis give the time you want.
If you want to show notification at a specific time you may need to use alarm manager as shown below.
First create alarm manager with the time you want to show notification
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 12);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
Intent notifyIntent = new Intent(getApplicationContext(),showNotification.class);
notifyIntent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
PendingIntent pendingIntent = PendingIntent.getBroadcast(etApplicationContext(),0,notifyIntent,PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),1000 * 60 * 60 * 24, pendingIntent);
Then in showNotification class
public class showNotification extends BroadcastReceiver {
public showNotification() {
}
#Override
public void onReceive(Context context, Intent intent) {
sendNotification(context);
}
private void sendNotification(Context context) {
Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Intent intent = new Intent(context, SecondActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
String NOTIFICATION_CHANNEL_ID = "101";
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
#SuppressLint("WrongConstant") NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "Notification", NotificationManager.IMPORTANCE_MAX);
//Configure Notification Channel
notificationChannel.setDescription("Game Notifications");
notificationChannel.enableLights(true);
notificationChannel.setVibrationPattern(new long[]{200});
notificationChannel.enableVibration(false);
notificationManager.createNotificationChannel(notificationChannel);
}
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle(title.get("Title of notification"))
.setContentText(subText.get("Sub text of notification"))
.setAutoCancel(true)
.setSound(defaultSound)
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis())
.setPriority(Notification.PRIORITY_MAX);
notificationManager.notify(1, notificationBuilder.build());
}
}

how to make notification in receiver

I have the following code to make a notification when the network state changes.
but when i change the network state the app stops working !
please help me with making notification.
I am sure the problem is in addMyNotification function . but dont know how to fix it.
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent broadcast) {
addMyNotification("hi","hello",1,context);
}
private void addMyNotification(String title,String message,int id ,Context context ) {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(context)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true);
Intent notificationIntent = new Intent(context, SendFood.class);
PendingIntent contentIntent = PendingIntent.getActivity(context, id, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
// Add as notification
NotificationManager manager = (NotificationManager) context.getSystemService(Service.NOTIFICATION_SERVICE);
manager.notify(id, builder.build());
}

Categories

Resources