Closed mshibl closed 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?
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.
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.
Currently experiencing this same issue. It still requires attention.
React Native 0.59.9 React Native Firebase ^5.3.0
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.
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:
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!
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
@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:
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.
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!
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!
Issue
I'm having an issue where I cannot get neither
setUserProperty
norsetUserProperties
to work -- even though other methods liketrackEvent
andsetCurrentScreen
work well. I'm having this issue on Android.here's a simple example of my code that's not working:
Project Files
Android
android/build.gradle
:android/app/build.gradle
:android/settings.gradle
:MainApplication.java
:AndroidManifest.xml
:Environment
Android API 28
mac seira
N/A
N/A
Android Studio 3.2.1
React Native
version:0.55.4
React Native Firebase
library version:5.1.1
Firebase
module(s) you're using that has the issue:TypeScript
?N/A
ExpoKit
?ExpoKit
N/A
Think
react-native-firebase
is great? Please consider supporting the project with any of the below:React Native Firebase
andInvertase
on Twitter