In my app I use Foreground Service to show a notification when the app goes in background. I created a Notification Channel in the following way:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.app_name);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(TransactionsUtil.getNotificationChannelId(this), name, importance);
channel.setDescription("some description");
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
Notification notification = new NotificationCompat.Builder(this, TransactionsUtil.getNotificationChannelId(this))
.setSmallIcon("some icon")
.setContentTitle("some content")
.setContentText("some content")
.setContentIntent(pendingIntent)
.setChannelId(TransactionsUtil.getNotificationChannelId(this))
.build();
startForeground(NOTIFICATION_ID, notification);
The I delete the notification channel in this way:
private void terminateService() {
stopForeground(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.deleteNotificationChannel(getNotificationChannelId(this));
}
stopSelf();
}
Recently, I'm having some crashes in my app releated to this; in particular, I have the following error:
Fatal Exception: java.lang.SecurityException
Not allowed to delete channel "channel name" with a foreground service
The problem is releated to the function terminateService, in particular in deleteNotificationChannel.
Caused by android.os.RemoteException
Remote stack trace: at com.android.server.notification.NotificationManagerService$11.enforceDeletingChannelHasNoFgService(NotificationManagerService.java:3859) at com.android.server.notification.NotificationManagerService$11.deleteNotificationChannel(NotificationManagerService.java:3872) at android.app.INotificationManager$Stub.onTransact(INotificationManager.java:1813) at android.os.Binder.execTransactInternal(Binder.java:1170) at android.os.Binder.execTransact(Binder.java:1134)
It happens only in Android 11 devices. Does someone has a solution or suggestion, please?
You don't need to delete the channel, you can share the channel with your normal notification channel.
You get crash because stopForeground is binder call through ActivityManagerService, it cross process, same as the deleteNotificationChannel through NotificationManagerService, if the NotificationManagerService goes fast, the method enforceDeletingChannelHasNoFgService will return true, which is added from android-11.0.0_r38, and you will get a crash.
Related
How can I switch all these settings on programmatically?
I noticed when you install WhatsApp they are all switched on in the beginning(look at the image below).
But I can not find a way to turn them on programmatically.
Here is how I send notifications:
private void sendNotification(Intent intent){
Context context = NotificationService.this;
//open the activity after the notification is clicked
Intent intent1 = new Intent(getApplicationContext(),MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(context, 0, intent1, 0);
Notification.Builder builder = new Notification.Builder(context)
.setTicker("Notification")
.setContentTitle("Important Message")
.setContentText("This is an example of a push notification using a Navigation Manager")
.setSmallIcon(R.drawable.ic_add)
.setContentIntent(pIntent);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
//These are necessary for the notification to pop up
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O){
builder.setPriority(Notification.PRIORITY_MAX);
builder.setSound(alarmSound);
builder.setLights(Color.BLUE, 500, 500);
}
//after android O we must use notification channels
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
String channelId = "Your_channel_id";
NotificationChannel channel = new NotificationChannel(
channelId,
"Reminder to remind to review your notes",
NotificationManager.IMPORTANCE_HIGH);
if(alarmSound != null){
AudioAttributes att = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
channel.setSound(alarmSound,att);
}
channel.setLightColor(Color.BLUE);
channel.enableVibration(true);
channel.setDescription("Hello Dear friends"); //this is to test what this is
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
channel.setVibrationPattern(new long[]{300, 300, 300});
notificationManager.createNotificationChannel(channel);
builder.setChannelId(channelId);
}
Notification notification = builder.build();
notificationManager.notify(0, notification);
}
I also added this permission to manifest:
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
Update:
Using this code on the emulator, I get the heads-up notification. But on my Xiaomi device, there is no heads-up notification. It just appears on the status bar. If I manually turn on the floating notification (which you can see in the photo) then I will get heads-up notification. But they are switched off by default. When you install Whatsapp they are all switched on.
Is that a kind of privilege for Whatsapp as it is famout? or is there a way to do it?
By default, when you install a app, the system register's default notification channel (on low priority) that doesn't support head up notification by default, it's turned off. You can't control that.
But what you can do it create your own notification channel with highest priority and then register it on app run once.
After that just pass the channel Id with your notification builder so that system shows the head's up notification which you want.
More information can be found here https://developer.android.com/training/notify-user/channels
I have tried for this but unable to set these settings programmatically. Instead of this I have used following method to open notification settings screen to enable notification sounds/vibration.
private void openNotificationSettingsForApp(String channelId) {
// Links to this app's notification settings.
Intent intent = new Intent();
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && channelId!=null){
intent.setAction(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_CHANNEL_ID,channelId);
intent.putExtra("android.provider.extra.APP_PACKAGE", getPackageName());
}
intent.putExtra("app_package", getPackageName());
intent.putExtra("app_uid", getApplicationInfo().uid);
startActivity(intent);
}
I searched many other questions related to this topic but found not satisfactory answer also none of them are working for me.
I want to show a continuous notification which should only be terminated by app. But the code i wrote was working a few days ago but not now.
private void GenNotification(String title, String body)
{
try
{
Log.i(Config.TAGWorker, "Generating Notification . . .");
Intent myIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(
this,
0,
myIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(title)
.setContentText(body)
.setChannelId("myID")
.setTicker("Notification!")
.setWhen(System.currentTimeMillis())
.setContentIntent(pendingIntent)
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(false)
.setSmallIcon(R.drawable.floppy)
.setOngoing(true)
.build();
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Service.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, notification);
}
catch (Exception e)
{
Log.e(Config.TAGWorker, e.getMessage());
}
}
There is no exception recorded in Logcat, regarding ths. The code is called in onCreate of service. The service is starting correctly i can see in Log cat also there is no exception but notification is not shown. My OS is Android ONE for nokia (PI)
You are using a deprecated NotificationCompat.Builder constructor which takes a single argument (context); and that won't work on starting from Android 8.0 (API level 26).
So, to solve this:
Step 1: Create a Notification channel with the NotificationManager
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Notification channels are only available in OREO and higher.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel
("PRIMARY_CHANNEL_ID",
"Service",
NotificationManager.IMPORTANCE_HIGH);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationChannel.setDescription("Description");
mNotificationManager.createNotificationChannel(notificationChannel);
}
Note: changeargument values as you wish
Step 2:: Use the non-deprecated Notification.Builder class with its two-argument constructor that takes a second argument as the channel ID which you assigned in the first step, where I set it to "PRIMARY_CHANNEL_ID"
Notification notification = new NotificationCompat.Builder
(this, "PRIMARY_CHANNEL_ID")
.setContentTitle("title")
.setContentText("body")
.setTicker("Notification!")
.setWhen(System.currentTimeMillis())
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.ic_launcher_background)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setOngoing(true)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setAutoCancel(true)
.build();
mNotificationManager.notify(0, notification);
Did you check your strings (title and body) is not null if it's null notification wont show
Also check that you call your notification channels when you start your service every time if your android above 7.0
Clear notification when you recall it same id in your case is 1.
So basically I have tried to implement Push Notifications using Firebase cloud message module. Initially I wasnot able to recieve notifications but after reasearch about the difference in code for Oreo versions of androi Notifications are working fine when the app is in the foreground but gives the following error when the app is closed or is in the background:
So when I monitored the log cat carefully this what it is showing:
Error while parsing timestamp in GCM event
java.lang.NumberFormatException: Invalid int: "null"
at java.lang.Integer.invalidInt(Integer.java:138)
...
My FirebaseMessageService class code is like this:
public class FirebaseMessagingService extends com.google.firebase.messaging.FirebaseMessagingService {
private String CHANNEL_ID = "personal_notifications";
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID,"personal_notifications",NotificationManager.IMPORTANCE_DEFAULT);
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
String notification_title = remoteMessage.getNotification().getTitle();
String notification_message = remoteMessage.getNotification().getBody();
String click_action = remoteMessage.getNotification().getClickAction();
String from_user_id = remoteMessage.getData().get("from_user_id");
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.chitchat_icon)
.setContentTitle(notification_title)
.setAutoCancel(true)
.setContentText(notification_message);
Intent resultIntent = new Intent(click_action);
resultIntent.putExtra("user_id", from_user_id);
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
this,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
int mNotificationId = (int) System.currentTimeMillis();
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mNotificationManager.createNotificationChannel(mChannel);
}
mNotificationManager.notify(mNotificationId,mBuilder.build());
}
}
I don't know why my channel is null only when I try to send the notification in the background.
Edit:
When I am building the project on Linux Push Notifications appear in foreground and give above error in background but when I build it from windows I do not recieve any notification neither in background or foreground.
To fix the failed to post notification on channel null problem, you have to update your firebase-messaging version to latest or at least 15.0.2. Hope this will resolve the problem.
In addition to this you may add the below meta data in your AndroidManifest to double sure that it will work. Thanks
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="#string/default_notification_channel_id"/>
I've implemented a startForeground() method to start the ongoing notification which is called in onCreate(). There are two usages in two different classes. I'm testing on API 27 (Android 8.1)
First Usage (PictureCapturingService.java):
onCreate():
#Override
public void onCreate() {
super.onCreate();
Context mContext = this.getApplicationContext();
context = this.getApplicationContext();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startMyOwnForeground();
} else {
startForeground(1234, new Builder(getApplicationContext()).setContentTitle("Capturing Image").setContentText("").setSmallIcon(R.drawable.icon_notif).build());
}
startMyOwnForeground():
#RequiresApi(api = Build.VERSION_CODES.O)
private void startMyOwnForeground() {
String channelID = "com.example.code";
NotificationChannel notificationChannel = new NotificationChannel(channelID, "Background Service", NotificationManager.IMPORTANCE_NONE);
notificationChannel.enableLights(false);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(notificationChannel);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelID);
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.drawable.icon_notif)
.setContentTitle("Capturing Image")
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(1234, notification);
}
Second Usage (VideoRecordService.java):
Gets called from onCreate() and startRecord()
onCreate():
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startMyOwnForeground("Sending Message");
}
else {
startForeground(1234, new Builder(this).setContentTitle("Sending Message").setContentText("").setSmallIcon(R.drawable.icon_notif).build());
}
startRecord():
private void startRecord() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startMyOwnForeground("Video Recording");
} else {
startForeground(1234, new Builder(getApplicationContext()).setContentTitle("Video Recording").setContentText("").setSmallIcon(R.drawable.icon_notif).build());
}
startMyOwnForeground:
#RequiresApi(api = Build.VERSION_CODES.O)
private void startMyOwnForeground(String str) {
String channelID = "com.example.code";
NotificationChannel notificationChannel = new NotificationChannel(channelID, "Background Service", NotificationManager.IMPORTANCE_NONE);
notificationChannel.enableLights(false);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(notificationChannel);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelID);
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.drawable.icon_notif)
.setContentTitle(str)
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(1234, notification);
}
I receive the following error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.raudram.barathikannamma, PID: 18871
android.app.RemoteServiceException: Bad notification for startForeground: java.lang.RuntimeException: invalid channel for service notification: Notification(channel=null pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x40 color=0x00000000 vis=PRIVATE)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1797)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:6651)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824)
Your icon is set to R.mipmap.ic_launcher. By name, that suggests that you are trying to use your app launcher icon as your notification icon. That is not a valid notification icon, though.
Use the Image Asset Wizard in Android Studio to create a dedicated notification icon — you will find a dedicated "Notification Icons" category for the "Icon Type" in the wizard. Then, switch to using that resource, instead of R.mipmap.ic_launcher, and see if you have better results.
Listen, the class in which you are creating a notification channel must inherit Application classenter image description here
enter image description here
I get this message when trying to display a notification on Android O.
Use of stream types is deprecated for operations other than volume
control
The notification is straight from the example docs, and displays fine on Android 25.
Per the comments on this Google+ post:
those [warnings] are currently expected when using NotificationCompat on Android O devices (NotificationCompat always calls setSound() even if you never pass in custom sound).
until the Support Library changes their code to use the AudioAttributes version of setSound, you'll always get that warning.
Therefore there's nothing that you can do about this warning. As per the notification channels guide, Android O deprecates setting a sound on an individual notification at all, instead having you set the sound on a notification channel used by all notifications of a particular type.
Starting with Android O, you are required to configure a NotificationChannel, and reference that channel when you attempt to display a notification.
private static final int NOTIFICATION_ID = 1;
private static final String NOTIFICATION_CHANNEL_ID = "my_notification_channel";
...
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_DEFAULT);
// Configure the notification channel.
notificationChannel.setDescription("Channel description");
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
notificationChannel.enableVibration(true);
notificationManager.createNotificationChannel(notificationChannel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setVibrate(new long[]{0, 100, 100, 100, 100, 100})
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Content Title")
.setContentText("Content Text");
notificationManager.notify(NOTIFICATION_ID, builder.build());
A couple of important notes:
Settings such as vibration pattern specified in the NotificationChannel override those specified in the actual Notification. I know, its counter-intuitive. You should either move settings that will change into the Notification, or use a different NotificationChannel for each configuration.
You cannot modify most of the NotificationChannel settings after you've passed it to createNotificationChannel(). You can't even call deleteNotificationChannel() and then try to re-add it. Using the ID of a deleted NotificationChannel will resurrect it, and it will be just as immutable as when it was first created. It will continue to use the old settings until the app is uninstalled. So you had better be sure about your channel settings, and reinstall the app if you are playing around with those settings in order for them to take effect.
All that #sky-kelsey has described is good, Just minor additions:
You should not register same channel every time if it has been already registered, so I have Utils class method that creates a channel for me:
public static final String NOTIFICATION_CHANNEL_ID_LOCATION = "notification_channel_location";
public static void registerLocationNotifChnnl(Context context) {
if (Build.VERSION.SDK_INT >= 26) {
NotificationManager mngr = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
if (mngr.getNotificationChannel(NOTIFICATION_CHANNEL_ID_LOCATION) != null) {
return;
}
//
NotificationChannel channel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID_LOCATION,
context.getString(R.string.notification_chnnl_location),
NotificationManager.IMPORTANCE_LOW);
// Configure the notification channel.
channel.setDescription(context.getString(R.string.notification_chnnl_location_descr));
channel.enableLights(false);
channel.enableVibration(false);
mngr.createNotificationChannel(channel);
}
}
strings.xml:
<string name="notification_chnnl_location">Location polling</string>
<string name="notification_chnnl_location_descr">You will see notifications on this channel ONLY during location polling</string>
And I call the method every time before I'm going to show a notification of the type:
...
NotificationUtil.registerLocationNotifChnnl(this);
return new NotificationCompat.Builder(this, NotificationUtil.NOTIFICATION_CHANNEL_ID_LOCATION)
.addAction(R.mipmap.ic_launcher, getString(R.string.open_app),
activityPendingIntent)
.addAction(android.R.drawable.ic_menu_close_clear_cancel, getString(R.string.remove_location_updates),
servicePendingIntent)
.setContentText(text)
...
Another typical problem - channel default sound - described here: https://stackoverflow.com/a/45920861/2133585
In Android O it's a must to use a NotificationChannel and NotificationCompat.Builder is deprecated (reference).
Below is a sample code :
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);
NotificationManager mNotificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("notify_001",
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
mNotificationManager.createNotificationChannel(channel);
}
mNotificationManager.notify(0, mBuilder.build());