I'm currently working on a library with android support.
I'm being asked to notify user on foreground service start.
The notification must contain "ApplicationName" as title, and "ApplicationName is running" as text. The notification icon has to be the same as the launcher one.
The target API level is 26.
The notification did not work because the previous developper forgot to open the notification chanel. This is now fixed, we have the notification that pops correctly. And the label are matching expectation.
But now i'm questioning why the notification contains the expected values. I could not find any reference in the javadoc.
The following code will display the notification as expectecd the application's name as title and the text "ApplicationName is running" :
#Override
public void onCreate() {
NotificationChannel channel = new NotificationChannel("APPLICATION_CHANNEL", "MyService", NotificationManager.IMPORTANCE_LOW);
channel.setDescription(notificationChannelText);
//block below useful for head up notification
channel.setSound(null, null);
channel.setShowBadge(false);
channel.enableLights(false);
channel.enableVibration(false);
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
}
#Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
foregroundNotification();
return Service.START_STICKY;
}
/**
* In order to start foreground service we and generate a service running notification.
*/
private void foregroundNotification() {
Context context = getApplicationContext();
Intent notificationIntent = new Intent(context, getClass());
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
Notification notification = new Notification.Builder(context, "APPLICATION_CHANNEL")
.setContentTitle("Title")
.setContentText("Subject")
.setContentIntent(pendingIntent)
.build();
startForeground(42666, notification);
}
Why doesn't it just display a notification with "Title" as the title and "Subject" as content ?
Are there any constants or magic values that we have to know ?
Where can we find any documentation or definition about it ?
Edit 2020/04/01 : Added code representing notification channel creation
I found your problem. This is result of your code:
and after add small icon:
.setSmallIcon(R.mipmap.ic_launcher)
It works fine
Related
I am just curious to know what are the differences between NotificationManager.notify and startForeground in Android.
Using NotificationManager.notify you can post as many updates to a notification as you like including adjustments to progress bars via Noticiation.Builder.setProgress in this way you only show one notification to the User, and its the one required by startForeground.
When you want to update a Notification set by startForeground(), simply build a new notication and then use NotificationManager to notify it.
The KEY point is to use the same notification id.
I didn't test the scenario of repeatedly calling startForeground() to update the Notification, but I think that using NotificationManager.notify would be better.
Updating the Notification will not remove the Service from the foreground status (this can be done only by calling stopForground.
Here is an example:
private static final int notif_id=1;
#Override
public void onCreate (){
this.startForeground();
}
private void startForeground() {
startForeground(notif_id, getMyActivityNotification(""));
}
private Notification getMyActivityNotification(String text){
// The PendingIntent to launch our activity if the user selects
// this notification
CharSequence title = getText(R.string.title_activity);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MyActivity.class), 0);
return new Notification.Builder(this)
.setContentTitle(title)
.setContentText(text)
.setSmallIcon(R.drawable.ic_launcher_b3)
.setContentIntent(contentIntent).getNotification();
}
/**
* this is the method that can be called to update the Notification
*/
private void updateNotification() {
String text = "Some text that will update the notification";
Notification notification = getMyActivityNotification(text);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(notif_id, notification);
}
You can find more examples and clarification on NotificationManager.notify here
I'd also suggest you to refer this page in order to understand more on startForeground
Usages of startForeground could be found here
I submitted my app at the end of 2017 in the play store and it worked.
Then it was built in Eclipse.
Now I run it in Android Studio and the same code doesn't show any notification.
It is a permanent notification which is present after I call the app's finish() method. (why I do this: see at the bottom if you want to know).
So I looked at all the examples and NONE of the work. No single notification is shown.
So I start an activity and in the activity I show the notification. Then I call finish().
This is my code:
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
intent, 0);
CharSequence connectedPart = getResources().getString(R.string.app_name);
String melding = "";
melding = getResources().getString(R.string.screentimeoutsetto) + " " + newTimeString + ".";
NotificationManager notificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification.Builder(this)
.setContentTitle(connectedPart)
.setTicker(connectedPart)
.setContentText(melding)
.setSmallIcon(R.drawable.ic_stat_name)
.setContentIntent(pendingIntent)
.setOngoing(true)
.build();
notification.flags |= Notification.FLAG_ONGOING_EVENT;
notification.flags |= Notification.FLAG_NO_CLEAR;
notificationManager.notify(2, notification);
dependencies:
dependencies{
implementation "com.android.support:support-compat:26.1.0"
}
Why I do this:
My app does 1 thing: toggle the screentimeout. So when you start it it sets the screentimeout to 30 minutes (starts, sets a notification, then finish()). Start again, it removes the notification and restore the original value for the screen timeout.
Starting with Android Oreo, all notifications require a notification channel, otherwise the notification wont post and an error will appear in your logcat. Here's an example of how you can do it, lifted from one of my apps:
private static void createNotificationChannel(Context ctx) {
if(SDK_INT < O) return;
final NotificationManager mgr = ctx.getSystemService(NotificationManager.class);
if(mgr == null) return;
final String name = ctx.getString(R.string.channel_name);
if(mgr.getNotificationChannel(name) == null) {
final NotificationChannel channel =
new NotificationChannel(CHANNEL_ID, name, IMPORTANCE_DEFAULT);
mgr.createNotificationChannel(channel);
}
}
//Usage...
createNotificationChannel(context);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID);
builder.setSmallIcon(R.drawable.ic_alarm_white_24dp);
//etc...
manager.notify(id, builder.build());
Now from Android 8.0 and onward you need to create notification channel before showing notifications. Here is the Docs link
https://developer.android.com/training/notify-user/channels
I have been trying to display a notification but it either doesn't show or causes a fatal error inside the notify method. This notification is supposed to effectively be a toast that will stay in the notification drawer until tapped.
I've tried several different intents including none. I have also, at points, copied an entire example in which still didn't work.
I have no clue what's causing the error and I've tried to attach a logcat into the app but I wasn't able to get anything out.
I'm using a Pixel 2 running stock 8.1; my programming is on the phone itself so I can't use adb / root options
public int noti(String title, String body, String ico){
//Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();
showToast(title+">"+body+">"+ico);
try{
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com/"));
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);
Notification.Builder mBuilder =
new Notification.Builder(getApplicationContext(), "83")
.setSmallIcon(Icon.createWithContentUri(ico))
.setContentTitle(title)
.setContentText(body)
.setOngoing(true)
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getApplicationContext());
Notification noti = mBuilder.build();
if(noti==null){
logBack("noti.builder == null.");
return -2;
}
int notificationId = notiIDz.getAndIncrement();
// notificationId is a unique int for each notification that you must define
notificationManager.notify(notificationId, noti);
return notificationId;
} catch(Exception e){
logBack(e.toString());
}
return -1;
}
I know that the parameters are valid from the toast, I also know that none of the logBack()s are fired.
Notification channel creation, called during onCreate:
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) {
NotificationChannel channel = new NotificationChannel("83", "vzyNotiChan", NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription("The notification channel for vzy apps.");
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
Edit, finally got to the logcat:07-24 10:48:10.879 27133 27133 E AndroidRuntime: android.app.RemoteServiceException: Bad notification posted from package vzy.html.tester: Couldn't create icon: StatusBarIcon(icon=Icon(typ=URI uri=content://com.android.externalstorage.documents/document/primary%3Ayp_sodapop.png) visible user=0 )
My guess is that you didn't create a notification channel for your notification. On All Android devices running 8.0+, each notification needs to be associated to a notification channel. You're passing in the channel ID "83" to the notification builder, but maybe you haven't actually created the channel beforehand.
For more information on how to create channels, check this out:
https://developer.android.com/training/notify-user/channels
I have followed the Xamarin walkthrough, and it's not working for me.
The code falls through this cleanly, but it never sends the notification.
It never shows up on my emulator or device.
I have no idea what is going on.
public override void OnReceive(Context context, Intent intent)
{
string message = intent.GetStringExtra("message");
string title = intent.GetStringExtra("title");
int id = int.Parse(intent.GetStringExtra("id"));
//Generate a notification with just short text and small icon
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.SetAutoCancel(true) // Dismiss from the notif. area when clicked
.SetContentTitle(title) // Set its title
.SetContentText(message); // The message to display.
NotificationManager notificationManager = (NotificationManager)context.GetSystemService(Context.NotificationService);
notificationManager.Notify(id, builder.Build());
Any help or links would be very helpful. I'm just completely lost; been working on this for about 14 hours now, and cannot find any help on the Google.
Answer to my inquiry: You must have an Icon set for notifications to be properly build and sent. Though, it won't send an error for not having one.
Short version: Needed to add
.SetSmallIcon(Resource.Drawable.icon);
Add an icon to notification.
Notification.Builder builder = new Notification.Builder (this)
.SetContentTitle ("Title")
.SetContentText ("Message")
.SetSmallIcon (Resource.Drawable.ic_notification);
Notification notification = builder.Build();
NotificationManager notificationManager =
GetSystemService (Context.NotificationService) as NotificationManager;
const int notificationId = 0;
notificationManager.Notify (notificationId, notification);
I'm using this code to create a Heads Up notification.
private static void showNotificationNew(final Context context,final String title,final String message,final Intent intent, final int notificationId, final boolean isHeaderNotification) {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context.getApplicationContext())
.setSmallIcon(R.drawable.prime_builder_icon)
.setPriority(Notification.PRIORITY_DEFAULT)
.setCategory(Notification.CATEGORY_MESSAGE)
.setContentTitle(title)
.setContentText(message)
.setWhen(0)
.setTicker(context.getString(R.string.app_name));
PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
notificationBuilder.setContentText(message);
if(isHeaderNotification) {
notificationBuilder.setFullScreenIntent(fullScreenPendingIntent, false);
}
notificationBuilder.setContentIntent(fullScreenPendingIntent);
notificationBuilder.setAutoCancel(true);
Notification notification = notificationBuilder.build();
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(notificationId, notification);
}
The thing is, notification should appear occupying a good part of top screen to call user attention, but after a couple seconds it should dismiss and a normal notification should appear.
But this code doesn't do that. The notification stay occupying all the top screen until user dismiss it.
I'm thinking in create another normal notification with same ID after a couple of seconds using Handler, but I want to know if there is a better way to do this.
Follow an example of WhatsApp, simulating the behavior I want.
The issue is caused because you use setFullScreenIntent:
An intent to launch instead of posting the notification to the status
bar. Only for use with extremely high-priority notifications demanding
the user's immediate attention, such as an incoming phone call or
alarm clock that the user has explicitly set to a particular time. If
this facility is used for something else, please give the user an
option to turn it off and use a normal notification, as this can be
extremely disruptive.
Also as explained in this answer you should use setVibrate to make Heads-up work.
This is an example of working Heads-up notification:
private static void showNotificationNew(final Context context, final String title, final String message, final Intent intent, final int notificationId) {
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context.getApplicationContext())
.setSmallIcon(R.drawable.small_icon)
.setPriority(Notification.PRIORITY_HIGH)
.setContentTitle(title)
.setContentText(message)
.setVibrate(new long[0])
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(notificationId, notificationBuilder.build());
}