I don't have any device older than 4.1 to test on. I'm trying to test out pushing my notifications with the code below. It's mostly all taken from the Notification documentation. Would my code crash or does the NotificationCompat class handle all of this for me gracefully?
Under the "Handling Compatability" section it reads:
Handling compatibility
Not all notification features are available for a particular version,
even though the methods to set them are in the support library class
NotificationCompat.Builder. For example, action buttons, which depend
on expanded notifications, only appear on Android 4.1 and higher,
because expanded notifications themselves are only available on
Android 4.1 and higher.
To ensure the best compatibility, create notifications with
NotificationCompat and its subclasses, particularly
NotificationCompat.Builder. In addition, follow this process when you
implement a notification:
...
So does this mean that if I use the NotificationCompat class it will handle all of the compatibility for me?
My code that I'm worried about (because it uses BigTextStyle):
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mContext).setSmallIcon(R.drawable.ic_launcher).setContentTitle("Title")
.setContentText(String.format("%s", message));
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(mContext, ActivityMain.class);
// The stack builder object will contain an artificial back stack for
// the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(mContext);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
// Add max priority
mBuilder.setPriority(NotificationCompat.PRIORITY_MAX);
// Add bigTextStyle
NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle();
bigTextStyle.bigText(String.format("%s", message));
mBuilder.setStyle(bigTextStyle);
mBuilder.setAutoCancel(true);
// mId allows you to update the notification later on.
mNotificationManager.notify(1, mBuilder.build());
You have nothing to worry about.
Helper class for generating large-format notifications that include a lot of text.
If the platform does not provide large-format notifications, this method has no effect. The user will always see the normal notification view.
(NotificationCompat.BigTextStyle)
Related
I am using Firebase (FCM) to show Push Notifications to the user and I am running into a weird problem.
The code I have works for the following scenarios (using FirebaseMessagingService):
App in foreground - Receiving data in onReceive() and showing a popup inside app.
App in background - Receiving data in onReceive() and showing a notification for the user. If this is clicked the app will be brought back to front. The intent from this is received in LauncherActivity followed by a finish() call which takes me to whatever activity I already had open.
App completely closed - same as background. App will be started and intent will be handled in LauncherActivity before calling finish() on that.
And here is where it gets interesting:
App completely closed -> open it through notification (intent received in LauncherActivity) -> put the app in background and send another notification -> when this notification is clicked the LauncherActivity is completely ignored (onCreate is no longer called) and I get taken straight to whatever activity I already had. The intent here has no extras or categories.
Why is LauncherActivity being bypassed in this specific case? Keep in mind that this works fine if the app was initially started normally (not by clicking on a notification)
Intent mainIntent = getPackageManager().getLaunchIntentForPackage(getPackageName());
if (mainIntent != null) {
mainIntent.addCategory(NOTIFICATION_CATEGORY);
mainIntent.putExtra(.........);
}
PendingIntent pendingMainIntent = PendingIntent.getActivity(this, SERVICE_NOTIFICATION_ID, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, context.getString(R.string.default_notification_channel_id));
notificationBuilder.setContentIntent(pendingMainIntent);
//.....icon, color, pririty, autoCancel, setDefaults, setWhen, setShowWhen, contentText, setStyle
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
getString(R.string.default_notification_channel_id),
getString(R.string.default_notification_channel),
NotificationManager.IMPORTANCE_HIGH
);
notificationManager.createNotificationChannel(channel);
notificationBuilder.setChannelId(getString(R.string.default_notification_channel_id));
}
notificationManager.notify(SERVICE_NOTIFICATION_ID, notificationBuilder.build());
}
I'd appreciate any ideas. Thank you.
When you launch an app for the first time, Android remembers the Intent that was used to launch it. Normally, when you launch an app from the HOME screen, this is an Intent that contains ACTION=MAIN and CATEGORY=LAUNCHER. If your app then goes to the background (for whatever reason), and the user later taps the icon on the HOME screen, the same launch Intent is used. Android matches this against the Intent used to launch the app for the first time, and if these match, Android doesn't launch a new Activity, it just brings the task containing the app from the background to the foreground in whatever state it was in when it got moved to the background. Under normal circumstances, this is exactly the behaviour that you want (and that the user expects).
However, when the app is launched for the first time from a Notification, this can mess things up. In your case, this is what you are seeing. You launch the app from a Notification and Android remembers the Intent used (from the Notification), when you later launch the app (again from a Notification), android matches the Intent in the Notification with the Intent used to launch the app for the first time, and thinks you want to bring the existing app task from the background to the foreground.
There are several ways to deal with this, depending on the behaviour that you want to have. The best thing to do is probably not to launch your root Activity (the one with ACTION=MAIN and CATEGORY=LAUNCHER) from the Notification. Instead launch a different Activity and have that Activity determine what it should do next (ie: redirect to the root Activity or something else, depending on the state of your app). You should also set the NO_HISTORY and EXCLUDE_FROM_RECENTS flags on the Intent that you put in the Notification. This will ensure that Android won't remember this Intent as the one that launched the app.
I'm wondering how to create a notification in android with action icons that allowed me to call a method in the main activity.
just like the one in this image : Notification icon exemple
First Welcome to stackoverflow. I'd like to remind you this is not a website to learn how to program but a website to ask questions with actual problems that can help the community. Your questions have to be detailed and specific with your code or attempt as well as the error log.
That being said, here is the best way to create a notification:
Step 1 - Create Notification Builder
First step is to create a notification builder using NotificationCompat.Builder.build(). You can use Notification Builder to set various Notification properties (small icons, large icons, title, priority etc)
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
Step 2 - Setting Notification Properties
Once you have Builder object, you can set its Notification properties using Builder object as per your requirement. But this is mandatory to set at least following −
A small icon, set by setSmallIcon()
A title, set by setContentTitle()
Detail text, set by setContentText()
mBuilder.setSmallIcon(R.drawable.notification_icon);
mBuilder.setContentTitle("I'm a notification alert, Click Me!");
mBuilder.setContentText("Hi, This is Android Notification Detail!");
Step 3 - Attach Actions
This is optional and only required if you want to attach an action with the notification. An action will allows users to go directly from the notification to an Activity in your application (where they can look at one or more events or do further work).
The action is defined by a PendingIntent containing an Intent that starts an Activity in your application. To associate the PendingIntent with a gesture, call the appropriate method of NotificationCompat.Builder.
For example, if you want to start Activity when the user clicks the notification text in the notification drawer, you add the PendingIntent by calling setContentIntent().
A PendingIntent object helps you to perform an action on your application's behalf, often at a later time, regardless whether or not your application is running.
Also there's the stackBuilder object which will contain an artificial back stack for the started Activity. This ensures that navigating backward from the Activity leads out of your application to the Home screen.
Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
Step 4 - Issue the notification
Finally, you pass the Notification object to the system by calling NotificationManager.notify() to send your notification. Make sure you call NotificationCompat.Builder.build() method on builder object before notifying it. This method combines all of the options that have been set and return a new Notification object.
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// notificationID allows you to update the notification later on.
mNotificationManager.notify(notificationID, mBuilder.build());
I hope this answers your question.
I need a program that will add a notification on Android. And when someone clicks on the notification, it should lead them to my second activity.
I have established code. The notification should be working, but for some reason it is not working. The Notification isn't showing at all. I don't know what am I missing.
Code of those files:
Notification n = new Notification.Builder(this)
.setContentTitle("New mail from " + "test#gmail.com")
.setContentText("Subject")
.setContentIntent(pIntent).setAutoCancel(true)
.setStyle(new Notification.BigTextStyle().bigText(longText))
.build();
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Hide the notification after it's selected
notificationManager.notify(0, n);
The code won't work without an icon. So, add the setSmallIcon call to the builder chain like this for it to work:
.setSmallIcon(R.drawable.icon)
Android Oreo (8.0) and above
Android 8 introduced a new requirement of setting the channelId property by using a NotificationChannel.
NotificationManager mNotificationManager;
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(mContext.getApplicationContext(), "notify_001");
Intent ii = new Intent(mContext.getApplicationContext(), RootActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, ii, 0);
NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle();
bigText.bigText(verseurl);
bigText.setBigContentTitle("Today's Bible Verse");
bigText.setSummaryText("Text in detail");
mBuilder.setContentIntent(pendingIntent);
mBuilder.setSmallIcon(R.mipmap.ic_launcher_round);
mBuilder.setContentTitle("Your Title");
mBuilder.setContentText("Your text");
mBuilder.setPriority(Notification.PRIORITY_MAX);
mBuilder.setStyle(bigText);
mNotificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
// === Removed some obsoletes
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
String channelId = "Your_channel_id";
NotificationChannel channel = new NotificationChannel(
channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_HIGH);
mNotificationManager.createNotificationChannel(channel);
mBuilder.setChannelId(channelId);
}
mNotificationManager.notify(0, mBuilder.build());
Actually the answer by ƒernando Valle doesn't seem to be correct. Then again, your question is overly vague because you fail to mention what is wrong or isn't working.
Looking at your code I am assuming the Notification simply isn't showing.
Your notification is not showing, because you didn't provide an icon. Even though the SDK documentation doesn't mention it being required, it is in fact very much so and your Notification will not show without one.
addAction is only available since 4.1. Prior to that you would use the PendingIntent to launch an Activity. You seem to specify a PendingIntent, so your problem lies elsewhere. Logically, one must conclude it's the missing icon.
You were missing the small icon.
I did the same mistake and the above step resolved it.
As per the official documentation:
A Notification object must contain the following:
A small icon, set by setSmallIcon()
A title, set by setContentTitle()
Detail text, set by setContentText()
On Android 8.0 (API level 26) and higher, a valid notification channel ID, set by setChannelId() or provided in the NotificationCompat.Builder constructor when creating a channel.
See http://developer.android.com/guide/topics/ui/notifiers/notifications.html
This tripped me up today, but I realized it was because on Android 9.0 (Pie), Do Not Disturb by default also hides all notifications, rather than just silencing them like in Android 8.1 (Oreo) and before. This doesn't apply to notifications.
I like having DND on for my development device, so going into the DND settings and changing the setting to simply silence the notifications (but not hide them) fixed it for me.
Creation of notification channels are compulsory for Android versions after Android 8.1 (Oreo) for making notifications visible. If notifications are not visible in your app for Oreo+ Androids, you need to call the following function when your app starts -
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name,
importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviours after this
NotificationManager notificationManager =
getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
You also need to change the build.gradle file, and add the used Android SDK version into it:
implementation 'com.android.support:appcompat-v7:28.0.0'
This worked like a charm in my case.
I think that you forget the
addAction(int icon, CharSequence title, PendingIntent intent)
Look here: Add Action
I had the same issue with my Android app. I was trying out notifications and found that notifications were showing on my Android emulator which ran a Android 7.0 (Nougat) system, whereas it wasn't running on my phone which had Android 8.1 (Oreo).
After reading the documentation, I found that Android had a feature called notification channel, without which notifications won't show up on Oreo devices. Below is the link to official Android documentation on notification channels.
Notifications Overview, Notification anatomy
Create and Manage Notification Channels
For me it was an issue with deviceToken. Please check if the receiver and sender device token is properly updated in your database or wherever you are accessing it to send notifications.
For instance, use the following to update the device token on app launch. Therefore it will be always updated properly.
// Device token for push notifications
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(
new OnSuccessListener<InstanceIdResult>() {
#Override
public void onSuccess(InstanceIdResult instanceIdResult) {
deviceToken = instanceIdResult.getToken();
// Insert device token into Firebase database
fbDbRefRoot.child("user_detail_profile").child(currentUserId).child("device_token")).setValue(deviceToken)
.addOnSuccessListener(
new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
}
});
}
});
I encountered a similar problem to yours and while searching for a solution I found these answers but they weren't as direct as I hoped they would be but it gives an Idea; Your notifications may not be showing because for versions >=8 notifications are done relatively differently there is a NotificationChannel which aids in managing notifications this helped me. Happy coding.
void Note(){
//Creating a notification channel
NotificationChannel channel=new NotificationChannel("channel1",
"hello",
NotificationManager.IMPORTANCE_HIGH);
NotificationManager manager=(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.createNotificationChannel(channel);
//Creating the notification object
NotificationCompat.Builder notification=new NotificationCompat.Builder(this,"channel1");
//notification.setAutoCancel(true);
notification.setContentTitle("Hi this is a notification");
notification.setContentText("Hello you");
notification.setSmallIcon(R.drawable.ic_launcher_foreground);
//make the notification manager to issue a notification on the notification's channel
manager.notify(121,notification.build());
}
Make sure your notificationId is unique. I couldn't figure out why my test pushes weren't showing up, but it's because the notification ids were generated based on the push content, and since I was pushing the same notification over and over again, the notification id remained the same.
Notifications may not be shown if you show the notifications rapidly one after the other or cancel an existing one, then right away show it again (e.g. to trigger a heads-up-notification to notify the user about a change in an ongoing notification). In these cases the system may decide to just block the notification when it feels they might become too overwhelming/spammy for the user.
Please note, that at least on stock Android (tested with 10) from the outside this behavior looks a bit random: it just sometimes happens and sometimes it doesn't. My guess is, there is a very short time threshold during which you are not allowed to send too many notifications. Calling NotificationManager.cancel() and then NotificationManager.notify() might then sometimes cause this behavior.
If you have the option, when updating a notification don't cancel it before, but just call NotificationManager.notify() with the updated notification. This doesn't seem to trigger the aforementioned blocking by the system.
If you are on version >= Android 8.1 (Oreo) while using a Notification channel, set its importance to high:
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
val pendingIntent = PendingIntent.getActivity(applicationContext, 0, Intent(), 0)
var notification = NotificationCompat.Builder(applicationContext, CHANNEL_ID)
.setContentTitle("Title")
.setContentText("Text")
.setSmallIcon(R.drawable.icon)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.build()
val mNotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
mNotificationManager.notify(sameId, notification)
I am trying to create a notification after every 2 mins but , only single notification is getting created(when app is started).
My code is :
notifyme.java :
public class notifyme extends Service {
#Override
public void onCreate() {
super.onCreate();
Intent intent=new Intent(this,MainActivity.class);
TaskStackBuilder stackBuilder=TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent=stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notify=new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Hello")
.setContentText("Some random text")
.setDefaults(Notification.DEFAULT_ALL)
.setWhen(System.currentTimeMillis())
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManager nMgr=(NotificationManager)this.getSystemService(this.NOTIFICATION_SERVICE);
Random r=new Random();
int nid=r.nextInt(50000)+1;
nMgr.notify(nid,notify.build());
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
In MainActivity.java :
Intent notificationIntent = new Intent(this, notifyme.class);
PendingIntent contentIntent = PendingIntent.getService(getApplicationContext(), 0, notificationIntent,0);
AlarmManager am = (AlarmManager) getSystemService(this.ALARM_SERVICE);
am.cancel(contentIntent);
am.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),120*1000, contentIntent);
first you don't need a whole service to show a notification, if that's all it's doing, you could use a BroadcastReceiver and use PendingIntent.getBroadcast method. BroadcastReceiver needs less memory and doesn't have any life-cycle (which could complicate things).
The reason you're not seeing more than one notification is on the line nMgr.notify(119,notify.build());
This number 119 is the notification ID. So after X seconds that it's executing that code again, your new notification is directly replacing the old one and it all looks as if it hasn't changed.
If you want to put several notifications up (AKA. SPAM the user), you should always change that number. maybe using a Random
First of all, making new notifications in every two seconds is completely against guidelines.
As docs says :
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.
here the issue is that you are using the same ID to create the notification. (here 19).
When you publish a notification, if there is an active notification with the same id. notificatipon manager will update the existing one. So everytime the service is running, it just updates the notification with id "19".
If you are keen on issuing notifications on every 2 minutes (Which will affect the user-experience of your app very badly, let me warn you), try giving different ids to the notifications. You can save the issued ids in SharedPreferences or something.
I am developing a music player however when I click the notification which is created, a new version of this activity is displayed and not the one displaying the currently playing song and seekbar.
The current code I'm using for the notification is
Intent i = new Intent(this, AmplitudeMusicPlayer.class);
i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pIntent = PendingIntent.getActivity(this, 0 , i, 0);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder noti = new NotificationCompat.Builder(this);
noti.setContentTitle("Now Playing")
.setContentText(songTitle)
.setSmallIcon(R.drawable.default_art)
.setContentIntent(pIntent);
notificationManager.notify(0, noti.build());
Which launch mode are you declaring for your activity?
http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
The "standard" and "singleTop" modes differ from each other in just
one respect: Every time there's a new intent for a "standard"
activity, a new instance of the class is created to respond to that
intent. Each instance handles a single intent. Similarly, a new
instance of a "singleTop" activity may also be created to handle a new
intent. However, if the target task already has an existing instance
of the activity at the top of its stack, that instance will receive
the new intent (in an onNewIntent() call); a new instance is not
created. In other circumstances — for example, if an existing instance
of the "singleTop" activity is in the target task, but not at the top
of the stack, or if it's at the top of a stack, but not in the target
task — a new instance would be created and pushed on the stack.