Discard a push notification when received on device - android

I'm using OneSignal to send push notifications to iOS and Android devices. Is it possible to discard a push notification when it's received on a iOS and Android device? It's not all of them, but some based on the payload data and if the user has the device in the background or foreground.
Update:
"discard" meaning that it is never shown as a notification.
What are my options when I don't want to disturb users with updates if they are already in foreground using their app, but in background I like to show the notification?

In OneSignal you want to use setNotificationWillShowInForegroundHandler method to decide whether the need to show a notification to the user or not.
For Android
OneSignal.setNotificationWillShowInForegroundHandler(new NotificationWillShowInForegroundHandler() {
#Override
void notificationWillShowInForeground(OSNotificationReceivedEvent notificationReceivedEvent) {
OSNotification notification = notificationReceivedEvent.getNotification();
// Get custom additional data you sent with the notification
JSONObject data = notification.getAdditionalData();
if (/* some condition */ ) {
// Complete with a notification means it will show
notificationReceivedEvent.complete(notification);
}
else {
// Complete with null means don't show a notification
notificationReceivedEvent.complete(null);
}
}
});
For IOS
let notificationWillShowInForegroundBlock: OSNotificationWillShowInForegroundBlock = { notification, completion in
print("Received Notification: ", notification.notificationId ?? "no id")
print("launchURL: ", notification.launchURL ?? "no launch url")
print("content_available = \(notification.contentAvailable)")
if notification.notificationId == "example_silent_notif" {
// Complete with null means don't show a notification
completion(nil)
} else {
// Complete with a notification means it will show
completion(notification)
}
}
OneSignal.setNotificationWillShowInForegroundHandler(notificationWillShowInForegroundBlock)
Note: For more info, you can check the documentation.
https://documentation.onesignal.com/docs/sdk-notification-event-handlers#foreground-notification-received-event

Related

How can I disable receiving notifications If the app is running in the Background? - Kotlin

I want to add functionality to my App to disable and enable notifications.
and for the notification I will use firebase cloud messaging "service push notifications"
If the app is running in the foreground then I will check a variable "showNotification" in the onMessageReceived function to show the notifications or not
if(showNotification) {
if (remoteMessage.notification != null) {
generateNot(
remoteMessage.notification!!.title!!,
remoteMessage.notification!!.body!!
)
}
}
The challenge I have is when the app is running in the background and since notifications are only displayed by the system when the app is not active.
Is there a way to disable showing notifications if the app is running in the background when the variable showNotification is false ?
I solved this problem using another method. you can override handleIntent instead of onMessageReceived. by using this method you are able to handle notification received from the firebase in foreground or background.
override fun handleIntent(intent: Intent?) {
val body = intent!!.getStringExtra("gcm.notification.body").toString()
val title = intent.getStringExtra("gcm.notification.title").toString()
try {
if(isAppOnForeground()){
// your app is running in the foreground
}else {
// your app is running in the background
}
} catch (e: Exception) {
Log.e("handleIntent: ", e.toString())
}
}
also you can get title and body using the code above. also with function below you can check if your app is in the background or not.
private fun isAppOnForeground(): Boolean {
return ProcessLifecycleOwner.get().lifecycle.currentState
.isAtLeast(Lifecycle.State.STARTED)
}

Firebase FCM notification image won't show

I am using FCM in my project and when trying to test the incoming notifications with the firebase "compose notification" feature I am putting a title, a body and an image URL to the message and it shows what it should look like - a rich notification with image. But the notification that is being sent to me is a normal one without any image.
here is the firebase UI and what is suposed to happen -
My issue is that I am getting only the text, without the image.
here is my MyFirebaseMessagingService class -
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public static final String RECEIVED_FCM_ACTION = "com.onemdtalent.app.RECEIVED_FCM_ACTION";
public static final String BD_KEY_BODY = "BD_KEY_BODY";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// [START_EXCLUDE]
// There are two types of messages data messages and notification messages. Data messages are handled
// here in onMessageReceived whether the app is in the foreground or background. Data messages are the type
// traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app
// is in the foreground. When the app is in the background an automatically generated notification is displayed.
// When the user taps on the notification they are returned to the app. Messages containing both notification
// and data payloads are treated as notification messages. The Firebase console always sends notification
// messages. For more see: https://firebase.google.com/docs/cloud-messaging/concept-options
// [END_EXCLUDE]
String image = remoteMessage.getData().get("image");
Timber.d("onMessageReceived: %s", remoteMessage.getFrom());
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
String body = remoteMessage.getNotification().getBody();
Timber.d("Message Notification Body: %s", body);
// broadcast
Intent localIntent = new Intent(RECEIVED_FCM_ACTION);
localIntent.putExtra(BD_KEY_BODY, image);
LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
}
}
}
As I sayed, I am getting only the text without the image. what am I missing?
Solved - I used an old version of firebase messaging dependency and I updated it, including my entire project to androidX and now I can see the images :)

FirebaseMessagingService Intercept notifications when app closed

can i intercept notifications when my app is closed?
I need for set badge with this library ShortcutBadger
Thanks.
There are 3 types of notifications:
notification: Can be send from the web console or any backend, it has predefines values. If the app is open the behaviour is customizable on onMessageRecieve if the app is closed triggers a default notification.
data: a key value pair, only Strings. Can be send from any backend. The behaviour is always defined in onMessageReceived method.
notification and data: Combination of previous it will have the behaviour of a notification, the data will be available as extras once the notification is clicked in the default launcher activity. Can be send from the web console or any backend.
A push is a json called Payload which contains those objects:
payload: {
data: {...}
}
Yes, you can send yourself a data type notification it will always do what you write in the onMessageReceived method inside the MessagingService.
This doc should help you
https://firebase.google.com/docs/cloud-messaging/concept-options?hl=es-419
If you dont have a server use Functions.
Since the default notification wont be shown, you will probably want to show your own.
If you want to also show a notification then the NotificationCompat class must be called from inside onMessageReceived. The visual notification is not related to the push message, in fact, a visual notification can be triggered by pressing a button.
For creating a visual notification, the best approach is to let Android Studio do it for you. Second click on the packages where your activities .java are, new, then selecet ui-component and there is the notification. It will create a basic template of a notification. Then use those methods inside onMessaReceived passing the info that has to be show to the user.
The docs about the class
https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html
And you will probably find this error
NotificationCompat.Builder deprecated in Android O
In case you never solved this, the problem is not how you are implementing it within your app, but how the JSON data payload is being sent. See this question and the respective answers for why you are not receiving the messages while they are in the background.
Very short summary is, if you are receiving the notification payload, it will never trigger in the background. If you receive the data payload without notification, you can parse and perform actions while the app is in the background.
do you mean it?
public class AppFcmMessagingsService extends FirebaseMessagingService {
private static final String TAG = "FirebaseMessageService";
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
try {
if(remoteMessage.getData().size() > 0) {
final JSONObject jsonObject = new JSONObject(remoteMessage.getData().toString());
Log.d(TAG,"remoteMessage = " + jsonObject.toString());
int badgeCount = 1;
ShortcutBadger.applyCount(getApplicationContext(), badgeCount);
}
} catch (Exception e) {
Log.e(TAG, "onMessageReceived: ", e);
}
if(remoteMessage.getNotification() != null) {
int badgeCount = 1;
ShortcutBadger.applyCount(getApplicationContext(), badgeCount);
Log.d(TAG, "notification body : " + remoteMessage.getNotification().getBody());
}
}
}

Android Firebase notifications (FCM)

I am using FCM in my app. I followed the Firebase documentation and all seems to be working as expected.
I am able to receive message notifications when the app is killed, in background and in foreground.
Now I want to give full control the user by adding some app preferences.
The user can disable all notification from the app settings
The user can change notification ringtone from the app settings
I have an idea on how to do it when the app is in killed or in the foreground. I am thinking of accessing the sharedprefs in my FirebaseMessagingService to see if the app should show the notification and check what ringtone to use. Unless there is a generic way to set those parameters, like "unsubscribing" from all notification or changing the app default notification ringtone which I am not aware of?
However I have no idea how i can do it for the notifications received when the app in is the background since the notifications are delivered to the device's system tray.
Anyone has any idea or can point me to some documentation... I am not finding any info on this?
By default, notifications affect every user. If you'd like to allow users to opt-out of all notifications (or certain subsets of notifications), you should use topic messaging: by default, you'd call subscribeToTopic() for all users and if they opt-out of notifications, you'd call unsubscribeToTopic().
By sending a notification to a topic, only the subscribed users will receive it.
The notification payload support documentation explains how to include a sound parameter to override the ringtone - on Android, that can be any sound bundled in the app's res/raw directory.
It should be noted that neither of these features are supported in the Console, but require that you create your own Firebase Cloud Messaging Server
As firebase notification service is having 2 object 1st is "data" and 2nd is "notification", when you are sending push from firebase console it sending data in "notification" object. When u handle the notification in FirebaseMessagingService.class you are creating a custom notification with NotificationBuilder. When App is in background you wont be able to create notification from "notification" object. so, your custom made notification wont be appear in notification tray, You need to push a notification from your backend and send notification contents in "data" object. You will be able to customise your notification every time.
please refer this for more : https://firebase.google.com/docs/cloud-messaging/android/send-multiple
The user can disable all notification from the app settings.
You can use shared preferences as you stated yourself. As far as a generic method is concerned you should look into #ianhanniballake 's answer.
The user can change notification ringtone from the app settings
For default ringtones refer to this link. The 3rd answer in this link also explains how to bring the sound selector from settings activity of your app. If you want custom sounds refer this.
Of course, you'll have to store user preferences so that you don't ask the user each time to select a sound.
And one more thing since you are using a service so you need not access shared preferences each and every time to find which sound to play, you can store the choice in any variable. Whenever there is a change of notif-sound by the user, you can either set a listener or {stop service -> update preferences -> restart service}. Make sure every time the service starts it reads the preferences.
In this AndroidHive tutorials you can find how we change Ringtone for particular app and how to deal with notifications when app is in foreground and app is in background.
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
......
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.e(TAG, "Notification Body: " + remoteMessage.getNotification().getBody());
handleNotification(remoteMessage.getNotification().getBody());
}
}
When notification type message is sent, firebase automatically shows the notification when the app is in background. If the app is in foreground, handleNotification() method handles the notification message.
private void handleNotification(String message) {
if (!NotificationUtils.isAppIsInBackground(getApplicationContext())) {
// app is in foreground, broadcast the push message
Intent pushNotification = new Intent(Config.PUSH_NOTIFICATION);
pushNotification.putExtra("message", message);
LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);
// play notification sound
NotificationUtils notificationUtils = new NotificationUtils(getApplicationContext());
notificationUtils.playNotificationSound();
}else{
// If the app is in background, firebase itself handles the notification
}
}
Here you handle custom Notification Sound-
// Playing notification sound
public void playNotificationSound() {
try {
Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
+ "://" + mContext.getPackageName() + "/raw/notification");
Ringtone r = RingtoneManager.getRingtone(mContext, alarmSound);
r.play();
} catch (Exception e) {
e.printStackTrace();
}
}
Firebase will not call your onMessageReceived when your app is in background or killed, and you can't customise your notification. System generated notification will show.
to make firebase library to call your onMessageReived in every cases
a) Foreground
b) Background
c) Killed
you must not put json key "notification" in your request to firebase api but instead use "data", see below.
For example following message will not call onMessagereceived()
{
"to": "/topics/test",
"notification": {
"title" : "title",
"text": "data!",
"icon": "ic_notification"
}
}
but this will work
{
"to": "/topics/test",
"data": {
"text":"text",
"title":"",
"line1":"testline",
"line2":"test"
}
}
see this link:https://firebase.google.com/docs/cloud-messaging/concept-options
it has a detailed description of firebase message type
For example:
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
if(remoteMessage.getData().get("state").toString().equals("Request")){
sendNotification(remoteMessage.getData().get("body").toString(), remoteMessage.getData().get("message").toString(), remoteMessage.getData().get("state").toString(),Activity_name.class);
}
}
private void sendNotification(String messageBody, String data, String state,Class<?> activityCompat) {
int requestID = (int) System.currentTimeMillis();
Intent intent = new Intent(this, activityCompat);
Bundle bundle = new Bundle();
bundle.putString("message", data);
bundle.putString("state", state);
intent.putExtras(bundle);
PendingIntent pendingIntent = PendingIntent.getActivity(this, requestID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.small_logo)
.setContentTitle("Title")
.setContentText(messageBody).setContentIntent(pendingIntent)
.setAutoCancel(true)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(messageBody))
.setTicker(messageBody);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationBuilder.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
Notification notification = notificationBuilder.build();
notificationManager.notify((int) Calendar.getInstance().getTimeInMillis(), notification);
}

Parse push notifications don't appear on notification tray on Android

I have an Android app developed with Ionic Framework. I'm using the ngCordova plugin for push notifications and sending them using parse.com
The notifications are received when the app is running, but the notifications are not shown on the notification tray when the app is on background. I receive something like this:
notification = {
payload: {
data: {
alert: "message",
}
}
}
But, when I send them directly through CGM, the notification do appear on the notification tray. And the object I receive is like:
notification = {
message: "this appear on notification tray",
payload: {
message: "this appear on notification tray"
}
}
Is there something wrong with Parse? Or is something I'm missing about Parse?
This is kind of an old post, but I ran across this issue using Xamarin and Parse Push notifications, but my work around may work for you (and others that may see this in the future).
I wound up broadcasting a local Push Notification after the Parse notification is received.
First assign a receiver to the Parse notification event:
ParsePush.ParsePushNotificationReceived += PushNotificationReceived;
Then in the method:
void PushNotificationReceived (object sender, ParsePushNotificationEventArgs e)
{
var payload = JObject.Parse (e.StringPayload); // Parse the JSON payload
Notification.Builder builder = new Notification.Builder (this);
builder.SetContentTitle (payload ["alert"].ToString ());
builder.SetContentText (payload ["androidDetail"].ToString ()); // Note: this is another field I added to the Parse Notification
builder.SetDefaults (NotificationDefaults.Sound | NotificationDefaults.Vibrate);
builder.SetSound (RingtoneManager.GetDefaultUri (RingtoneType.Notification));
builder.SetSmallIcon (Resource.Drawable.small_notification_icon);
var largeIcon = BitmapFactory.DecodeResource (Resources, Resource.Drawable.large_notification_icon);
builder.SetLargeIcon (largeIcon);
var notification = builder.Build ();
notification.Defaults |= NotificationDefaults.Vibrate;
NotificationManager notManager = (NotificationManager)GetSystemService (Context.NotificationService);
notManager.Notify (0, notification);
}
Hope this helps you and anyone else who comes across this!

Categories

Resources