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"/>
Related
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.
I am sharing two images please have a look on it you will understand my problem
in fist image notification comes successfully as shown better me notification but
I want it to come and show first on main screen as shown in second image just this telegram notification.
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
// r.play();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
r.setLooping(false);
}
// vibration
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
long[] pattern = {100, 300, 300, 300};
v.vibrate(pattern, -1);
int resourceImage = getResources().getIdentifier(remoteMessage.getNotification().getIcon(), "drawable", getPackageName());
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "CHANNEL_ID");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder.setSmallIcon(R.mipmap.betterme);
} else {
builder.setSmallIcon(R.mipmap.betterme);
}
Intent resultIntent = new Intent(this, SplashScreen.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentTitle(remoteMessage.getNotification().getTitle());
builder.setContentText(remoteMessage.getNotification().getBody());
builder.setContentIntent(pendingIntent);
builder.setStyle(new NotificationCompat.BigTextStyle().bigText(remoteMessage.getNotification().getBody()));
builder.setAutoCancel(true);
builder.setOngoing(true);
builder.setPriority(NotificationCompat.PRIORITY_MAX);
builder.setSound(notification);
mNotificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
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);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build();
channel.setSound(notification, audioAttributes);
mNotificationManager.createNotificationChannel(channel);
builder.setChannelId(channelId);
}
mNotificationManager.notify(100, builder.build());
}
}
first image
second image
If I understand correctly, you would like to have a heads up notification.
Note, that the android system decides when to make a notification a heads up notification and has the final say - not you the developer. Here you can find some examples when it does so: https://developer.android.com/guide/topics/ui/notifiers/notifications#Heads-up
Make sure that your setup reflects these. From your sample it seems to be the case, but maybe you have changed the notification channel settings (from the app settings), which override your code preferences (the user has precedence over the app).
Additionally, note that if you swipe the heads up notification in a upward direction (not sideways), Android starts a cool off time, where no heads up notifications from that app appears for a few seconds (or more). You can try that with Telegram or any other app as well. After the cool-off time, it starts showing up again like a heads up notification. This is a way Android utilises to prevent apps to be annoying to users.
Seems there is no problem in the notification. But your channel is already created with normal notification and you update to IMPORTANCE_HIGH for NotificationChannel.
Once the channel is created with priority it cannot be changed. So you can either change the channel id or uninstall and reinstall and test it.
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'm sending push notifications in my app and want to be able to show them even if the app is already running, so therefore I'm trying to use the onMessageReceived() function. The function runs whenever I send a notification and I can see that the title and body of the notification is correct, so no problems this far. Then I want the notification to pop up on the users device, but for some reason I just can't get it to work. I have looked at numerous sites and stackoverflow questions and all code basically looks the same, so it's a bit confusing why it doesn't work for me.
#Override
public void onMessageReceived(#NonNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
String messageTitle = remoteMessage.getNotification().getTitle();
String messageBody = remoteMessage.getNotification().getBody();
System.out.println("TITLE_IS: " + messageTitle);
System.out.println("MESSAGE_BODY: "+ messageBody);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, getString(R.string.default_notification_channel_id))
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(messageTitle)
.setContentText(messageBody);
//Sets ID for the notification
int mNotificationId = (int) System.currentTimeMillis();
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotifyMgr.notify(mNotificationId, mBuilder.build());
System.out.println("Everything went fine");
}
It never prints the last line ("Everything went fine"), but also don't give an error so it seems it works even though it didn't. What is the problem and how do I fix it?
There seem to have been a recent update which requires you to run some additional code in order for it to work on newer android versions. So the code should looks something like:
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, getString(R.string.default_notification_channel_id))
.setSmallIcon(R.drawable.ic_challenge)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setPriority(Notification.PRIORITY_MAX)
.setContentIntent(pendingIntent);
//to show notification do this
//Sets ID for the notification
int mNotificationId = (int) System.currentTimeMillis();
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
String channelId = "Tic-Tac-Toe";
NotificationChannel channel = new NotificationChannel(
channelId,
"Tic-Tac-Toe",
NotificationManager.IMPORTANCE_HIGH);
mNotifyMgr.createNotificationChannel(channel);
mBuilder.setChannelId(channelId);
}
mNotifyMgr.notify(mNotificationId, mBuilder.build());
I am working on a small project that involves a web interface that can send information to my android app which will display such information as Push Notifications.
But here is the thing, I am a bit confused with how to do that. As in what step will i have to take.
So I have a web interface in HTML which has a Textfield for notification Title, Content, and a submit button. I want it that when the user clicks the Submit button, the webpage will send the text that s in the Title and Content fields to my android app and then the app will just display them as push notifications.
So far on the app i have it that when you click a button on your device then it just shows a notification on the Actionbar. This is great for testing but It would be better that you can just compose your notification through a web interface.
My test Push Notification code for the app:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent();
PendingIntent pIntent = PendingIntent.getActivity(MainActivity.this, 0, intent, 0);
// TODO: Make this accessible to exterior projects, such as web interface.
Notification notification = new Notification.Builder(MainActivity.this)
.setTicker("Notification")
.setContentTitle("Important Message")
.setContentText("This is an example of a push notification using a Navigation Manager")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pIntent)
.build();
notification.flags = Notification.FLAG_AUTO_CANCEL;
NotificationManager nManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nManager.notify(0, notification);
}
});
If anyone could be so kind to give me a hand, it would be much appreciated.
You are right, so far so good with the notification bar, now what you need is a notification service, and google has something like that for us...
how does this works??
Take a look at the image below,
you need to register your android app in the google service, and your web interface will need an id, so everytime you want to push something to the android, your web interface instead will push it to the google server with the Id of the app, then google (no matter how) will localize your app, and even if its not running, they will get the notification,
behind the scenes there is a couple of thing that you must do, bu nothing like launching rockets from the NASA.
I will suggest to take a look to some tutorials
in order to start with the registration of your app, get the api key etc etc..
Here is a great source in github which shows how you can add push notification service in your android app
github.com/rana01645/android-push-notification
Firstly read the full documentation
How to add push notification in android application from android studio – Android developer (part – 1 Connect with firebase ) ~ http://androidrace.com/2016/12/08/how-to-add-push-notification-in-android-application-from-android-studio-android-developer-part-1-connect-with-firebase/
How to add push notification in android application from android studio – Android developer (part – 2 Working with server) ~http://androidrace.com/2017/01/05/how-to-add-push-notification-in-android-application-from-android-studio-android-developer-part-2-working-with-server/
Then you can able to send push notification from your server using html
public class Uyarilar extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent arg1) {
Date currentTime = Calendar.getInstance().getTime();
showNotification(context);
}
private void showNotification(Context context) {
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
new Intent(context, MainActivity.class), 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.presta)
.setContentTitle("Saat 9:00")
.setContentText("Mesai saatiniz başlamıştır Lütfen harakete geçiniz!");
mBuilder.setContentIntent(contentIntent);
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
mBuilder.setAutoCancel(true);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mBuilder.build());
}
}
and call
private void setNotification() {
Calendar calNow = Calendar.getInstance();
Calendar calSet = (Calendar) calNow.clone();
calSet.set(Calendar.HOUR_OF_DAY, 9);
calSet.set(Calendar.MINUTE, 00);
calSet.set(Calendar.SECOND, 0);
calSet.set(Calendar.MILLISECOND, 0);
if (calSet.compareTo(calNow) <= 0) {
calSet.add(Calendar.DATE, 1);
}
Date currentTime = Calendar.getInstance().getTime();
Intent intent = new Intent(getBaseContext(), Uyarilar.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), REQUEST_CODE, intent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calSet.getTimeInMillis(), pendingIntent);
}
and
onCreate
setNotification();
this method to push notification
public void testMessage (String message , Intent intent){
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 , intent,
PendingIntent.FLAG_ONE_SHOT);
String channelId = "some_channel_id";
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
android.support.v4.app.NotificationCompat.Builder notificationBuilder =
new android.support.v4.app.NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle(getString(R.string.app_name))
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setBadgeIconType(android.support.v4.app.NotificationCompat.BADGE_ICON_SMALL)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
assert notificationManager != null;
notificationManager.createNotificationChannel(channel);
}
assert notificationManager != null;
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}