React-native-intercom: Doesn't receive Push Notifications on Android

Created on 22 Dec 2017  Â·  32Comments  Â·  Source: tinycreative/react-native-intercom

Hello,
First off, thanks for a great library!

98% of the implementation went swiftly and easily but getting pushes to show up has shown itself to be impossible (for me at least).

Problem

To repeat, the problem is that I can't get push notifications sent from Intercom to show up on an Android device. In App messages work fine and all the other features. The user used for testing is verified to be accepting pushes and we're sending the push tokens to Intercom like this:

FCM.getFCMToken().then(pushToken => {
  if (pushToken) {
    // Send to internal backend push service
    this.props.postUserPush(pushToken, 'fcm')
    Intercom.sendTokenToIntercom(pushToken)
  }
})

And when running adb logcat I'm seeing MessagingService: Remote message received when sending pushes from Intercom. Which I interpret as the push arriving at the device but something blocks it from showing up, ergo some problem with my implementation. But I can't for the life of me figure out what's wrong.

Environment

We have an existing Push Notification setup using react-native-fcm which is verified to be receiving pushes from our own Push Service as before.

Some code

build.gradle

...
compileSdkVersion 26
buildToolsVersion "26.0.2"
...
minSdkVersion 16
targetSdkVersion 23
...

```java
...
compile project(':react-native-fcm')
compile 'com.google.firebase:firebase-core:11.+'
...
compile 'io.intercom.android:intercom-sdk-base:4.+'
compile 'io.intercom.android:intercom-sdk-fcm:4.+'
compile 'com.google.firebase:firebase-messaging:11.+'

**AndroidManifest.xml**
```xml
...
<service android:name="com.robinpowered.react.Intercom.IntercomIntentService" android:exported="false">
    <intent-filter android:priority="999">
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
    </intent-filter>
</service>
<receiver android:name="io.intercom.android.sdk.push.IntercomPushBroadcastReceiver" tools:replace="android:exported" android:exported="true" />
<service android:name="com.evollu.react.fcm.MessagingService" android:enabled="true" android:exported="true">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
    </intent-filter>
</service>

<service android:name="com.evollu.react.fcm.InstanceIdService" android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
    </intent-filter>
</service>
...

Any help or guidance would be greatly appreciated!

Most helpful comment

I fixed this issue by overriding the MessagingService of the react-native-fcm library. This gives the effect of IntercomIntentService not being used since the push handling happens in the class OverriddenMessagingService (just an example name).

Example:

public class OverriddenMessagingService extends MessagingService {
    private static final String TAG = "OverriddenMessagingService";
    private final IntercomPushClient intercomPushClient = new IntercomPushClient();

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Map message = remoteMessage.getData();
        if (intercomPushClient.isIntercomPush(message)) {
            Log.d(TAG, "Intercom message received");
            intercomPushClient.handlePush(getApplication(), message);
        } else {
            super.onMessageReceived(remoteMessage);
        }
    }
}

All 32 comments

If you're running react-native-firebase it will grab the incoming messages.
I caught this by running the log from android studio while sending the message from intercom and saw this message
D/MessagingService: Remote message received - which is from
https://github.com/invertase/react-native-firebase/blob/master/android/src/main/java/io/invertase/firebase/messaging/MessagingService.java

@iamjon not using react-native-firebase in this project, but using react-native-fcm which also has a MessagingService at com.evollu.react.fcm.MessagingService

@jrbaudin
Check that it is not capturing your messages.

@iamjon I've verified that what happens is that

if (intercomPushClient.isIntercomPush(intent.getExtras())) {
    intercomPushClient.handlePush(getApplication(), intent.getExtras());
    return;
}

... doesn't run. I.e. intercomPushClient.isIntercomPush(intent.getExtras()) returns false when I send push messages from Intercom.

Then the intent/push message is passed on towards to react-native-fcm (printing MessagingService: Remote message received etc) as is expected behaviour.

The sequence is then correct when react-native-intercom handles the intent first and then react-native-fcm

For debugging purposes

intent.getExtras();

Gives...

Bundle[{android.support.content.wakelockid=5}]

I fixed this issue by overriding the MessagingService of the react-native-fcm library. This gives the effect of IntercomIntentService not being used since the push handling happens in the class OverriddenMessagingService (just an example name).

Example:

public class OverriddenMessagingService extends MessagingService {
    private static final String TAG = "OverriddenMessagingService";
    private final IntercomPushClient intercomPushClient = new IntercomPushClient();

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Map message = remoteMessage.getData();
        if (intercomPushClient.isIntercomPush(message)) {
            Log.d(TAG, "Intercom message received");
            intercomPushClient.handlePush(getApplication(), message);
        } else {
            super.onMessageReceived(remoteMessage);
        }
    }
}

@jrbaudin I implemented the following and still could not get it working. Could you be more specific? Do I need to do any JS for this to work? Will using any of the libraries JS functions override what's done here? Which server key did you use: legacy or standard? Did you specify a sender id? My FCM notifications are working from firebase, just not from Intercom. I'm using react-native-firebase, would make a difference in my overrides? They seem to have the same classes.

package com.my.app;

import io.invertase.firebase.messaging.*;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import io.intercom.android.sdk.push.IntercomPushClient;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;

public class MainInstanceIdService extends InstanceIdService {
  private final IntercomPushClient intercomPushClient = new IntercomPushClient();
  private static final String TAG = "InstanceIdService";

  /**
   * Called if InstanceID token is updated. This may occur if the security of
   * the previous token had been compromised. This call is initiated by the
   * InstanceID provider.
   */
  @Override
  public void onTokenRefresh() {
    // Get updated InstanceID token.
    String refreshedToken = FirebaseInstanceId.getInstance().getToken();
    intercomPushClient.sendTokenToIntercom(getApplication(), refreshedToken);
    Log.d(TAG, "Refreshed token: " + refreshedToken);

    // Broadcast refreshed token
    Intent i = new Intent("io.invertase.firebase.messaging.FCMRefreshToken");
    Bundle bundle = new Bundle();
    bundle.putString("token", refreshedToken);
    i.putExtras(bundle);
    sendBroadcast(i);
  }
}
///
package com.my.app;
import io.invertase.firebase.messaging.*;
import android.content.Intent;
import android.content.Context;
import io.intercom.android.sdk.push.IntercomPushClient;
import com.google.firebase.messaging.RemoteMessage;
import android.util.Log;
import java.util.Map;

public class MainMessagingService extends MessagingService {
    private static final String TAG = "MainMessagingService";
    private final IntercomPushClient intercomPushClient = new IntercomPushClient();

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Map message = remoteMessage.getData();
        if (intercomPushClient.isIntercomPush(message)) {
            Log.d(TAG, "Intercom message received");
            intercomPushClient.handlePush(getApplication(), message);
        } else {
            super.onMessageReceived(remoteMessage);
        }
    }
}

@jrbaudin UPDATE: My code above does work but you need to make sure you have this in your Android manifest for the overrides and it works well 👍


android:name=".MainMessagingService"
android:enabled="true"
android:exported="true">








@evanjmg I intergrated your code but still push notification is not displaying in tray. As i debugged it going to " intercomPushClient.handlePush(getApplication(), message);"

Any help on this ?

There are a lot more things than this to setup to get working as documented in the intercom setup on their website. This is the bit that’s missing from the documentation in this repo. So follow everything intercom lists in the intercom android setup guide (not this repo) such as adding the correct server key in intercom settings etc. From my experience, my pushes did not work on a test account also, I had to use a live account

On Mar 9, 2018, at 5:59 AM, Jaffer notifications@github.com wrote:

@evanjmg I intergrated your code but still push notification is not displaying in tray. As i debugged it going to " intercomPushClient.handlePush(getApplication(), message);"

Any help on this ?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

Any luck on this one? I still cannot receive notification from firebase console for android.

If you are using FCM. Make sure you have the following:

  • receiving a firebase token from Firebase and sending it to user. Earlier versions of firebase and React native firebase didn’t always send the token on all devices. Make sure you have latest React native firebase and are receiving the token every time.
  • then it’s best to hook into your own instance message service as coded in Java above - be sure to switch out the service in the Android manifest
  • lastly ensure you have the correct server token in intercom

The code has changed slightly from the latest firebase update. When I have time at home, i’ll Try to update it

hi @evanjmg where did you implement the override services? I mean you created a new file or in an existen file or your android folder? I am not so familiarized with android, and I am facing the same problem as you notifcations from firebase console are working on android and ios perfectly (using react-native-firebase and FCM) but push notifications from intercom are only displayed in ios. Lot of thanks!

See the xml snippet of the android manifest above I posted. Instead of using the RN fcm service, use your 2 of your own services - MainMessagingService and MainInstanceIdService. create 2 new files similar to the two above I shared and put them in same the directory as your MainApplication.java. If you’re not comfortable playing around with Java you’ll have some difficulty with this as you will need to rename a couple things such as your com.yourapp to your dependency etc.

I guess you should extend RNFirebaseMessagingService and RNFirebaseInstanceIdService instead of MessagingService and InstanceIdService. Btw, I am wondering why you did not include the methods isIntercomPush and handlePush in the react-native-intercom library, then it would be easier and the services will not be required. I did a fork to implement it, but due to my basic Java skills I am having some implementation issues, but when it will be done I will create a PR :)

@evanjmg @jrbaudin So where are we at with this? I can currently send notifications from Firebase to my app which work fine, but when I try to use Intercom I get nothing.

Also tried removing firebase FCM completely, but then you can't send a firebase.messaging() token to Intercom...

Readme is confusing on this. Is firebase messaging / notifications a dependancy here?

Edit: I'm using @evanjmg's suggested implementation above, but intercomPushClient.handlePush() gives me this error:

06-19 17:09:09.060 11298 11448 D MainMessagingService: Intercom message received
06-19 17:09:09.068  1703  3792 E NotificationService: No Channel found for pkg=com.myapp.name, 
channelId=intercom_actions_channel, id=1681756710, tag=17062540287, opPkg=com.myapp.name,
callingUid=10079, userId=0, incomingUserId=0, notificationUid=10079, 
notification=Notification(channel=intercom_actions_channel pri=1 contentView=null vibrate=null sound=null 
defaults=0x0 flags=0x11 color=0xff333333 category=msg vis=PRIVATE)

Do I have to do anything special to get this to work?

I use react-native-firebase. I followed @evanjmg's suggested implementation by overriding RNFirebaseMessagingService to intercept the intercom messages however couldn't get it to work like many others here.
What finally solved it for me was adding
implementation "io.intercom.android:intercom-sdk-fcm:5.+" to my gradle dependencies

@sauceypan I've tried all the things here but could not get it working, could you give us more details please?

This + the solution in #208 helped me out. I'm using react-native-firebase and react-native-intercom with FCM. I had to add this MessagingService code, but also had to remove the <service android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service> <service android:name="io.invertase.firebase.messaging.RNFirebaseInstanceIdService"> <intent-filter> <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/> </intent-filter> </service>
code in the manifest in favour of the manifest code specified in these issues.

@zibs I've tried that workaround too, could you please give me the list of changes in .gradle, manifest please?

After following all the advice in this thread, the final missing step for me was to create a channel for the intercom replies:

const intercomChannel = new firebase.notifications.Android.Channel(
        "intercom_chat_replies_channel",
        "Intercom Replies Channel",
        firebase.notifications.Android.Importance.Max
      ).setDescription("Channel for intercom replies");

@mtford90 can you get push notification when android app is killed?

@vvusts - ha, nope - I realised that a couple hours after I implemented this...

I moved the creation of the channels to native land and now I can. So in my MainApplication.java I now have:

    @Override
    public void onCreate() {
        // ...
        SoLoader.init(this, /* native exopackage */ false);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            int importance = NotificationManager.IMPORTANCE_HIGH;
            NotificationChannel intercomChannel = new NotificationChannel("intercom_chat_replies_channel", "Intercom Replies", importance);
            intercomChannel.setDescription("Replies from Support (Chat to us)");
            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            assert notificationManager != null;
            notificationManager.createNotificationChannel(intercomChannel);
        }
    }

@mtford90 I can't figure import I imported NotificationManager and NotificationChannel from intercom and build failed what imports you use?

@vvusts

import android.app.NotificationChannel;
import android.app.NotificationManager;

@mtford90 thanks I would never thought to register channels in native.
Just short question can you catch in rn code when user tap on notification to get data from message? For me firebase.notifications().onNotificationOpened is not called when intercom notification is invoked. I am interested does this work for you?

@vvusts I didn't need to use that.

For reasons I haven't investigated fully, when the intercom notification is tapped my Linking event listener fires off with an intercom url and then I do the following:

   // Also: Linking.getInitialURL()
    Linking.addEventListener("url", e => {
      const url = e.url;
      const components = URI.parse(url);
      if (components.path && components.path.startsWith("intercom_sdk/")) {
        Intercom.handlePushMessage();
      }
    });

@vvusts I did just check though and I do indeed receive data from firebase.notifications

I would like to add one update to this.

Solution from @mtford90 works well. But later I found that Intercom Android SDK implements this on their own, since version 4.0.0 here changelog:

What fixed the same issue for me was using this sdk in my build.gradle

implementation 'io.intercom.android:intercom-sdk:5.+'

I removed the io.intercom.android:intercom-sdk-fcm:5.+ which was recommended in readme here.

After this it all worked out of the box.

@usrbowe this is strange because I have to use @mtford90 solution to get the notification through.

implementation 'io.intercom.android:intercom-sdk-base:6.+'

Im using this now though.
Should not be a reason for that not to work 🤔

But im getting both replies and new chats when I create the notification channels explictly.

But I would love to understand why.

Also @mtford90 why do you need that if sentence when creating the channel?
I also had to add to get new chats notificaitons

NotificationChannel intercomNewChannel = new NotificationChannel("intercom_new_chats_channel", "Intercom Chats", importance);

@vongohren had same problem on nativescript.

implementation 'io.intercom.android:intercom-sdk-base:6.+'

does not create notification channel for push notifications

implementation 'io.intercom.android:intercom-sdk:6.+'

solved the problem. Didn't spot that _sdk-base_ and _sdk_ difference at first...

@kanclalg ah, so there is a -base difference :D
So then you dont need to create your own channels?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

elnygren picture elnygren  Â·  10Comments

aditibarbhai picture aditibarbhai  Â·  6Comments

wadeyw picture wadeyw  Â·  5Comments

forsen picture forsen  Â·  5Comments

felippepuhle picture felippepuhle  Â·  9Comments