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());
}
}
Related
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);
}
}
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.
I'm developing an android app in which i want to send notification daily at 14:30. I am able to get notification on time, But my problem is that, whenever i open app after 14:30, i received notification everytime. How to solve that ?
Code to send notification is here ... !
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 14);
calendar.set(Calendar.MINUTE, 30);
Intent intent = new Intent(getApplicationContext(), TimeAlarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 100,intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
and code of TimeAlarm.class is ....
NotificationManager manager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
Intent repeating_intent = new Intent(context, MainActivity.class);
repeating_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 100, repeating_intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentIntent(pendingIntent)
.setSmallIcon(android.R.drawable.ic_btn_speak_now)
.setContentTitle("Title")
.setContentText("Text")
.setAutoCancel(true);
manager.notify(100,builder.build());
Try this:
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentIntent(pendingIntent)
.setSmallIcon(android.R.drawable.ic_btn_speak_now)
.setContentTitle("Title")
.setContentText("Text")
.setOngoing(false)
.setWhen(calendar.getTimeInMillis());
.setAutoCancel(true);
manager.notify(100,builder.build());
setWhen
NotificationCompat.Builder setWhen (long when)
Set the time that the event occurred. Notifications in the panel are sorted by this time.
You can even try setShowWhen
Control whether the timestamp set with setWhen is shown in the content view.
public void al(){
Calendar myAlarmDate = Calendar.getInstance();
myAlarmDate.setTimeInMillis(System.currentTimeMillis());
myAlarmDate.set(var_Not_Year, var_Not_Month, var_Not_Day,var_Not_Hour, var_Not_Min, 0);
AlarmManager alarmMgr0 = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent0 = new Intent(this, AlarmReceiver.class);
intent0.putExtra("Heading",var_Reminder_Title);
PendingIntent pendingIntent0 = PendingIntent.getBroadcast(this, 0, intent0, 0);
alarmMgr0.set(AlarmManager.RTC_WAKEUP, myAlarmDate.getTimeInMillis(), pendingIntent0);
}
This is alarm receiver where the notification title is setup by intent when I get notification of alarm it gets old reminder title if run the application on version 4.1 but when I run this app on version 5.0 it shows old (First time input) reminder title in notification not new reminder set title.
public void onReceive(Context context, Intent intent) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new NotificationCompat.Builder(context)
.setContentTitle(intent.getStringExtra("Heading"))
.setSmallIcon(R.drawable.logo)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL)
.setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, FrontScreen.class), 0))
.build();
notificationManager.notify(0, notification);
}
I am trying to do scheduled notification. All works except: When application is active and minimized. Notification auto starts activity without waiting for user to click on it.
On reveive:
public void onReceive(Context context, Intent paramIntent) {
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancelAll();
Notification notification = new Notification(R.drawable.logo_f, context.getResources().getString(R.string.notification_text), System.currentTimeMillis());
Intent notificationIntent = new Intent(context, TimeLeftActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, 0,
notificationIntent, 0);
notification.setLatestEventInfo(context, context.getResources().getString(R.string.notification_text), "", intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.sound=alarmSound;
// Fire the notification
notificationManager.notify(1, notification);
}
My notification start method:
private void createScheduledNotification(int sec)
{
// Get new calendar object and set the date to now
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
// Add defined amount of days to the date
calendar.add(Calendar.SECOND, sec);
// Retrieve alarm manager from the system
AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(getBaseContext().ALARM_SERVICE);
// Every scheduled intent needs a different ID, else it is just executed once
int id = 1;
// Prepare the intent which should be launched at the date
Intent intent = new Intent(this, TimeAlarm.class);
// Prepare the pending intent
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.cancel(pendingIntent);
// Register the alert in the system. You have the option to define if the device has to wake up on the alert or not
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
EDIT after Kirill answer. Error still persist. Notification auto starts pending intent and does not wait for click.
#Override
public void onReceive(Context context, Intent paramIntent) {
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancelAll();
Intent notificationIntent = new Intent(context, TimeLeftActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, 0,
notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(context)
.setContentTitle(context.getResources().getString(R.string.notification_text))
.setContentIntent(intent)
.setSound(alarmSound)
.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
// Fire the notification
notificationManager.notify(1, notification);
}
It is hard to find error, because you use deprecated API in your code, you should to use Notication.Builder
Notification noti = new Notification.Builder(mContext)
.setContentTitle("New mail from " + sender.toString())
.setContentText(subject)
.setSmallIcon(R.drawable.new_mail)
.setLargeIcon(aBitmap)
.build();
If you need to support old versions you can use NotificationCompat
UPDATE
This is sample from my app, it throws a notification, which open activity by click, I marked method to add intent.
String message = context.getString(R.string.notif_message);
Intent notificationIntent = new Intent(AddBpRecordActivity.ADD_ACTION);
NotificationCompat.Builder nb = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_notif_logo)
.setContentTitle(message)
.setContentText(billet.comment)
.setDefaults(Notification.DEFAULT_ALL)
.setAutoCancel(true)
>>> .setContentIntent(PendingIntent.getActivity(context, (int) billet.id, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT))
.setWhen(System.currentTimeMillis());
Notification notification = nb.build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify((int) billet.id, notification);