My android app tracks the user's location and compares it to the locations in a list, and if it finds a match, it creates a heads-up notification that remains visible at the top of the screen (the green band in this image).
Then if the user taps the notification, it starts another activity (DisplayActivity) using a pendingIntent. This process may be repeated many times in a journey, with a new notification for each one.
Here is my code:
void makeNotification() {
if (SDK_INT >= Build.VERSION_CODES.O) {
int soundName;
String NOTIFICATION_CHANNEL_ID = "AMJnotifychannel";
Intent goShow = new Intent(this, DisplayActivity.class);
goShow.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
goShow.putExtra("placeno", placeNumber);
goShow.putExtra("plname", placeName);
goShow.putExtra("justquiz", quizOnly);
goShow.putExtra("addedscore", scoreAdded);
goShow.putExtra("killlquiz", false);
PendingIntent pendingIntent = PendingIntent.getActivity(this, notificationNumber, goShow, PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
RemoteViews expandedView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.expandednotify);
expandedView.setTextViewText(R.id.placename, placeName);
NotificationManager notificationManager = (NotificationManager) this.getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
soundName = R.raw.alert;
Uri sound = Uri.parse("android.resource://" + getPackageName() + "/" + soundName);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build();
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "amjchannel", NotificationManager.IMPORTANCE_HIGH);
channel.setSound(sound, audioAttributes);
channel.shouldVibrate();
channel.enableLights(true);
channel.enableVibration(true);
channel.setLockscreenVisibility(NotificationCompat.VISIBILITY_PUBLIC);
notificationManager.createNotificationChannel(channel);
builder.setSound(sound);
builder.setSmallIcon(R.mipmap.amjnotify);
builder.setContentIntent(pendingIntent);
builder.setCustomContentView(expandedView);
builder.setCustomBigContentView(expandedView);
builder.setAutoCancel(true);
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
builder.setFullScreenIntent(pendingIntent, true);
builder.setOngoing(true);
builder.setChannelId(NOTIFICATION_CHANNEL_ID);
notificationManager.notify(717, builder.build());
}
}
As long as the user does tap the notification each time and starts DisplayActivity, this works fine - new notifications continue to appear as a heads-up notifications at the top of the screen and the user doesn't have to open the notification drawer to see them.
However, if at any time the user dismisses a notification by swiping it upwards and off the screen, the next time a notification occurs it behaves differently. Swiping a notification away into the drawer just once means that, after that, all future notifications no longer appear at the top of the screen automatically - they go straight into the drawer and the user then has to open the drawer to see them.
I have tried this on a number of Android builds using emulators - API28, API29, API30 and API33 - always with the same result.
These notifications are essential to my app, which is useless without them. Can anyone tell me how to make sure that new notifications appear on the screen every time, as in the picture, even after the user has swiped one away into the notification drawer.
And just to make the puzzle more complicated..........
I have just tried deleting the old notification using:
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(717);
before creating a new one. As before, everything is ok if the user taps the notification and opens the new activity each time. However, if he swips the notification away one time, then whenever there is another notification after that it goes straight to the displayActivity without waiting for the user to tap the intent.
I'm totally confused!
Related
I've been building an alarm clock via youtube tutorial by Anna Xu
She ends up keeping her code within the If statement and it seems to click and bring up her application just fine. I've made modifications based on searching for fixes for Oreo on Pixel XL. This is what I have so far:
// notification parameters
int notifyID = 1;
String CHANNEL_ID = "my channel_01";
CharSequence name = "Hello";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance);
// set up the notification service
NotificationManager notify_manager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
notify_manager.createNotificationChannel(mChannel);
Notification notification_popup = new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("An alarm is going off!")
.setContentText("Click me!")
.setChannelId(CHANNEL_ID).build();
// set up notification start command
notify_manager.notify(0, notification_popup);
This brings up the notification when the alarm sounds, but clicking does not bring up the app, in fact I don't think you can click it at all, you can only swipe it away. I just want to be able to click the notification to bring the app to the foreground. I'm super new with Java and Android Studio, this was all prompted by necessity now that Oreo system alarm clock can't be trusted. Any help would be amazing.
//Create pendingIntent to open your particular activity
Intent notificationIntent = new Intent(context, YourActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, 0,
notificationIntent, 0);
//Then edit here
Notification notification_popup = new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("An alarm is going off!")
.setContentText("Click me!")
.setContentIntent(notificationIntent )
.setChannelId(CHANNEL_ID).build();
Short version:
I want to create a notification that is uninterruptible by all other notifications, SMS messages, etc until the user clears it.
Long version:
I'm using Firebase Cloud Messaging to send alerts to my phone. Messages are handled based on the topic, and I need to make the "alarm" messages repeat continuously until the notification is cleared by the user. This is currently accomplished by setting the notification with FLAG_INSISTENT, which loops the sound.
The problem is the insistent "alarm" notification is permanently stopped when a different notification or SMS comes through.
I would like to ignore all new notifications, or restart the alarm after the new notification plays. I've searched for a couple hours and tried several flags and settings, but can't figure out how to do it.
Here is the code I'm using to handle FCM messages and set the notifications:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage.getData() != null){
String messageTopic= remoteMessage.getFrom();
String messageTitle = remoteMessage.getData().get("title");
String messageBody = remoteMessage.getData().get("message");
if (messageTopic.equals("/topics/news")) {
Intent intent = new Intent(this, MainScreenActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Uri soundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_news)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(soundUri)
.setContentIntent(pendingIntent)
.setPriority(Notification.PRIORITY_MAX);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(30548, notificationBuilder.build());
}
else if (messageTopic.equals("/topics/alarm")) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.example.com/alarm.php"));
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_alarm)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(soundUri)
.setContentIntent(pendingIntent)
.setPriority(Notification.PRIORITY_MAX);
Notification mNotification = notificationBuilder.build();
mNotification.flags |= Notification.FLAG_INSISTENT;
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(30549, mNotification);
}
}
}
I may be able to prevent my own notifications from interrupting the alarm by ignoring them when the alarm notification ID (30549) is active (or create the new notification and then create the alarm again). However, SMS and notifications from other programs will still interrupt, so that wouldn't be a perfect solution.
I don't think you'll have luck with this, unfortunately. Android will not let you have a notification that takes full priority from my understanding.
However, in the Firebase console when you go to the notifications section and click advanced you can set the priority of a notification to High and set a sound.
Since it looks like you're writing the notification programmatically and setting priority to Max this will achieve the same affect.
Setting priority to high, from Google's documentation:
When a high-priority notification arrives (see right), it is presented to users for a short period of time with an expanded layout exposing possible actions.
After this period of time, the notification retreats to the notification shade. If a notification's priority is flagged as High, Max, or full-screen, it gets a heads-up notification
Also check out this SO for someone who's notification wouldn't go away when they wanted it to
here
Actually I have two questions regarding notification implementation I am trying to achieve in my application:
1. Notification opening automatically : I am trying to notify on the phone during an event in my application. The notification is functioning correctly in the way that when the event is fired, the intent which I have set in the notification gets called and the screen which I need to display is shown. However the notification comes on status bar for a second and then disappears. My application which was in background automatically comes in foreground because of the notification. I don't want the application to come on foreground automatically. I just need to display the notification.
2. Displaying notification on locked screen : With the following code, I am not able to display notification on locked screen.
This is the code I have used to display the notification :
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setSmallIcon(R.drawable.ic_launcher);
mBuilder.setContentTitle("Trip Alert");
mBuilder.setContentText(StringUtils.join("You have reached ",destination.getAddress()));
mBuilder.setNumber(++numMessages);
mBuilder.setOnlyAlertOnce(true);
mBuilder.getNotification().flags |= Notification.FLAG_ONLY_ALERT_ONCE | Notification.FLAG_AUTO_CANCEL | Notification.FLAG_ONGOING_EVENT;
Intent detailIntent = new Intent();
detailIntent.setClass(DestinationListActivity.this,
DestinationDetailActivity.class);
detailIntent.putExtra("Destination", destination);
startActivityForResult(detailIntent, 1);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(DestinationDetailActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(detailIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// notificationID allows you to update the notification later on.
mNotificationManager.notify(notificationID, mBuilder.build());
The reason notification is getting displayed for a very little time is because I have written following code in the DestinationDetailsActivity onCreate :
if (getIntent().getExtras() != null) {
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancel(100);
..
}
But if this code won't come here, how shall I dismiss the notification?
Please do let me know if I need to explain more.
I am trying to Notify user based on some criteria. Multiple Notifications are being shown in Status Bar but I want to Group the notification in single notification and when user clicks in the Status Bar, I want to retrieve all notifications in that group. Is that possible? Or I have to maintain PendingIntents of those notifications? Any help will be appreciated. For example, if birthdays of two friends come on same day, then 2 notifications should be shown. I want to combine these notifications i.e. instead of 2 notifications in the status bar, I want one, when user clicks on it, it should have information about 2 notifications. Is it possible?
Please see the code below for displaying notifications.
public void displayNotification(BirthdayDetail detail)
{
NotificationCompat.Builder builder = new NotificationCompat.Builder(this.context);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentTitle(detail.getContactName());
builder.setContentText(detail.getContactBirthDate());
Intent resultIntent = new Intent(this.context, NotificationView.class);
resultIntent.putExtra("name", detail.getContactName());
resultIntent.putExtra("birthdate", detail.getContactBDate());
resultIntent.putExtra("picture_path", detail.getPicturePath());
resultIntent.putExtra("isContact", detail.isFromContact());
resultIntent.putExtra("notificationId", notificationId);
if(detail.isFromContact())
{
resultIntent.putExtra("phone_number", detail.getPhoneNumber());
}
PendingIntent resultPendingIntent = PendingIntent.getActivity(this.context, requestCode++,
resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(resultPendingIntent);
notificationManager
= (NotificationManager) this.context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationId, builder.build());
notificationId++;
}
When you need to issue a notification multiple times for the same type
of event, you should avoid making a completely new notification.
Instead, you should consider updating a previous notification, either
by changing some of its values or by adding to it, or both.
You can use something like:
mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Sets an ID for the notification, so it can be updated
int notifyID = 1;
mNotifyBuilder = new NotificationCompat.Builder(this)
.setContentTitle("New Message")
.setContentText("You've received new messages.")
.setSmallIcon(R.drawable.ic_notify_status)
numMessages = 0;
// Start of a loop that processes data and then notifies the user
...
mNotifyBuilder.setContentText(currentText)
.setNumber(++numMessages);
// Because the ID remains unchanged, the existing notification is
// updated.
mNotificationManager.notify(
notifyID,
mNotifyBuilder.build());
Source: http://developer.android.com/training/notify-user/managing.html
I want notification which will stick on notification bar until music stop playing it.
currently i have written some code in which i can show notification but when i press clear notification button or swap it than it disappear from notification center.
I want notification like spotify which stays on bar until you stop playing music.
Here is my code for notification
int pendingRequestCode = 0;
// final Resources res = getResources();
notificationManager = (NotificationManager) getSystemService(
NOTIFICATION_SERVICE);
Intent i = new Intent(getApplicationContext(),Mainactivity.class);
Notification.Builder builder = new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_action_search)
.setAutoCancel(true)
.setTicker("test ckick")
.setContentIntent(PendingIntent.getActivity(getApplicationContext(), NOTIFICATION_DEFAULT, i,0));
// Sets a custom content view for the notification, including an image button.
layout = new RemoteViews(getPackageName(), R.layout.notification);
layout.setTextViewText(R.id.notification_title, getString(R.string.app_name));
Intent clickIntent = new Intent();
clickIntent.setAction(ACTION_DIALOG);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), pendingRequestCode, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
layout.setOnClickPendingIntent(R.id.notification_button,pendingIntent);
builder.setContent(layout);
// Notifications in Android 3.0 now have a standard mechanism for displaying large
// bitmaps such as contact avatars. Here, we load an example image and resize it to the
// appropriate size for large bitmaps in notifications.
layout.setImageViewResource(R.id.notification_button, R.drawable.pause);
notificationManager.notify(NOTIFICATION_DEFAULT, builder.getNotification());
waiting for reply
Use setOngoing(true) to indicate that the event is ongoing. You may also wish to remove setAutoCancel(true), as that clears the Notification when the user taps upon it.
notification.flags = Notification.DEFAULT_LIGHTS | Notification.FLAG_AUTO_CANCEL