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
Related
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
I am trying to create notifications in android but no matter what importance and priority I set, there's no sound. I am assuming sound (ringtone) is handle by android itself I don't need to provide any mp3/wav file. I am trying on android 8.1 (actual device), 8.0 (emulator) and 8.1 (emulator). Notification channel created on actual device has sound off by default, I don't know why and on emulator sound is on but still no sound played on notification
Here is my code:
public void sendMessage(View view) {
createNotificationChannel();
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("New Notification")
.setContentText("Lorem Ipsum")
.setPriority(NotificationCompat.PRIORITY_HIGH);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(1, builder.build());
}
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 = "basic-channel";
String description = "Lorem Ipsum";
int importance = NotificationManager.IMPORTANCE_HIGH;
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 behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
Channel on Actual Device
Channel on Emulator
Root Cause:
For actual device, that's OEM's problem, which in my case is Xiaomi and I found this link threema.ch/en/faq/notification_channels_xiaomi which says that xiaomi sets sound=off for all app except select few like FB, whatsApp, etc.
For emulator, we need to complete the setup process after which notification starts making sound.
When you build the notification, you need to indicate that you want to use the default system values:
builder.setDefaults(Notification.DEFAULT_ALL)
And remember to clear the app data or reinstall the app to properly recreate the notification channel. A notification channel will retain its initial configuration even if you recreate it in code.
Check this out :
//Define sound URI
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("New Notification")
.setContentText("Lorem Ipsum")
.setPriority(NotificationCompat.PRIORITY_HIGH);
.setSound(soundUri); //This sets the sound to play
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 did an update on Android Studio recently and after that, I couldn't get my notification showing.
The codes were working fine initially before the update, so I believe the issue is with the software and not the codes. Is there anything I need to change after updating?
My program will actually display a Toast message and also have a notification saying that an account has been registers(after registering an account). However, right after the toast message, another toast message displaying ,"Developer warning for package"com.example.jianminong.aucon" Failed to post notification channel "personal" See log for more details".
public void displayNotification(){
NotificationCompat.Builder builder = new
NotificationCompat.Builder(this,CHANNEL_ID);
builder.setSmallIcon(R.drawable.aucon);
builder.setContentTitle("Welcome " +
editUsername.getText().toString());
builder.setContentText("You have just created an account with
the email of " +editEmail.getText().toString());
builder.setPriority(NotificationCompat.PRIORITY_DEFAULT);
NotificationManagerCompat notificationManagerCompat =
NotificationManagerCompat.from(this);
notificationManagerCompat.notify(NOTIFICATION_ID,builder.build());
}
private void createNotificationChannel(){
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O)
{
CharSequence name = "Personal";
String description = "HAHA";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID,name,importance);
notificationChannel.setDescription(description);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(notificationChannel);
}
}
Are you calling somewhere in your code createNotificationChannel() method that should create the channel for notification? Because if not, the channel is not created, hence the toast message. You can call it before displaying the notification:
public void displayNotification(){
createNotificationChannel()
NotificationCompat.Builder builder = new NotificationCompat.Builder(this,CHANNEL_ID);
...
}
You need to make use of the new notification channels if you are running this on the newer android devices:
Starting in Android 8.0 (API level 26), all notifications must be assigned to a channel or it will not appear.
You need to follow this:
https://developer.android.com/training/notify-user/channels
I need to generate notifications when a PUSH notification is received but also I need to generate notifications (for display them in the notification bar of the device) when something happens in the application, so I'm using NotificationCompat.Builder for it.
As you know, android has deprecated this call to Notification.Builder:
Notification.Builder (Context context)
And now you must use this call:
NotificationCompat.Builder (Context context, String channelId)
What happens if you don't want to specify a notification channel and you want to send general notifications to all the users of your app and you want to receive all the notifications in all the apps installed without dealing with notification channels? Or what happens if you want to create a simple notification in the notification bar when a user has pressed a button in your app? How to display a notification without specifying the channelId? I mean... just working like until api 26 and before notification channels appeared.
Can't see how to work without specifying notification channels in any place of the official documentation.
Notification Channels are mandatory on Android 8+. So you must use NotificationCompat.Builder(Context context, String channelId) and create channel(s) on api 26+ via NotificationManager.createNotificationChannel(NotificationChannel channel).
On api < 26, just don't call createNotificationChannel but let the channel id parameter (just a String).
val builder = NotificationCompat.Builder(context, "a_channel_id")
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setSmallIcon(R.drawable.ic_notif)
.setAutoCancel(true)
...
val notificationManager = NotificationManagerCompat.from(context)
notificationManager.notify(NOTIFICATION_ID, builder.build())
on Api 26+, create a channel before:
val channel = NotificationChannel("a_channel_id", "channel_name", NotificationManager.IMPORTANCE_HIGH)
channel.description = "channel_description"
channel.enableLights(true)
channel.lightColor = Color.RED
channel.enableVibration(true)
val notificationManager = NotificationManagerCompat.from(context)
notificationManager.createNotificationChannel(channel)
There is currently no workaround for this. Notification Channels has been recently announced (last last I/O if I remember correctly), and is (most probably if not absolutely) here to stay. What I do though is something like this.
To abide to the new standard, I just implement the Notification Channels, but only as needed. I also use FCM on my app and here's something similar to what I have for it -- this is in my Application class:
private void initFirebase() {
... // other Firebase stuff.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) initNotificationChannels();
}
#TargetApi(Build.VERSION_CODES.O)
private void initNotificationChannels() {
NotificationChannel publicChannel = new NotificationChannel(NOTIFICATION_CHANNEL_PUBLIC,
NOTIFICATION_CHANNEL_PUBLIC, NotificationManager.IMPORTANCE_DEFAULT);
publicChannel.setDescription(NOTIFICATION_CHANNEL_PUBLIC);
NotificationChannel privateChannel = new NotificationChannel(NOTIFICATION_CHANNEL_PRIVATE,
NOTIFICATION_CHANNEL_PRIVATE, NotificationManager.IMPORTANCE_HIGH);
publicChannel.setDescription(NOTIFICATION_CHANNEL_PRIVATE);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (mNotificationManager != null) {
mNotificationManager.createNotificationChannel(publicChannel);
mNotificationManager.createNotificationChannel(privateChannel);
}
}
And my MessagingService has something like this:
private static final String NOTIFICATION_CHANNEL_PRIVATE = "my.app.package.name.private";
private static final String NOTIFICATION_CHANNEL_PUBLIC = "my.app.package.name.public";
private void buildNotification(....(other params),String source, String message) {
String channelId = getChannelId(source);
Intent resultIntent = new Intent(this, MyActivity.class);
resultIntent.putExtra(EXTRAS_PARAM_ID, myVal);
PendingIntent notificationIntent = buildNotificationIntent(channelId, roomId, roomType);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, getChannelId(source))
.setSmallIcon(R.drawable.ic_sample
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_SOUND)
.setContentIntent(notificationIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(id, 0, notificationBuilder.build());
}
private String getChannelId(String source) {
switch(source){
case PRIVATE:
return NOTIFIFICATION_CHANNEL_PRIVATE;
default:
return NOTIFICATION_CHANNEL_PUBLIC;
}
}
I don't know if this answers the question or not. But, having any channel below api 26 just worked without doing anything on my app.
1. instantiate notificationCompat with some channel Id
//which is irrelevant for api < 26
2. handle the case of creating notification channel for api 26+
3. bundled it up.
It just worked. Configuring Notifications did not have any effects below api 26.