Show notification for Android O and above without AppCompat - android

So I have ultralight app without any libs, except Crashlytics.
I want to show notifications on all versions of Android, but there is no constructor or method to set channel id for Android O+.
My code looks like this for now
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
//Some builder things
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("service_id",
context.getString(R.string.app_name),
NotificationManager.IMPORTANCE_DEFAULT);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
}
Notification notification = builder.getNotification();
NotificationManagerCompat.from(context).notify(id, notification);
Is there any compat lite lib only for notifications?

Both Notification.Builder and NotificationCompact.Builder can do this:
Notification.Builder(context, "channelId")
NotificationCompat.Builder(context, "channelId")
and they have setChannelId method.

Related

NotificationManager.IMPORTANCE_HIGH still no sound

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

Notification crashes app in notify method

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

Working with Firebase Push Notifications without Notification 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.

Android O: disable heads-up

My application could play some audio.
Once user press at the audio title the notification with the play/pause/rewind buttons appears at the notification drawer.
I noticed that in Android O (8) this notification appears with "heads-up" effect.
I don't need heads-up notification, I need just silent common notification. How can I disable "heads-up" effect?
NotificationCompat.Builder notificationBuilder;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationBuilder = new NotificationCompat.Builder(getApplicationContext(), Constants.CHANNEL_ID);
} else {
notificationBuilder = new NotificationCompat.Builder(getApplicationContext());
}
Notification notification = notificationBuilder
.setSmallIcon(R.drawable.tray_icon)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setWhen(System.currentTimeMillis())
.setContent(remoteViews)
.setChannelId(Constants.CHANNEL_ID)
.build();
notification.defaults = 0;

Status Bar Notification Not Showing?

I have a simple method which onclick() of a Button should generate status bar notification, but for some reason, it isn't showing up.
public void createNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(android.R.drawable.ic_dialog_alert)
.setContentTitle("Notification!")
.setContentText("This is my first notification!");
Notification notification = builder.build();
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(0, notification);
}
In Android 8 (API level 26), all notifications must be assigned to a channel.
This work for me:
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getContext(), CHANNEL_ID)
.setSmallIcon(R.drawable.emo_no_paint_120)
.setContentTitle("title")
.setContentText("content")
.setColor(Color.parseColor("#009add"))
.setAutoCancel(true);
NotificationManager notificationManager = (NotificationManager) getContext().getSystemService(
NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(mChannel);
}
notificationManager.notify(0, mBuilder.build());
And you should add AppCompat library
implementation 'com.android.support:support-compat:27.1.0'
You could check official Android Docs
Your code is okay. But since you are targeting Android 8.0, you need to implement Notification Channels since this the preferred way in Android Oreo.
https://developer.android.com/guide/topics/ui/notifiers/notifications.html

Categories

Resources