V1(legacy)

Easiest way to integrate push notifications in your Chat applications is using Firebase. React Native Firebase is the officially recommended collection of packages that brings React Native support for all Firebase services on both Android and iOS apps.

Version 1 (legacy) of push notifications won’t be removed immediately but there won’t be any new features. That’s why new applications are highly recommended to use version 2 from the beginning to leverage upcoming new features.

Requirements

  • Only members of channel receive Push Notifications
  • We only send push notifications, when the user doesn’t have any active WebSocket connection (which is established when you call client.connectUser).
  • If you are using components from React Native Chat SDK, we automatically drop the WebSocket connection when app goes to background. To disable this behaviour, you can set prop closeConnectionOnBackground={false} on Chat component, in which case WebSocket will stay active for approximately 15-20 seconds when app goes to background.

Firebase Setup

Follow the steps mentioned on Firebase documentation setup Firebase.

  1. Create a firebase project.

  2. Register your Android and iOS app with Firebase app.

  3. Download a Firebase configuration file for iOS and Android.

  4. Install React Native Firebase.

    # Install & setup the app module
    yarn add @react-native-firebase/app
    
    # Install the messaging module
    yarn add @react-native-firebase/messaging
  5. Setup Android credentials.

  6. Setup iOS credentials.

Integration with Stream

Get the Server Key

  1. From the Firebase Console, select the project your app belongs to.
  2. Click on the gear icon next to Project Overview and navigate to Project settings.

Firebase Project Settings

  1. Navigate to the Cloud Messaging tab
  2. Under Project Credentials, locate the Server key and copy it

Upload Server Key on Stream

You can upload your server key either from dashboard OR using Stream Chat Server side SDK.

Upload FCM Server Key via Chat Dashboard

  1. Go to the Stream dashboard.
  2. Select your app.
  3. Go to Chat Overview page from top navigation.

  1. Enable Firebase Push notifications toggle.

  1. You will see a modal when you enable Firebase toggle, where you can enter your FCM Server Key. Or you can click on Edit Settings button to edit/update previously configured FCM Server Key.

Under the modal, you can also update the Firebase Notification Template. Please read more about template on template docs

  1. Save your push notification settings changes.

Upload FCM Server Key via Stream Chat Server side SDK

You can also upload the Server Key via API call using a backend SDK.

const client = StreamChat.getInstance(API_KEY, API_SECRET);
await client.updateAppSettings({
  firebase_config: {
    server_key: "server_key",
    notification_template: `{"message":{"notification":{"title":"New messages","body":"You have {{ unread_count }} new message(s) from {{ sender.name }}"},"android":{"ttl":"86400s","notification":{"click_action":"OPEN_ACTIVITY_1"}}}}`,
    data_template: `{"sender":"{{ sender.id }}","channel":{"type": "{{ channel.type }}","id":"{{ channel.id }}"},"message":"{{ message.id }}"}`,
  },
});

Registering a device with Stream

Once you configure Firebase server key and set it up on Stream dashboard, a device that is supposed to receive push notifications needs to be registered at Stream backend. This is usually done by listening for Firebase device token.

Please note that, client.addDevice call requires user token to be set on client. So client.addDevice call should be made after client.connectUser in code.

// Request Push Notification permission from device.
const requestPermission = async () => {
  const authStatus = await messaging().requestPermission();
  const enabled =
    authStatus === messaging.AuthorizationStatus.AUTHORIZED || authStatus === messaging.AuthorizationStatus.PROVISIONAL;

  if (enabled) {
    console.log('Authorization status:', authStatus);
  }
};

const App = () => {
  const [isReady, setIsReady] = useState(false);
  const unsubscribeTokenRefreshListenerRef = useRef<() => void>();

  useEffect(() => {
    // Register FCM token with stream chat server.
    const registerPushToken = async () => {
      // unsubscribe any previous listener
      unsubscribeTokenRefreshListenerRef.current?.();
      const token = await messaging().getToken();
      await client.addDevice(token, 'firebase');

      unsubscribeTokenRefreshListener = messaging().onTokenRefresh(async newToken => {
        await client.addDevice(newToken, 'firebase');
      });
    };

    const init = async () => {
      await client.connectUser({ id: USER_ID }, USER_TOKEN);

      await requestPermission();
      await registerPushToken();

      setIsReady(true);
    };

    init();

    return async () => {
      await client?.disconnectUser();
      unsubscribeTokenRefreshListenerRef.current?.();
    };
  }, []);

  if (!isReady) {
    return null;
  }

  return (
    <View style={styles.container}>
      <Chat client={client}>{/* Child components of Chat go here */}</Chat>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

This concludes the setup for push notifications. If you are having trouble receiving push notifications, please check Troubleshooting guide.

Interact with Push Notification

When a user interacts with your notification by pressing on it, the default behavior is to open the application (since notifications via FCM only display when the application is in the background, the application will always open).

On Android, you can set a "click_action": "OPEN_ACTIVITY_1" in Firebase Notification Template

In many cases, it is useful to detect whether the application was opened by pressing on a notification (so you could open a specific screen for example). The React Native Firebase API provides two APIs for handling interaction:

  • getInitialNotification: When the application is opened from a quit state.
  • onNotificationOpenedApp: When the application is running, but in the background.

You can access the notification data in both these functions. Make sure you have set the correct notification template in dashboard:

Please check Push Template docs for more details on template.

To handle both scenarios, the code can be executed during setup. For example, using React Navigation we can set an initial route when the app is opened from a quit state, and push to a new screen when the app is in a background state:

import React, { useEffect } from "react";
import messaging from "@react-native-firebase/messaging";
import { NavigationContainer } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";

const Stack = createStackNavigator();

function App() {
  useEffect(() => {
    // `onNotificationOpenedApp` gets called when app is in background, and you press
    // the push notification.
    //
    // Here its assumed a message-notification contains a "channel" property in the data payload.
    //
    // Please check the docs on push template:
    // /chat/docs/javascript/push_template/
    messaging().onNotificationOpenedApp((remoteMessage) => {
      console.log(
        "Notification caused app to open from background state:",
        remoteMessage,
      );
      const channel = JSON.parse(remoteMessage.data.channel);
      const message = remoteMessage.data.message;

      console.log("This message belongs to channel with id - ", channel.id);
      console.log("Message id is", message);

      // You will add your navigation logic, to navigate to relevant channel screen.
    });

    // `getInitialNotification` gets called when app is in quit state, and you press
    // the push notification.
    //
    //
    // Here its assumed that a message-notification contains a "channel" property in the data payload.
    // Please check the docs on push template:
    // /chat/docs/javascript/push_template/
    messaging()
      .getInitialNotification()
      .then((remoteMessage) => {
        if (remoteMessage) {
          console.log(
            "Notification caused app to open from quite state:",
            remoteMessage,
          );
          const channel = JSON.parse(remoteMessage.data.channel);
          const message = remoteMessage.data.message;

          console.log("This message belongs to channel with id - ", channel.id);
          console.log("Message id is", message);

          // You will add your navigation logic, to navigate to relevant channel screen.
        }
      });
  }, []);

  if (loading) {
    return null;
  }

  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName={initialRoute}>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="ChannelListScreen" component={SettingsScreen} />
        <Stack.Screen name="ChannelScreen" component={SettingsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

Troubleshooting

If you are having trouble receiving push notifications, please use our Push Notification Test Application to check if you have setup Push Configuration correctly. Please follow the steps mentioned in README for further instructions

If you are still having trouble with Push Notifications, please contact support@getstream.io

© Getstream.io, Inc. All Rights Reserved.