RB RB
RB RB

Reputation: 166

Sendbird push notification when app is in background

Here is my query. I have implemented sendbird sdk in one of my react-native app for chat implementation. I am trying to implement push notifications. I have used react-native-firebase for firebase push notifications as described in sendbird's documentation. Now the issue is my android app is getting push notification when the app is in foreground. OnMessageReceived() listener is triggered for this. But when my app is in background I am not receiving any push notification from sendbird.. None of the firebase notification listeners are triggered.

Also, when I am trying to send notification from firebase console I am receiving foreground as well as background notification.

Hoping for a response from you guys, as this can help me implement this feature successfully.

My notification listener code is similar to this. But, here haven't added display notification code though.

async componentDidMount() {
  this.checkPermission();
  this.createNotificationListeners(); //Notification listener 
}

 async createNotificationListeners() {
  /*
  * Triggered when a particular notification has been received in foreground
  * */
  this.notificationListener = firebase.notifications().onNotification((notification) => {
      const { title, body } = notification;
      this.showAlert(title, body);
  });

  /*
  * If your app is in background, you can listen for when a notification is clicked / tapped / opened as follows:
  * */
  this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen) => {
      const { title, body } = notificationOpen.notification;
      this.showAlert(title, body);
  });

  /*
  * If your app is closed, you can check if it was opened by a notification being clicked / tapped / opened as follows:
  * */
  const notificationOpen = await firebase.notifications().getInitialNotification();
  if (notificationOpen) {
      const { title, body } = notificationOpen.notification;
      this.showAlert(title, body);
  }
  /*
  * Triggered for data only payload in foreground
  * */
  this.messageListener = firebase.messaging().onMessage((message) => {
    //process data message
    console.log(JSON.stringify(message));
  });
}

showAlert(title, body) {
  Alert.alert(
    title, body,
    [
        { text: 'OK', onPress: () => console.log('OK Pressed') },
    ],
    { cancelable: false },
  );
}
}

My AndroidManifest.xml code is as below:-

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WAE_LOCK"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

<application ....

<activity android:name="com.facebook.devsupport.DevSettingsActivity"/>
<service android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService" android:exported="false">

<intent-filter>
   <action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service android:name="io.invertase.firebase.messaging.RNFirebaseBackgroundMessagingService"/>

<meta-data androd:name="com.google.firebase.messaging.default_notification_icon"
androd:resource="@mipmap/ic_launcher_logo"/>

<meta-data androd:name="com.google.firebase.messaging.default_notification_channel_id"
androd:value="test-channel"/>

</application>

Upvotes: 3

Views: 1717

Answers (2)

RB RB
RB RB

Reputation: 166

So finally after lot of research, I successfully got the solution by refering to the Sendbird's sample App, pasting link below.

https://github.com/sendbird/SendBird-JavaScript/tree/master/react-native-redux-sample

Solution:-

You need to register channel in App. Js componentDidMount().

//code for app js

componentDidMount(){
const channel = new firebase.notification.Android.Channel(
"YOUR-CHANNEL-ID",
"CHANNEL NAME",
firebase.notification.Android.Importance.Max).setDescription("description);
firebase.notifications().android.createChannel(chanel);


//don't forget to add handler for app state change
Appstate.addEventListener('change',this._handleAppStateChange);

)
}

_handleAppStateChange = currentAppState =>{
  const sb = SendBird.getInstance();
if(sb)
{
   if(currentAppState == "active")
  {
     sb.setForegroundState();
  }
else if(currentAppState == "background")
{
   sb.setBackgroundState();
}
}

//NOW in main index.js add below lines

import backgroundPush from './Services/push';

AppRegistry.registerHeadlessTask('RNFirebaseBackgroundMessage',()=>backgroundPush) //add this line after appRegistry Component and this is a key to be added to get notitification in background when using sendbird, whicch is nowhere mentioned in its official doc. It is in the sample App I have also added link to it.

And the push/backgroundPush that imported is a file containing below source:-

push.js //this file is in sample app though

import firebase from 'react-native-firebase'

export default async message => {
  try {
    const text = message.data.message;
    const payload = JSON.parse(message.data.sendbird);
    const localNotification = new firebase.notifications.Notification({
      show_in_foreground: true
    }).android
      .setChannelId('channel_id')
      .android.setSmallIcon('sendbird_ic_notification')
      .android.setPriority(firebase.notifications.Android.Priority.High)
      .setNotificationId(message.messageId)
      .setTitle('New message')
      .setSubtitle(`Unread message: ${payload.unread_message_count}`)
      .setBody(text)
      .setData(payload);
    return firebase.notifications().displayNotification(localNotification);
  } catch (e) {
    return Promise.resolve();
  }
};

This is the solution worked for me for my query Android background push notification now received. Although, still struggling with receiving push notificaiton iOS side.

Thanks.

Upvotes: 2

Muhammad Numan
Muhammad Numan

Reputation: 25403

For android set "priority": "high" into notification payload

{
  "to": "cjUyGxLa3pU...",
  "data": {
    "title": "Some title",
    "body": "Some text"
  },
  "priority": "high"
}

for ios i think it will able to get background and foreground notifications working by using the following code in my AppDelegate.m:

#import <UserNotifications/UserNotifications.h>
#import <Firebase.h>
#import <FirebaseInstanceID/FirebaseInstanceID.h>
#import <FirebaseMessaging.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
  }

if ([UNUserNotificationCenter class] != nil) {
    // iOS 10 or later
    // For iOS 10 display notification (sent via APNS)
    [UNUserNotificationCenter currentNotificationCenter].delegate = self;
    UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert |
    UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
    [[UNUserNotificationCenter currentNotificationCenter]
    requestAuthorizationWithOptions:authOptions
    completionHandler:^(BOOL granted, NSError * _Nullable error) {
    // …
    }];
   } else {
    // iOS 10 notifications aren’t available; fall back to iOS 8–9 notifications.
    UIUserNotificationType allNotificationTypes =
    (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
    UIUserNotificationSettings *settings =
    [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
    [application registerUserNotificationSettings:settings];
   }
  [application registerForRemoteNotifications];
  [FIRMessaging messaging].delegate = self;
  [[FIRInstanceID instanceID] instanceIDWithHandler:^(FIRInstanceIDResult * _Nullable result,
    NSError * _Nullable error) {
      if (error != nil) {
        NSLog(@"Error fetching remote instance ID: %@", error);
      } else {
        NSLog(@"Remote instance ID token: %@", result.token);
        NSString* message = [NSString stringWithFormat:@"Remote InstanceID token: %@", result.token];
      }
    }
  ];
  [FIRMessaging messaging].autoInitEnabled = YES;

...
}

- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
  NSLog(@"FCM registration token: %@", fcmToken);
  NSDictionary *dataDict = [NSDictionary dictionaryWithObject:fcmToken forKey:@"token"];
  [[NSNotificationCenter defaultCenter] postNotificationName: @"FCMToken" object:nil userInfo:dataDict];
}

/Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
  completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
}

also removed FirebaseAppDelegateProxyEnabled: YES in Info.plist if you have not this key on info.plist then you can add to try first before changing AppDelegate.m

Note: 1.5 years ago I used the same react-native-firebase library I received the same issue because then I moved to react-native-fcm library because that library is highly maintained

Upvotes: 1

Related Questions