invertase / react-native-firebase

🔥 A well-tested feature-rich modular Firebase implementation for React Native. Supports both iOS & Android platforms for all Firebase services.
https://rnfirebase.io
Other
11.7k stars 2.21k forks source link

🔥setUserProperty and setUserProperties methods not working #1743

Closed mshibl closed 5 years ago

mshibl commented 5 years ago

Issue

I'm having an issue where I cannot get neither setUserProperty nor setUserProperties to work -- even though other methods like trackEvent and setCurrentScreen work well. I'm having this issue on Android.

here's a simple example of my code that's not working:

import firebase from "react-native-firebase";
firebase.analytics().setUserProperty("foo", "bar");
firebase.analytics().logEvent("Testing");
firebase.analytics().setCurrentScreen("Test_Screen");

image


Project Files

Android

android/build.gradle:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'
        classpath 'com.google.gms:google-services:4.0.1'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        mavenLocal()
        google() 
        jcenter()
        maven { url 'https://maven.google.com' } 
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
        maven {
            url 'https://maven.google.com/'
            name 'Google'
        }        
    }
}

android/app/build.gradle:

apply plugin: "com.android.application"

import com.android.build.OutputFile

project.ext.react = [
    entryFile: "index.js"
]

apply from: "../../node_modules/react-native/react.gradle"

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.2"

    defaultConfig {
        applicationId *************
        minSdkVersion 16
        targetSdkVersion 26
        versionCode *************
        versionName *************
        multiDexEnabled true
        ndk {
            abiFilters "armeabi-v7a", "x86"
        }
    }
    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86"
        }
    }
    buildTypes {
        release {
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
            signingConfig signingConfigs.release
        }
    }

    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def versionCodes = ["armeabi-v7a":1, "x86":2]
            def abi = output.getFilter(OutputFile.ABI)
            if (abi != null) {  // null for the universal-debug, universal-release variants
                output.versionCodeOverride =
                        versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
            }
        }
    }
}

dependencies {
    implementation project(':react-native-firebase')
    implementation "com.facebook.react:react-native:+"  // From node_modules
    implementation "com.android.support:appcompat-v7:23.0.1"
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "com.google.android.gms:play-services-base:16.0.1"
    implementation "com.google.firebase:firebase-core:16.0.4"    
}

// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
    from configurations.compile
    into 'libs'
}

apply plugin: 'com.google.gms.google-services'

android/settings.gradle:

rootProject.name = ******

include ':react-native-firebase'
project(':react-native-firebase').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-firebase/android')

include ':app'

MainApplication.java:

package **********;

import android.app.Application;

import io.invertase.firebase.RNFirebasePackage;
import io.invertase.firebase.RNFirebasePackage;
import io.invertase.firebase.analytics.RNFirebaseAnalyticsPackage;

import java.util.Arrays;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
            new RNFirebaseAnalyticsPackage(),
            new RNFirebasePackage(),
      );
    }

    @Override
    protected String getJSMainModuleName() {
      return "index";
    }
  };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
  }
}

AndroidManifest.xml:

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

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />

    <application
      android:name=".MainApplication"
      android:label="@string/app_name"
      android:icon="@mipmap/ic_launcher"
      android:allowBackup="false"
      android:theme="@style/AppTheme">
      <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
        android:windowSoftInputMode="adjustResize"
        android:launchMode="singleTask">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
            <action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
        </intent-filter>
        <intent-filter android:label="filter_third_party_auth">
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data
                android:scheme="*****"
                android:host="*****" />
        </intent-filter>
      </activity>
      <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
    </application>
</manifest>

Environment


Think react-native-firebase is great? Please consider supporting the project with any of the below:

mshibl commented 5 years ago

Maybe as a temporary workaround -- is there any other way (other than using setUserProperty) to set a parameter or a unique identifier in firebase that can be used later to filter analytics data?

appli-intramuros commented 5 years ago

Hello guys ! I (probably) found the root cause of this issue !!

Explanation: Few days ago, I have implemented anonymous firebase authentication:

firebase.auth().signInAnonymously().then(() => {
        const id = firebase.auth().currentUser.uid
        console.log('User successfully authenticated with userID: ' + id)
})

And the issue began to occur: The user property was never set/updated by calling firebase.analytics().setUserProperty('key', 'value')

Why ? Because when the user authenticates with firebase, a new userID is set (new current user created). So, If you want to set/update a user property for the current user with setUserProperty() method, you need first to update the userID right after successfully authentication by calling firebase.analytics().setUserId(id)

What I did:

firebase.auth().signInAnonymously().then(() => {
        const id = firebase.auth().currentUser.uid
        firebase.analytics().setUserId(id)    <------ ADD THIS LINE
        console.log('User successfully authenticated with userID: ' + id)
})

To sum up, as firebase authentication generates a new current userID you have to refresh the userID calling firebase.analytics().setUserId(id)

Hope it can help !

**** UPDATE **** It seems that the error occurs again .... randomly .... So the issue is not fixed for me .... Keep investigating.

stale[bot] commented 5 years ago

Hello 👋, to help manage issues we automatically close stale issues. This issue has been automatically marked as stale because it has not had activity for quite some time. Has this issue been fixed, or does it still require the community's attention?

This issue will be closed in 15 days if no further activity occurs. Thank you for your contributions.

MLDimitry commented 5 years ago

Currently experiencing this same issue. It still requires attention.

React Native 0.59.9 React Native Firebase ^5.3.0

mikehardy commented 5 years ago

Actually @MLDimitry I think this goes the other way I can't reproduce and I'm using this in production now. Just checked. I believe the previous comment about user linking / anon auth is probably right.

Incidentally, "^5.3.0" is not a version it's a range. I have no idea what version you are on :-). That said, this code did not change in the 5.3.x range

If you can post a reproduction and you are certain you are handling auth to logged in transition correctly then maybe there's an issue, but it works for me with logged in users.

MLDimitry commented 5 years ago

Edit: Could it be my Google Play Services SDK being <16.1.0 maybe? Just saw that version requirement on 5.x.x Github branch page.

Edit 2: I'm not using Firebase auth at all. Only attempting to use Firebase Messaging and Firebase analytics to set up audiences for messaging.

Hi @mikehardy thanks for a response. I have been tearing my hear out trying to get this to work in my app and have had no luck getting any of the analytics to even register on Firebase console. I was about to scrap my work with RN Firebase, after seeing this ticket, and attempt to DIY it myself but if you believe this works, maybe a fruitful discussion can solve my problems. It's very likely I just have a version mismatch somewhere and someone more experienced with the library could help.

Here's some details:

package.json:

{
  "name": "KTNRYMS",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest",
    "lint": "eslint ./",
    "lint-fix": "yarn lint --fix",
    "appium": "appium",
    "appium:doctor": "appium-doctor",
    "android": "react-native run-android",
    "android:start": "$ANDROID_SDK/emulator/emulator -avd Nexus8.1",
    "android:adbReverse": "adb reverse tcp:5000 tcp:5000"
  },
  "dependencies": {
    "@react-native-community/netinfo": "^3.1.0",
    "apollo-cache-inmemory": "^1.6.0",
    "apollo-cache-persist": "^0.1.1",
    "apollo-client": "^2.6.0",
    "apollo-link": "^1.2.11",
    "apollo-link-context": "^1.0.17",
    "apollo-link-error": "^1.1.10",
    "apollo-link-rest": "^0.7.3",
    "appcenter": "1.12.2",
    "appcenter-analytics": "1.12.2",
    "appcenter-crashes": "1.12.2",
    "base-64": "^0.1.0",
    "graphql": "^14.0.2",
    "graphql-anywhere": "^4.2.2",
    "graphql-tag": "^2.10.0",
    "prop-types": "^15.6.2",
    "ramda": "^0.26.1",
    "react": "16.8.3",
    "react-apollo": "^2.5.6",
    "react-native": "0.59.9",
    "react-native-config": "^0.11.6",
    "react-native-device-info": "^0.29.1",
    "react-native-draggable-flatlist": "^1.1.7",
    "react-native-firebase": "^5.3.1",
    "react-native-gesture-handler": "^1.0.9",
    "react-native-keyboard-aware-scroll-view": "^0.8.0",
    "react-native-paper": "^2.6.1",
    "react-native-push-notification": "^3.1.2",
    "react-native-sentry": "^0.43.1",
    "react-native-vector-icons": "^6.1.0",
    "react-navigation": "^3.11.0",
    "react-navigation-tabs": "^1.0.2",
    "reactotron-react-native": "^2.1.0",
    "styled-components": "^4.1.3"
  },
  "devDependencies": {
    "@babel/core": "^7.4.5",
    "@babel/runtime": "^7.4.5",
    "@types/jest": "^23.3.10",
    "babel-core": "^7.0.0-bridge.0",
    "babel-eslint": "^10.0.1",
    "babel-jest": "^24.8.0",
    "eslint-config-airbnb": "^17.1.0",
    "eslint-config-react-native": "^4.0.0",
    "eslint-config-standard": "^12.0.0",
    "eslint-plugin-jest": "^22.1.2",
    "eslint-plugin-jsx-a11y": "^6.1.2",
    "eslint-plugin-node": "^8.0.0",
    "eslint-plugin-promise": "^4.0.1",
    "eslint-plugin-react-native": "^3.5.0",
    "eslint-plugin-standard": "^4.0.0",
    "jest": "24.8.0",
    "metro-react-native-babel-preset": "0.54.1",
    "node-fetch": "^2.6.0",
    "prettier": "^1.15.3",
    "react-native-testing-library": "^1.4.2",
    "react-test-renderer": "16.8.3",
    "standard": "^12.0.1",
    "wd": "^1.11.1"
  },
  "standard": {
    "parser": "babel-eslint",
    "env": [
      "jest",
      "es6",
      "browser"
    ]
  },
  "jest": {
    "preset": "react-native",
    "setupTestFrameworkScriptFile": "./jest-setup.js"
  },
  "rnpm": {
    "assets": [
      "./src/assets/fonts"
    ]
  }
}

android/build.gradle:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext {
        buildToolsVersion = "28.0.3"
        minSdkVersion = 16
        compileSdkVersion = 28
        targetSdkVersion = 28
        supportLibVersion = "28.0.0"
    }
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:3.4.0")
        classpath 'com.google.gms:google-services:4.2.0'
        classpath 'com.google.firebase:firebase-plugins:1.1.5'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        mavenLocal()
        google()
        jcenter()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
    }
    configurations.all {
        resolutionStrategy.force "com.android.support:support-v4:27.1.1"
    }
}

android/app/build.gradle:

apply plugin: "com.android.application"
apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"

import com.android.build.OutputFile
import groovy.json.JsonSlurper

def getNpmVersion() {
  def inputFile = new File("../package.json")
  def packageJson = new JsonSlurper().parseText(inputFile.text)
  def buildEnv = System.getenv("BUILD_ENV")

  return packageJson["version"] + (buildEnv ? buildEnv : "")
}

def getGitVersion() {
  def buildCount = System.getenv("BUILD_COUNT")

  return buildCount ? buildCount.toInteger() : 1
}

/**
 * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
 * and bundleReleaseJsAndAssets).
 * These basically call `react-native bundle` with the correct arguments during the Android build
 * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
 * bundle directly from the development server. Below you can see all the possible configurations
 * and their defaults. If you decide to add a configuration block, make sure to add it before the
 * `apply from: "../../node_modules/react-native/react.gradle"` line.
 *
 * project.ext.react = [
 *   // the name of the generated asset file containing your JS bundle
 *   bundleAssetName: "index.android.bundle",
 *
 *   // the entry file for bundle generation
 *   entryFile: "index.android.js",
 *
 *   // whether to bundle JS and assets in debug mode
 *   bundleInDebug: false,
 *
 *   // whether to bundle JS and assets in release mode
 *   bundleInRelease: true,
 *
 *   // whether to bundle JS and assets in another build variant (if configured).
 *   // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
 *   // The configuration property can be in the following formats
 *   //         'bundleIn${productFlavor}${buildType}'
 *   //         'bundleIn${buildType}'
 *   // bundleInFreeDebug: true,
 *   // bundleInPaidRelease: true,
 *   // bundleInBeta: true,
 *
 *   // whether to disable dev mode in custom build variants (by default only disabled in release)
 *   // for example: to disable dev mode in the staging build type (if configured)
 *   devDisabledInStaging: true,
 *   // The configuration property can be in the following formats
 *   //         'devDisabledIn${productFlavor}${buildType}'
 *   //         'devDisabledIn${buildType}'
 *
 *   // the root of your project, i.e. where "package.json" lives
 *   root: "../../",
 *
 *   // where to put the JS bundle asset in debug mode
 *   jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
 *
 *   // where to put the JS bundle asset in release mode
 *   jsBundleDirRelease: "$buildDir/intermediates/assets/release",
 *
 *   // where to put drawable resources / React Native assets, e.g. the ones you use via
 *   // require('./image.png')), in debug mode
 *   resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
 *
 *   // where to put drawable resources / React Native assets, e.g. the ones you use via
 *   // require('./image.png')), in release mode
 *   resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
 *
 *   // by default the gradle tasks are skipped if none of the JS files or assets change; this means
 *   // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
 *   // date; if you have any other folders that you want to ignore for performance reasons (gradle
 *   // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
 *   // for example, you might want to remove it from here.
 *   inputExcludes: ["android/**", "ios/**"],
 *
 *   // override which node gets called and with what additional arguments
 *   nodeExecutableAndArgs: ["node"],
 *
 *   // supply additional arguments to the packager
 *   extraPackagerArgs: []
 * ]
 */

project.ext.react = [
    entryFile: "index.js"
]

apply from: "../../node_modules/react-native/react.gradle"
apply from: "../../node_modules/react-native-sentry/sentry.gradle"
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"

/**
 * Set this to true to create two separate APKs instead of one:
 *   - An APK that only works on ARM devices
 *   - An APK that only works on x86 devices
 * The advantage is the size of the APK is reduced by about 4MB.
 * Upload all the APKs to the Play Store and people will download
 * the correct one based on the CPU architecture of their device.
 */
def enableSeparateBuildPerCPUArchitecture = false

/**
 * Run Proguard to shrink the Java bytecode in release builds.
 */
def enableProguardInReleaseBuilds = false

def gitVersion = getGitVersion()
def packageVersion = getNpmVersion()

android {
    compileSdkVersion rootProject.ext.compileSdkVersion

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    defaultConfig {
        applicationId "com.ktnryms"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode gitVersion
        versionName packageVersion
    }
    signingConfigs {
        release {
            if (project.hasProperty('KTNRYMS_RELEASE_STORE_FILE')) {
                storeFile file(KTNRYMS_RELEASE_STORE_FILE)
                storePassword KTNRYMS_RELEASE_STORE_PASSWORD
                keyAlias KTNRYMS_RELEASE_KEY_ALIAS
                keyPassword KTNRYMS_RELEASE_KEY_PASSWORD
            }
        }
    }
    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
        }
    }
    buildTypes {
        release {
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
            signingConfig signingConfigs.release
        }
    }
    // applicationVariants are e.g. debug, release
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            // For each separate APK per architecture, set a unique version code as described here:
            // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
            def versionCodes = ["armeabi-v7a":1, "x86":2, "arm64-v8a": 3, "x86_64": 4]
            def abi = output.getFilter(OutputFile.ABI)
            if (abi != null) {  // null for the universal-debug, universal-release variants
                output.versionCodeOverride =
                        versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
            }
        }
    }
}

dependencies {
    implementation project(':react-native-firebase')
    compile project(':react-native-sentry')
    compile project(':@react-native-community_netinfo')
    compile project(':react-native-device-info')
    compile project(':appcenter-crashes')
    compile project(':appcenter-analytics')
    compile project(':appcenter')
    compile project(':react-native-vector-icons')
    compile project(':react-native-push-notification')
    compile project(':react-native-gesture-handler')
    compile project(':react-native-config')
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation project(':react-native-firebase')
    implementation "com.google.android.gms:play-services-base:16.1.0"
    implementation "com.google.firebase:firebase-core:16.0.4"
    implementation "com.google.firebase:firebase-analytics:16.0.4"
    implementation "com.google.firebase:firebase-messaging:17.3.4"
    implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
    implementation "com.facebook.react:react-native:+"  // From node_modules
}

// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
    from configurations.compile
    into 'libs'
}

apply plugin: 'com.google.gms.google-services'

Usage: image

None of these seem to register on my Firebase console. Unless there is some sort of delay but I don't see anything in StreamView or DebugView. Note: this isn't my intended usage, I was testing to see if any of the analytics instance methods worked and didn't seem like any did.

I CAN send notifications to all devices, and they're received. But I am trying to set up audiences by user role so I can send notifications to specific roles. And that is where my issue lies. The analytics instance never seems to get userId, current screen, or user properties. If I try to send a test notification from FB console to a specific role-based audience, it never receives that because it has 0 users registered. I do see the log 'Firebase setup complete' appear in my debug console logs so it doesn't seem like any error is thrown.

Let me know if there's any other files I can provide to help you help me!

mikehardy commented 5 years ago

Interesting - first thoughts are that you're a half year behind on a lot of the versions. I maintain react-native-device-info as well, for instance, and we're on 2.x. For modern gradle I'm not sure if RN0.57 works even, I'd use rn-diff-purge project to get the diffs and apply them up to current (0.59.9), etc

For analytics hits to actually show up quickly, you need to turn on a special mode https://firebase.google.com/docs/analytics/debugview - I have a package.json script that does this for me via adb, but for iOS you have to actually alter code and rebuild.

It's a positive sign that you have cloud messaging working, that's not easy. As for subscriptions etc, I tried this route, and still plan on using it a little but you should read how the audiences work from firebase docs. In a nutshell, you define criteria, then the criteria are pushed down to the device (in firebase libs) and the device decides if it matches then subscribes itself.

If I have understood that correctly, and you combine that chain of events with knowledge of how background on execution works (or completely fails to work reliably, in my experience) then you can imagine that design may not be great vs an explicit subscription while app is in foreground design

But first settle your analytics issue.

I intend to leave this closed though. I know it works. You should open a new issue with your details after an initial attempt with analytics debugging toggled.

You may also like https://github.com/mikehardy/rnfbdemo as it'll get you a sample app in a single command 5 minutes of wall clock time, assuming you copy in your google firebase json/plist. And you could try adding a quick analytics hit in there to test

MLDimitry commented 5 years ago

@mikehardy Gah, looks like I copied the old version of package.json and pasted that instead of my new version. Was looking at git diff view. Yes we definitely have a lot of out of date packages. But React Native is actually 0.59.9 (Following rn-diff-purge update) and React Native Firebase is 5.3.1. I've updated my package.json that was pasted in my above comment with my CURRENT version. Here's a pic of diffs relative to this ticket:

image

I also updated play services to 16.1.0 and I think that may have helped.

And your tip on DebugView was VERY helpful! Didn't realize I needed to activate that via adb shell. My app is android only so I activated it via the adb command and now looks like Firebase actually is receiving my requests! So yes this ticket definitely seems to be working and can be closed. image

So how long from when a user registers a property until they would appear in the audience for Messaging to an audience based on that property with debug mode turned off? For production? Right now I see the user in DebugView but if I try to send a message to my GROUNDSMAN role audience (based on role: GROUNDSMAN property) it says there are 0 users and my app doesn't receive anything (Still receives all device notifications). I'm also not sure what you're talking about with subscriptions...

I'm going to go comb through the docs to learn more about this but if you have any links you think could be helpful to my situation, I would love any more help if you're willing to provide. Either way, thank you so much for pointing me in the right direction on this!

mikehardy commented 5 years ago

there are a few articles on this but in general I had to read through all the blog entries. https://firebase.googleblog.com/2019/01/a-crash-course-in-using-new-audiences.html

Highly recommend the blog

What I meant by subscriptions is that I understand messaging to be directed either to everyone, to specific audiences (either by device parameters are by some analytics things), by FCM tokens, or by topic. Everyone is easy, specific audiences is easy if it's something "solid" (like platform) but to me it is iffy it is is driven by an analytics audience for the reasons mentioned above (latency etc). Maybe it's amazing at scale but my app is new and small so for me audiences basically don't work. FCM token is obvious and easy, but the subscription thing is to make topics and have the apps subscribe to the topics, then message the topics. That seems deterministic to me vs my fluffy / failing experience with audiences so I thought it worth mentioning

Glad debug view worked, good luck!