17

I'm using Firebase console to send notifications to users. However I want to let users disable notifications. How can I disable them?

I am able to handle (and stop) notifications through FirebaseMessagingService only when the app is in foreground. But I cannot stop notifications when the app is in background.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
martinodecarlo
  • 173
  • 1
  • 1
  • 6

5 Answers5

14

I couldn't comment yet, but racs' comment helped me a lot.

Actually, Firebase docs recommend to use data push instead of notifications if you want to have complete control over how it is handled: firebase.google.com/docs/cloud-messaging/… - quote: "Use notifications when you want FCM to handle displaying a notification on your client app's behalf. Use data messages when you want your app to handle the display or process the messages on your Android client app..."

So basically, I changed the body for the push notification request from:

{
   "data": {
       "type" : "mytype"
    },
    "notification": {
        "title": "My Title",
        "body": "My Notification Message"
    },
    "to": "/topics/all"
}

To:

{
   "data": {
       "type" : "mytype",
       "title": "My Title",
       "body": "My Notification Message"
    },
    "to": "/topics/all"
}

Now my app calls onMessageReceived() everytime even in background, and I just changed the methods to use the obtained notification title and message in the push data.

Community
  • 1
  • 1
Alvin Rusli
  • 1,026
  • 1
  • 11
  • 19
6

Not sure why this happens to you (code snippet maybe?), but there is a heavy weight ultimate solution: define your own c2dm receiver in the manifest and set the priority high (>0) then stop the notification from processing.

GCM messages are processed as ordered broadcasts, so you can stop the processing chain by calling this method:

https://developer.android.com/reference/android/content/BroadcastReceiver.html#abortBroadcast()

If you don't do anything in your receiver then the next receiver will do the processing, which will be the Firebase receiver.

Please note: Firebase is sending push notification for Remote Config changes. So, if you use Remote Config then it is not advisable to suppress any data push.

racs
  • 3,974
  • 2
  • 23
  • 26
  • 1
    Actually, Firebase docs recommend to use data push instead of notifications if you want to have complete control over how it is handled: https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages - quote: "Use notifications when you want FCM to handle displaying a notification on your client app's behalf. Use data messages when you want your app to handle the display or process the messages on your Android client app..." – racs May 30 '16 at 04:01
  • Thank you. Using data push (through a POST request) I am able to handle the notification even if the app is in background. Now, how can I send data to all devices without specifying the token of every single device in my JSON file? Through Firebase console it is possibile to specify "User Segment", but if I don't specify the element "to" in the JSON file, I receive the error 400. – martinodecarlo Jun 04 '16 at 12:12
  • I am not an expert on this topic, but as far as I can tell when you do data push then basically you skip the Firebase features all together. So no sending to topic subscribers or analytics is available. In this case FB is acting as a relay to GCM and does not interact with the sent data at all. – racs Jun 06 '16 at 21:18
  • As it seems sending data to topics is available: https://firebase.google.com/docs/cloud-messaging/topic-messaging#sending_topic_messages_from_the_server You can sign up every device to a topic and send the data push to that topic, so you don't need to track the device tokens by yourself. – racs Jun 06 '16 at 21:36
3

I meet the same question. I use subscribeToTopic API to subscribe the notification.

FirebaseMessaging.getInstance().subscribeToTopic("APP");

And I find the other API unsubscribeFromTopic to unsubscribe.

FirebaseMessaging.getInstance().unsubscribeFromTopic("APP");

Maybe it would be useful for APP using topic notification. It would not receive notification in foreground and background.

Tunaki
  • 132,869
  • 46
  • 340
  • 423
Fantasy Fang
  • 6,106
  • 2
  • 25
  • 30
3

I had this problem.and solved by use below code:

Enable Firebase Notifications:

FirebaseInstanceId.getInstance().getToken();

Disable Firebase Notifications: deleteInstanceId() is a blocking call. It cannot be called on the main thread.

FirebaseInstanceId.getInstance().deleteInstanceId();
Better
  • 165
  • 1
  • 13
  • where mothod is set `FirebaseInstanceId.getInstance().deleteInstanceId();` ? – ARR.s Jul 06 '17 at 10:55
  • I use AsyncTask,and put `FirebaseInstanceId.getInstance().deleteInstanceId();` in `doInBackground` – Better Aug 25 '17 at 01:13
  • Just a note that FirebaseInstanceId is deprecated (the whole IID package is deprecated) but the Installations package has taken over it's duties, and `FirebaseInstallations.getInstance().delete()` should do the trick (https://firebase.google.com/docs/reference/android/com/google/firebase/installations/FirebaseInstallations#delete()) – Mike Hardy Sep 02 '21 at 18:39
2

You can handle all push events from all difference services (with Firebase). First create YouUniversalFCM extends WakefulBroadcastReceiver

For example:

public class YourUniversalFCM extends WakefulBroadcastReceiver {

    private static final String ACTION_REGISTRATION
        = "com.google.android.c2dm.intent.REGISTRATION";
    private static final String ACTION_RECEIVE
        = "com.google.android.c2dm.intent.RECEIVE";

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        for (String key : intent.getExtras().keySet()) {
            Log.d(
                    "TAG",
                    "{UniversalFCM}->onReceive: key->"
                            + key + ", value->" + intent.getExtras().get(key)
            );
        }
        switch (action) {
            case ACTION_REGISTRATION:
                // TODO: 2016-08-06
                break;

            case ACTION_RECEIVE:
                // TODO: 2016-08-06
                break;

            default:
        }

        abortBroadcast();
    }
}

Next in AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>

<application
    ...>

    ...

    <receiver
        android:name=".fcm.receivers.UniversalFCM"
        android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
            <action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
            <category android:name="YOUR_PACKAGE"/>
        </intent-filter>
    </receiver>

</application>

Replace YOUR_PACKAGE by the package of your app. That's all. If you want to subscribe for another push service, you must be add YourTokenService

public class YourTokenService extends FirebaseInstanceIdService {
    @Override
    public void onTokenRefresh() {
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        L.d(TokenService.class, "onTokenRefresh() Refreshed token: " + refreshedToken);
        // TODO: 2016-08-06
        super.onTokenRefresh();
    }
}

And declared in AndroidManifest.xml

<service android:name="YourTokenService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
    </intent-filter>
</service>
Kurt Van den Branden
  • 11,995
  • 10
  • 76
  • 85
TarikW
  • 359
  • 4
  • 12