> ## Documentation Index
> Fetch the complete documentation index at: https://docs.quickblox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Push Notifications

> Learn how to send push notifications to users when they are offline.

<Warning>
  Firebase is shutting down FCM legacy API on **June 20, 2024**. Migrate to FCM HTTP v1 API before this date in order to keep Android Push Notifications working. Follow steps in our [migration guide](https://quickblox.com/blog/firebase-cloud-messaging-fcm-migration-guide/).

  In case of any issues please reach us out via [our Help Center](https://help.quickblox.com/conversation/new).
</Warning>

Push Notifications provide a way to deliver some information to a user while they are not using your app actively. The following use cases can be covered by push notifications:

* **Offline messages.** Send a chat message when a recipient is offline. In this case, a push notification will be sent automatically if the user is offline.
* **Offline calls.** Make a video/audio call with offline opponents. In this case, a push notification will be sent manually.
* **Requests to contact list.** Send requests to add a user to the contact list. In this case, a push notification will be sent manually).
* **User tags.** Send notifications to specific user groups defined by tags.

Visit [Key Concepts](/docs/key-concepts) page to learn the most important QuickBlox concepts.

## Before you begin

1. Register a [QuickBlox account](https://admin.quickblox.com/signin). This is a matter of a few minutes and you will be able to use this account to build your apps.
2. Configure QuickBlox SDK for your app. Check out [Setup](/sdks/android-setup) page for more details.
3. Create a user session to be able to use QuickBlox functionality. See [Authentication](/sdks/android-authentication) page to learn how to do it.

<Tip>
  HTTP v1 API it's recommended solution.
</Tip>

<AccordionGroup>
  <Accordion title="HTTP v1 API">
    ### 1. Generate a new service account key

    <Frame>
      <img src="https://mintcdn.com/quickblox/-4CiPyZYUlxdCa4v/images/7e5e4f3-step1.webp?fit=max&auto=format&n=-4CiPyZYUlxdCa4v&q=85&s=ecd87cfdb7b8737568b2e6708b730795" alt="Generate New Service Account Key" width="1400" height="830" data-path="images/7e5e4f3-step1.webp" />
    </Frame>

    To generate a new service account key, you need to:

    1. Open the Firebase console and select your project.
    2. Go to Project settings > Service Accounts.
    3. Click on Generate new private key and confirm by clicking Generate key.
    4. Securely store the JSON file containing the private key that will be downloaded

    ### 2. Navigate to the push notifications section on QuickBlox dashboard

    <Frame>
      <img src="https://mintcdn.com/quickblox/blsYQNp-sI61UYaV/images/0b9db33-step2.webp?fit=max&auto=format&n=blsYQNp-sI61UYaV&q=85&s=3fdb1f8b8a9cd1aba4082fbef6b7e260" alt="Navigate to Push Notifications Section on QuickBlox Dashboard" width="1400" height="920" data-path="images/0b9db33-step2.webp" />
    </Frame>

    To navigate to the push notifications section:

    1. Head over to QuickBlox dashboard, and choose your application.
    2. Select the push notifications tab and navigate to the settings page.
    3. Select the Service account key tab

    Note: we will remove the Server key tab when it will be discontinued by FCM, you will by default only have the service account key section on the dashboard.

    ### 3. Upload the service account key on QuickBlox dashboard

    <Frame>
      <img src="https://mintcdn.com/quickblox/e8BObhqG0WJty0gE/images/5d06852-step3.webp?fit=max&auto=format&n=e8BObhqG0WJty0gE&q=85&s=6432e2c40ac0ba9809e217593e78f9fd" alt="Upload Service Account Key on QuickBlox Dashboard" width="1400" height="920" data-path="images/5d06852-step3.webp" />
    </Frame>

    To upload your service account key:

    1. Choose the environment for your service account key. (Development/Production)
    2. Click on the browse button and select the JSON file containing the key that was downloaded in step-1.
    3. Hit the upload button.

    Note: When setting up your environment, it’s important to distinguish between development and production modes. If you’ve uploaded a development certificate, it will only function for subscriptions created in the development environment, and likewise for production. This separation ensures seamless testing and deployment of push notifications across different environments.

    <Warning>
      API (Legacy) it's deprecated, not recommended
    </Warning>
  </Accordion>

  <Accordion title="How to enable Cloud Messaging API (Legacy)">
    To enable **Cloud Messaging API (legacy)** instead of **Firebase Cloud Messaging API (HTTP V1)**, please log in to your Firebase account, afterward select your Application and do the following:

    1. Click on the Settings icon.
    2. Select **Project Settings** from the drop-down list.

    <Frame>
      <img src="https://mintcdn.com/quickblox/Ue7oFsbTxPKULNVC/images/e2a0eb1-2022-09-16_13-40.png?fit=max&auto=format&n=Ue7oFsbTxPKULNVC&q=85&s=595b01f5ff7820fc54c34cb48dee5308" alt="Project Settings Cloud Messaging Tab" width="2408" height="368" data-path="images/e2a0eb1-2022-09-16_13-40.png" />
    </Frame>

    3. In section **Project Settings** select **Cloud Messaging** tab.
    4. Click on the three-dots (kebab) menu to the right of **Cloud Messaging API (Legacy)** and choose the **Manage API in Google Cloud Console** option. You will be redirected to **Google Cloud Console**.

    <Frame>
      <img src="https://mintcdn.com/quickblox/e8BObhqG0WJty0gE/images/6bc9d73-2022-09-16_17-01.png?fit=max&auto=format&n=e8BObhqG0WJty0gE&q=85&s=57e51fc502465d0cd613dbd28fbd2a99" alt="Enable Cloud Messaging" width="1540" height="706" data-path="images/6bc9d73-2022-09-16_17-01.png" />
    </Frame>

    5. Click the **Enable** buttons in the **Cloud Messaging** section.

    <Frame>
      <img src="https://mintcdn.com/quickblox/e8BObhqG0WJty0gE/images/5454a94-2022-09-16_15-48.png?fit=max&auto=format&n=e8BObhqG0WJty0gE&q=85&s=bde1dd34ba4911fb105019c3d7c6121f" alt="Server Key Appears" width="1646" height="762" data-path="images/5454a94-2022-09-16_15-48.png" />
    </Frame>

    6. Refresh the **Cloud Messaging** page and a server key will appear.

    <Frame>
      <img src="https://mintcdn.com/quickblox/tw9NMPEfMkW_LAuD/images/df5d105-2022-09-16_16-57.png?fit=max&auto=format&n=tw9NMPEfMkW_LAuD&q=85&s=ca36c8f26b1069b44a88f953287a8ddf" alt="Configure Firebase Project and API Key" width="1856" height="726" data-path="images/df5d105-2022-09-16_16-57.png" />
    </Frame>
  </Accordion>
</AccordionGroup>

## Configure Firebase project and API key

To start working with push notifications functionality, you need to configure it. At first, you should create a Firebase account if you haven't it. Then you should configure your [Firebase project](https://console.firebase.google.com/) and obtain the **API key**.

1. To find your **FCM server key**, go to your **Firebase console => Project Settings => Cloud Messaging**.

<Frame>
  <img src="https://mintcdn.com/quickblox/e8BObhqG0WJty0gE/images/487783f-firebase_project_settings.png?fit=max&auto=format&n=e8BObhqG0WJty0gE&q=85&s=48084506c3353ce5d7b3efb61e0c2d7e" alt="Firebase Project Settings" width="1280" height="222" data-path="images/487783f-firebase_project_settings.png" />
</Frame>

<Frame>
  <img src="https://mintcdn.com/quickblox/-4CiPyZYUlxdCa4v/images/73174fb-server_key.png?fit=max&auto=format&n=-4CiPyZYUlxdCa4v&q=85&s=a69ef537c571adb1db0513e8b84a5f9b" alt="Server Key" width="2144" height="866" data-path="images/73174fb-server_key.png" />
</Frame>

2. Copy the **server key** to your **Dashboard => *YOUR\_APP* => Push Notifications => Settings**, select the environment for which you are adding the key and click the **Save key**. Use the same server key for development and production zones. You can use both these environments up to you.

<Frame>
  <img src="https://mintcdn.com/quickblox/xkS1X1sSZwktmwsY/images/9c6584b-android-push-settings.png?fit=max&auto=format&n=xkS1X1sSZwktmwsY&q=85&s=13f656b166d451eb01205ad4d3017805" alt="Android Push Settings" width="1370" height="1010" data-path="images/9c6584b-android-push-settings.png" />
</Frame>

## Add Firebase to your Project

1. As part of enabling Firebase services in your Android application, you need to add the **google-services dependency** to your **project-level** `build.gradle` file.

```Groovy Groovy theme={null}
buildscript {

    // ...

    dependencies {
        // ...
        classpath 'com.google.gms:google-services:4.3.10'
    }
}
```

2. Add FCM dependency to your **app level** `build.gradle` file.

```Groovy Groovy theme={null}
implementation "com.google.firebase:firebase-core:20.0.0"
```

3. Include a **gms plugin** to your **app level** `build.gradle` file.

```Groovy Groovy theme={null}
apply plugin: 'com.google.gms.google-services'
```

4. Download the `google-services.json` file from your Firebase Project dashboard and put it into your app folder in your Android project.
5. Copy the **sender ID** value following **Firebase console => Project Settings => Cloud Messaging**.

<Frame>
  <img src="https://mintcdn.com/quickblox/-4CiPyZYUlxdCa4v/images/6eeb008-android-locate-project-settings.png?fit=max&auto=format&n=-4CiPyZYUlxdCa4v&q=85&s=3609aa3425eddc984f634b12be6d8bcf" alt="Locate Project Settings in Android" width="2552" height="442" data-path="images/6eeb008-android-locate-project-settings.png" />
</Frame>

<Frame>
  <img src="https://mintcdn.com/quickblox/4gw4x-2IrfN_sgat/images/1b66194-sender_id.png?fit=max&auto=format&n=4gw4x-2IrfN_sgat&q=85&s=138bc815519cf0dd88675bc9cc7880fe" alt="Sender ID" width="2216" height="858" data-path="images/1b66194-sender_id.png" />
</Frame>

6. Edit your app **AndroidManifest** file and add your Firebase **sender ID** as well as notification type and environment to integrate automatic push subscription.

```XML XML theme={null}
<meta-data
    android:name="com.quickblox.messages.TYPE"
    android:value="FCM"/>
<meta-data
    android:name="com.quickblox.messages.SENDER_ID"
    android:value="639872757929"/>
<meta-data
    android:name="com.quickblox.messages.QB_ENVIRONMENT"
    android:value="DEVELOPMENT"/>
```

* `com.quickblox.messages.TYPE` - can be `GCM` or `FCM`.
* `com.quickblox.messages.SENDER_ID` - your sender ID from google console (for example, 639872757929).
* `com.quickblox.messages.QB_ENVIRONMENT` - can be `DEVELOPMENT` or `PRODUCTION`.

7. Then you need to setup `QBFcmPushListenerService` and `QBFcmPushInstanceIDService` in AndroidManifest.

```XML XML theme={null}
<service android:name="com.quickblox.messages.services.fcm.QBFcmPushListenerService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
    </intent-filter>
</service>

<service android:name="com.quickblox.messages.services.fcm.QBFcmPushInstanceIDService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
    </intent-filter>
</service>
```

## Automatic push subscription

QuickBlox Android SDK provides automatic push subscription management. It means that you do not need to bother how to get FCM device token, create push subscription, and what to do with the received data. Thus, you can reduce your code and make it cleaner.

<Warning>
  A single user can have up to **10** subscriptions on different devices.
</Warning>

### Enable/Disable push subscription

Here you can use a global setting to enable or disable delivery of push notifications. Set this parameter only once.

<Tabs>
  <Tab title="Java">
    ```Java theme={null}
    QBSettings.getInstance().setEnablePushNotification(false);
    // by default is true

    boolean isEnabled = QBSettings.getInstance().isEnablePushNotification();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```Kotlin theme={null}
    QBSettings.getInstance().isEnablePushNotification = true
    // By Default is TRUE

    boolean isEnabled = QBSettings.getInstance().isEnablePushNotification
    ```
  </Tab>
</Tabs>

### Track subscription status

To be aware of what is happening with your push subscription, whether you're subscribed successfully or not, you can use the `QBSubscribeListener`. Just add `QBSubscribeListener` right after the `QBSettings.getInstance().init()` code.

<Tabs>
  <Tab title="Java">
    ```Java theme={null}
    QBPushManager.getInstance().addListener(new QBPushManager.QBSubscribeListener() {
        @Override
        public void onSubscriptionCreated() {

        }

        @Override
        public void onSubscriptionError(Exception exception, int resultCode) {
            if (resultCode >= 0) {
                // might be Google play service exception
            }
        }

        @Override
        public void onSubscriptionDeleted(boolean delete) {

        }
    });
    ```
  </Tab>

  <Tab title="Kotlin">
    ```Kotlin theme={null}
    QBPushManager.getInstance().addListener(object : QBPushManager.QBSubscribeListener {
        override fun onSubscriptionCreated() {

        }

        override fun onSubscriptionError(exception: Exception?, resultCode: Int?) {
            if (resultCode >= 0) {
                // might be Google play service exception
            }
        }

        override fun onSubscriptionDeleted(deleted: Boolean?) {

        }
    })
    ```
  </Tab>
</Tabs>

## Manual push subscription

If you do not want to use the automatic push subscription feature, then do the following:

1. Set `SubscribePushStrategy.NEVER` as the main strategy.

<Tabs>
  <Tab title="Java">
    ```Java theme={null}
    // default SubscribePushStrategy.ALWAYS
    QBSettings.getInstance().setSubscribePushStrategy(SubscribePushStrategy.NEVER)
    ```
  </Tab>

  <Tab title="Kotlin">
    ```Kotlin theme={null}
    // default SubscribePushStrategy.ALWAYS
    QBSettings.getInstance().subscribePushStrategy = SubscribePushStrategy.NEVER
    ```
  </Tab>
</Tabs>

In this case, you need to subscribe and unsubscribe manually using the following methods:

<Tabs>
  <Tab title="Java">
    ```Java theme={null}
    SubscribeService.subscribeToPushes(context, false);
    SubscribeService.unSubscribeFromPushes(context);
    ```
  </Tab>

  <Tab title="Kotlin">
    ```Kotlin theme={null}
    SubscribeService.subscribeToPushes(context, false)
    SubscribeService.unSubscribeFromPushes(context)
    ```
  </Tab>
</Tabs>

2. And then in your class extended from `QBFcmPushListenerService` you need to handle when the token is refreshed:

<Tabs>
  <Tab title="Java">
    ```Java theme={null}
    @Override
    public void onNewToken(String token) {
        boolean tokenRefreshed = true;
        SubscribeService.subscribeToPushes(context, tokenRefreshed);
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```Kotlin theme={null}
    override fun onNewToken(token: String?) {
        val tokenRefreshed = true
        SubscribeService.subscribeToPushes(context, tokenRefreshed)
    }
    ```
  </Tab>
</Tabs>

3. Add your class extended from `QBFcmPushListenerService` to the Manifest file.

```XML XML theme={null}
<service android:name="your_file_location.YourFilePushListenerService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
    </intent-filter>
</service>

<service android:name="com.quickblox.messages.services.fcm.QBFcmPushInstanceIDService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
    </intent-filter>
</service>
```

<Warning>
  The `token` is a device registration token generated by the APNs or GCM/FCM. The token can be unregistered by the APNs or GCM/FCM anytime. In this case, the device should be registered again and obtain a new token. When a new token is obtained, a new subscription should be created.
</Warning>

## Send push notifications

You can manually initiate sending of push notifications to a user/users on any event in your application. To send a push notification, you should use `QBEvent`, fill its fields with push notification parameters (payload) and set push recipients.

<Tabs>
  <Tab title="Java">
    ```Java theme={null}
    StringifyArrayList<Integer> userIds = new StringifyArrayList<>();

    for (QBUser user : userList) {
        userIds.add(user.getId());
    }

    QBEvent event = new QBEvent();
    event.setUserIds(userIDs);
    event.setEnvironment(QBEnvironment.DEVELOPMENT);
    event.setNotificationType(QBNotificationType.PUSH);
    event.setPushType(QBPushType.GCM);

    HashMap<String, Object> customData = new HashMap<>();
    customData.put("data.message", "Hello QuickBlox");
    customData.put("data.type", "First QuickBlox Push");

    event.setMessage(customData);

    QBPushNotifications.createEvents(event).performAsync(new QBEntityCallback<QBEvent>() {
        @Override
        public void onSuccess(QBEvent event, Bundle bundle) {

        }

        @Override
        public void onError(QBResponseException exception) {

        }
    });
    ```
  </Tab>

  <Tab title="Kotlin">
    ```Kotlin theme={null}
    val userIds = StringifyArrayList<Int>()

    for (user in userList) {
        userIds.add(user.id)
    }

    val event = QBEvent()
    event.userIds = userIDs
    event.environment = QBEnvironment.DEVELOPMENT
    event.notificationType = QBNotificationType.PUSH
    event.pushType = QBPushType.GCM

    val customData = HashMap<String, Any>()
    customData["data.message"] = "Hello QuickBlox"
    customData["data.type"] = "First QuickBlox Push"

    event.setMessage(customData)

    QBPushNotifications.createEvent(event).performAsync(object : QBEntityCallback<QBEvent> {
        override fun onSuccess(event: QBEvent?, bundle: Bundle?) {

        }

        override fun onError(exception: QBResponseException?) {

        }
    })
    ```
  </Tab>
</Tabs>

<Warning>
  You can send only FCM data messages to the Android app. QuickBlox doesn't support FCM notification messages.

  To process FCM data messages on your app when the app is in the background, you need to handle them. If not handled, they will not pop on the screen even if the app has received such push notification. See [FCM documentation](https://firebase.google.com/docs/cloud-messaging/concept-options#notifications%5Fand%5Fdata%5Fmessages) to learn more about data messages.
</Warning>

<Note>
  You can send APNs VoIP notifications to the iOS app. However, if the iOS app is not subscribed to APNs VoIP notifications or the APNs VoIP certificate has expired, the regular APNs will be delivered instead of APNs VoIP.
</Note>

## Receive push notifications

To receive push notifications, you should register the `BroadcastReceiver`.

<Tabs>
  <Tab title="Java">
    ```Java theme={null}
    BroadcastReceiver pushBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String message = intent.getStringExtra("message");
            String from = intent.getStringExtra("from");
        }
    };

    LocalBroadcastManager.getInstance(this).registerReceiver(pushBroadcastReceiver, new IntentFilter("new-push-event"));
    ```
  </Tab>

  <Tab title="Kotlin">
    ```Kotlin theme={null}
    val pushBroadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            val message = intent.getStringExtra("message")
            val from = intent.getStringExtra("from")
        }
    }

    LocalBroadcastManager.getInstance(this).registerReceiver(pushBroadcastReceiver, IntentFilter("new-push-event"))
    ```
  </Tab>
</Tabs>

Or use the `onMessageReceived()` in your class that extends `QBFcmPushListenerService`.

<Tabs>
  <Tab title="Java">
    ```Java theme={null}
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        String from = remoteMessage.getFrom();
        Map<String, String> data = remoteMessage.getData();
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```Kotlin theme={null}
    override fun onMessageReceived(remoteMessage: RemoteMessage?) {
        val from = remoteMessage?.from
        val data = remoteMessage?.data
    }
    ```
  </Tab>
</Tabs>

## Troubleshooting

#### Push notifications are not received on Android devices

**Cause 1**: incorrect FCM server key is set in the Dashboard.

**Tip**: check if you put a correct FCM server key into the **FCM API key** field in the **Dashboard => *YOUR\_APP* => Push Notifications => Settings**. See how to obtain the FCM server key and where to set it [here](/sdks/android-push-notifications#configure-firebase-project-and-api-key).

It is possible that you are using the FCM sender ID instead of the FCM server key in the Dashboard. Try to send the message from a Firebase console directly. If a message has appeared, a problem is in the FCM server key. If the FCM server key is incorrect, then there will be the following error: `error 401 (Unauthorized, check your App auth_key)`. This means that the QuickBlox server wasn't able to authorize on the Firebase server.

**Cause 2**: incorrect FCM sender ID in the `google-services.json` file.

<Tip>
  **Tip**: check if you added a correct `google-services.json` file to your project.
</Tip>

**Cause 3**: the push is sent to the production zone while the device is subscribed to the development zone or vice versa.

<Tip>
  **Tip**: check if you put the same FCM server key into the **FCM API key** field in the **Dashboard => *YOUR\_APP* => Push Notifications => Settings** for development and production to reduce the risk of error.
</Tip>

#### A subscription is removed after a push is sent and the push isn't delivered

**Cause**: a device registration token is invalid.

<Note>
  The device registration token is represented as `token` within the system. See [this section](/sdks/android-push-notifications#manual-push-subscription) to learn how to subscribe a device to push notifications.
</Note>

<Tip>
  **Tip**: check if the device registration is correct. The device registration token can be invalid due to a number of reasons:
</Tip>

1. Some other data is set instead of a correct device registration token. For example, a Firebase project ID, Firebase user token, etc.
2. The client app unregistered itself from GCM/FCM. This can happen if the user uninstalls the application or, on iOS, if the APNs Feedback Service reported the APNs token as invalid.
3. The registration token expired. For example, Google might decide to refresh registration tokens or the APNs token may have expired for iOS devices.
4. The client app was updated, but the new version is not configured to receive messages.

For all these cases, remove the invalid device registration token and stop using it to send messages. Then, obtain a new token and make sure to create a new subscription with a valid token.
