davide-scalzo / react-native-mixpanel

A React Native wrapper for Mixpanel tracking
MIT License
455 stars 195 forks source link

Firebase and mixpanel support on Android #194

Open tjhowe opened 5 years ago

tjhowe commented 5 years ago

I've been implementing adding mixpanel to a project with an existing firebase configuration. I've followed the installation documentation outline in the readme. Then I added the extension of the FirebaseMessagingService outline in this release. I am also using firebase notifications in the react native app, I receive iOS notifications in the js listeners, but not android.

package org.tm.app;
import com.google.firebase.messaging.RemoteMessage;
import com.mixpanel.android.mpmetrics.MixpanelFCMMessagingService;
import com.google.firebase.messaging.FirebaseMessagingService;
import android.util.Log;

public class PushProviderService extends FirebaseMessagingService {
    private static final String TAG = "PushProviderService";

    @Override
    public void onNewToken(String s) {
        super.onNewToken(s);
        Log.d(TAG, "MixpanelFCMMessagingService token: " + s);

        MixpanelFCMMessagingService.addToken(s);
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);

        if (remoteMessage.getData().containsKey( "mp_message")) {
            Log.d(TAG, "application context" + getApplicationContext().toString());
            Log.d(TAG, "Message Notification getFrom: " + remoteMessage.toString());
            Log.d(TAG, "Message Notification Intent: " + remoteMessage.toIntent().toString());
            Log.d(TAG, "Message Notification getFrom: " + remoteMessage.getFrom().toString());
            Log.d(TAG, "Notification Data: " + remoteMessage.getData().toString());

            MixpanelFCMMessagingService.showPushNotification(getApplicationContext(), remoteMessage.toIntent());
        }
    }
}

I then added this service to my Manifest file.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="org.tm.app">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.VIBRATE"/>
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-feature android:name="android.hardware.camera" android:required="false" />
    <uses-feature android:name="android.hardware.camera.front" android:required="false" />

    <application
      android:name=".MainApplication"
      android:label="@string/app_name"
      android:icon="@mipmap/ic_launcher"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:allowBackup="false"
      android:theme="@style/AppTheme">

      <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:screenOrientation="unspecified"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
        android:windowSoftInputMode="adjustResize"
        android:launchMode="singleTop">
        <intent-filter>
          <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
          <action android:name="android.intent.action.VIEW" />
          <category android:name="android.intent.category.DEFAULT" />
          <category android:name="android.intent.category.BROWSABLE" />
          <data android:scheme="tmapp" />
        </intent-filter>
      </activity>

      <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

      <activity android:name="SplashActivity" android:theme="@style/SplashTheme">
        <intent-filter>
          <action android:name="android.intent.action.MAIN" />
        </intent-filter>
      </activity>

      <service android:name="io.invertase.firebase.messaging.RNFirebaseBackgroundMessagingService" />

      <meta-data android:name="com.mixpanel.android.MPConfig.ResourcePackageName" android:value="org.tm.app" />

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

      <service android:name=".PushProviderService" android:exported="false">
        <intent-filter>
          <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
      </service>

      <receiver android:name="io.invertase.firebase.notifications.RNFirebaseNotificationReceiver"/>

      <receiver android:enabled="true" android:exported="true" android:name="io.invertase.firebase.notifications.RNFirebaseNotificationsRebootReceiver">
        <intent-filter>
          <action android:name="android.intent.action.BOOT_COMPLETED"/>
          <action android:name="android.intent.action.QUICKBOOT_POWERON"/>
          <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
          <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
      </receiver>
    </application>

</manifest>

I am receiving the notification data from mixpanel when logging in logcat in android studio, so i assume the api keys are provided - however I only receive background notifications. The MixpanelFCMMessagingService.showPushNotification is being called, so I'm not 100 percent sure where I'm going wrong!

craigcoles commented 5 years ago

@tjhowe I am currently trying to implement the exact same thing for Android.

I am receiving/seeing the push notifications in Android (regardless of whether the app is open or closed). I am just not seeing any events happening in the JS from Firebase.

android/app/src/main/java/com/app/PushProvidersHandler.java

package com.app;

import io.invertase.firebase.messaging.RNFirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import com.mixpanel.android.mpmetrics.MixpanelFCMMessagingService;
import android.util.Log;

public class PushProvidersHandler extends RNFirebaseMessagingService {
    private static final String TAG = "PushProviderService";

    @Override
    public void onNewToken(String s) {
        super.onNewToken(s);

        MixpanelFCMMessagingService.addToken(s);
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);

        if (remoteMessage.getData().containsKey("mp_message")) {
            MixpanelFCMMessagingService.showPushNotification(getApplicationContext(), remoteMessage.toIntent());
        }
    }
}

android/app/src/main/AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.app">

    ...

    <application ...>
        <meta-data android:name="com.mixpanel.android.MPConfig.NotificationChannelId"
            android:value="app-notifications" />

        <meta-data android:name="com.mixpanel.android.MPConfig.NotificationChannelName"
            android:value="App Notifications" />

        <meta-data android:name="com.mixpanel.android.MPConfig.NotificationChannelImportance"
            android:value="4" />

        <service android:name=".PushProvidersHandler" android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>

        ...

    </application>

</manifest>

Have you made any progress?

declanelcocks commented 4 years ago

@tjhowe @craigcoles did you ever solve this one?

craigcoles commented 4 years ago

@declanelcocks Unfortunately, I never got much further than what I posted before. The problem I found is the payload of the notification. Mixpanel sends a very custom payload which makes things trickier.

declanelcocks commented 4 years ago

@craigcoles yeah...I can never get Firebase to pick up the notification in the app, it's a pain as I can see the payload is there too when debugging the Java side.