-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Description
Issue
When adding utm campaign attributes to a dynamic link they are not registered in Firebase Analytics.
With debug mode enabled I can see the dynamic_link_first_open events rolling in, with campaign attribution:
With debug mode disabled the campaign attribution does not show up in the Firebase -> Analytics -> Conversions or in Google Analytics. I waited a few days to make sure, I also marked dynamic_link_first_open as a conversion event. The events do exists in the Analytics Database. Screenshot from BigQuery:
When I add the campaign details manually with logCampaignDetails the the campaign attribution is showing up in Firebase and Analytics. Am I missing something should I be logging the campaign attribution myself? I have now way to get the utm params from the dynamic link as getInitialLink and onLink only returns app/deeplink and not any details of the dynamic link (separate issue?).
I tested mostly on IOS but a short test on Android gave the same result.
Project Files
Javascript
Click To Expand
Dynamic link handling:
import React from 'react';
import {navigateToDeeplink} from 'lib/utils/deeplink';
import dynamicLinks from '@react-native-firebase/dynamic-links';
import analytics from '@react-native-firebase/analytics';
export default class RootNavigator extends React.Component {
componentDidMount() {
analytics(); // Init analytics before dynamic links
// Unquoting this make campaign tracking work
// But I have no way to get them from the dynamic link params
// A hacky solution could be adding them to the deeplink.
// analytics().logCampaignDetails({
// source: 'utmTestSource',
// campaign: 'utmTestCampaign',
// medium: 'utmTestMedium',
// });
this.handleDeepLinks();
this.firDynamicLinksUnsubscribe = dynamicLinks().onLink(
this.handleDynamicLink,
);
dynamicLinks()
.getInitialLink()
.then(this.handleDynamicLink);
}
handleDynamicLink = async link => {
console.log('#### handle firebase dynamic link:');
console.log(link);
console.log('resolve dynamic link');
if (link && link.url) {
console.log(link.url);
navigateToDeeplink(link.url);
}
};
componentWillUnmount() {
this.firDynamicLinksUnsubscribe();
}
render() {
return null
}
}
package.json
:
{
"name": "--",
"version": "0.119",
"build": 72,
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest",
"test:watch": "jest --watch",
"postinstall": "./postinstall.sh"
},
"dependencies": {
"@react-native-community/async-storage": "^1.6.1",
"@react-native-community/google-signin": "^3.0.4",
"@react-native-community/netinfo": "^4.7.0",
"@react-native-firebase/analytics": "^7.6.7",
"@react-native-firebase/app": "^8.4.5",
"@react-native-firebase/crashlytics": "^8.4.9",
"@react-native-firebase/dynamic-links": "^7.5.10",
"@react-native-firebase/perf": "^7.4.8",
"axios": "^0.18.0",
"axios-mock-adapter": "^1.15.0",
"color-string": "^1.5.3",
"events": "^3.0.0",
"i18n-js": "^3.0.11",
"immutable": "^3.8.2",
"js-sha1": "^0.6.0",
"jsx-control-statements": "^3.2.8",
"lodash": "^4.17.11",
"lottie-ios": "3.0.3",
"lottie-react-native": "^3.1.0",
"parse-duration": "^0.1.1",
"prop-types": "^15.6.2",
"react": "16.11.0",
"react-native": "0.62.2",
"react-native-actionsheet": "^2.4.2",
"react-native-app-auth": "^5.1.3",
"react-native-background-color": "^0.0.8",
"react-native-background-timer": "^2.1.1",
"react-native-barcode-builder": "^2.0.0",
"react-native-blur": "^3.2.2",
"react-native-camera": "^3.3.0",
"react-native-circular-progress": "^1.0.1",
"react-native-date-picker": "^2.7.3",
"react-native-device-info": "^5.2.1",
"react-native-extra-dimensions-android": "^1.2.5",
"react-native-fast-image": "^8.3.2",
"react-native-gesture-handler": "^1.5.0",
"react-native-image-picker": "^0.27.1",
"react-native-keyboard-aware-scroll-view": "^0.9.1",
"react-native-keychain": "^4.0.5",
"react-native-languages": "^3.0.0",
"react-native-qrcode-svg": "^5.1.1",
"react-native-reanimated": "^1.3.1",
"react-native-render-html": "^3.10.0",
"react-native-restart": "^0.0.7",
"react-native-screens": "^2.0.0-alpha.6",
"react-native-splash-screen": "^3.2.0",
"react-native-startup-time": "^1.3.0",
"react-native-status-bar-height": "^2.1.0",
"react-native-svg": "9.3.7",
"react-native-system-setting": "^1.7.3",
"react-native-vector-icons": "^6.6.0",
"react-native-version-number": "0.3.4",
"react-native-webview": "^8.0.3",
"react-navigation": "^4.0.10",
"react-navigation-drawer": "^2.3.3",
"react-navigation-stack": "^1.10.3",
"react-redux": "^5.0.7",
"redux": "^4.0.0",
"redux-actions": "^2.6.1",
"redux-form": "^7.4.2",
"striptags": "^3.1.1",
"url-parse": "^1.4.7"
},
"devDependencies": {
"@babel/cli": "^7.2.3",
"@babel/core": "^7.6.2",
"@babel/runtime": "^7.6.2",
"@react-native-community/eslint-config": "^0.0.7",
"babel-jest": "24.9.0",
"babel-plugin-jsx-control-statements": "^3.2.8",
"babel-plugin-module-resolver": "^3.1.1",
"eslint": "^6.5.1",
"eslint-config-standard": "^12.0.0",
"eslint-config-standard-react": "^7.0.2",
"eslint-import-resolver-babel-module": "5.0.0-beta.1",
"eslint-plugin-detox": "^1.0.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jest": "^21.22.0",
"eslint-plugin-jsx-a11y": "^6.1.1",
"eslint-plugin-jsx-control-statements": "^2.2.1",
"eslint-plugin-jsx-max-len": "^1.0.0",
"eslint-plugin-node": "^8.0.1",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-react": "^7.11.1",
"eslint-plugin-react-native": "^3.2.1",
"eslint-plugin-standard": "^4.0.0",
"flipper-plugin-react-native-performance": "^0.5.0",
"fs-extra": "^8.1.0",
"immutablediff": "^0.4.4",
"jest": "24.9.0",
"jetifier": "^1.6.4",
"metro-react-native-babel-preset": "^0.58.0",
"react-devtools": "^3.3.4",
"react-native-flipper": "^0.52.1",
"react-test-renderer": "16.11.0",
"reactotron-react-native": "^5.0.0",
"replace-in-file": "^4.1.3"
}
}
firebase.json
for react-native-firebase v6:
{
"react-native": {
"crashlytics_debug_enabled": true
}
}
iOS
Click To Expand
ios/Podfile
:
- I'm not using Pods
- I'm using Pods and my Podfile looks like:
# Uncomment the next line to define a global platform for your project
platform :ios, '12.0'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
#source 'https://github.com/CocoaPods/Specs.git'
source 'https://cdn.cocoapods.org/'
def flipper_pods()
flipperkit_version = '0.52.1'
pod 'FlipperKit', '~>' + flipperkit_version, :configuration => 'Debug'
pod 'FlipperKit/FlipperKitLayoutPlugin', '~>' + flipperkit_version, :configuration => 'Debug'
pod 'FlipperKit/SKIOSNetworkPlugin', '~>' + flipperkit_version, :configuration => 'Debug'
pod 'FlipperKit/FlipperKitUserDefaultsPlugin', '~>' + flipperkit_version, :configuration => 'Debug'
pod 'FlipperKit/FlipperKitReactPlugin', '~>' + flipperkit_version, :configuration => 'Debug'
end
# Post Install processing for Flipper
def flipper_post_install(installer)
file_name = Dir.glob("*.xcodeproj")[0]
app_project = Xcodeproj::Project.open(file_name)
app_project.native_targets.each do |target|
target.build_configurations.each do |config|
cflags = config.build_settings['OTHER_CFLAGS'] || '$(inherited) '
unless cflags.include? '-DFB_SONARKIT_ENABLED=1'
puts 'Adding -DFB_SONARKIT_ENABLED=1 in OTHER_CFLAGS...'
cflags << '-DFB_SONARKIT_ENABLED=1'
end
config.build_settings['OTHER_CFLAGS'] = cflags
end
app_project.save
end
installer.pods_project.save
end
target 'Project' do
pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
pod 'React', :path => '../node_modules/react-native/'
pod 'React-Core', :path => '../node_modules/react-native/'
pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'
pod 'React-ART', :path => '../node_modules/react-native/Libraries/ART'
pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon"
pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga', :modular_headers => true
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
pod 'GoogleSignIn', '~> 5.0.2'
use_native_modules!
pod 'notificare-push-lib-react-native', :path => '../node_modules/notificare-push-lib-react-native'
# Enables Flipper.
#
# Note that if you have use_frameworks! enabled, Flipper will not work and
# you should disable these next few lines.
flipper_pods()
pod 'flipper-plugin-react-native-performance', :path => "../node_modules/flipper-plugin-react-native-performance/ios", :configuration => 'Debug'
post_install do |installer|
flipper_post_install(installer)
end
end
target 'notification' do
pod 'notificare-push-lib', '2.3.2'
end
AppDelegate.m
:
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <Firebase.h>
#import "RNSplashScreen.h"
#import "NotificareReactNativeIOS.h"
#import <RNGoogleSignin/RNGoogleSignin.h>
#if DEBUG
#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitLayoutPlugin/SKDescriptorMapper.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <flipper-plugin-react-native-performance/FlipperReactPerformancePlugin.h>
#endif
#endif
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Force Firebase DebugView if FirebaseDebugEnabled set in Info.plist
// see https://stackoverflow.com/questions/43754848/how-to-debug-firebase-on-ios-adhoc-build
NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"Info" ofType:@"plist"];
NSDictionary *plistConfig = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
BOOL isFirebaseDebugEnabled = [[plistConfig valueForKey:@"FirebaseDebugEnabled"] boolValue];
if (isFirebaseDebugEnabled) {
NSLog(@"Firebase debug enabled.");
NSMutableArray *newArguments = [NSMutableArray arrayWithArray:[[NSProcessInfo processInfo] arguments]];
[newArguments addObject:@"-FIRAnalyticsDebugEnabled"];
[newArguments addObject:@"-FIRDebugEnabled"];
[[NSProcessInfo processInfo] setValue:[newArguments copy] forKey:@"arguments"];
}
if ([FIRApp defaultApp] == nil) {
[FIRApp configure];
}
[self initializeFlipper:application];
[NotificareReactNativeIOS launch:launchOptions];
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"Project"
initialProperties:nil];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
#if DEBUG
#ifdef FB_SONARKIT_ENABLED
[[FlipperReactPerformancePlugin sharedInstance] setBridge:bridge];
#endif
#endif
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
[RNSplashScreen show];
return YES;
}
- (void) initializeFlipper:(UIApplication *)application {
#if DEBUG
#ifdef FB_SONARKIT_ENABLED
FlipperClient *client = [FlipperClient sharedClient];
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
[client addPlugin: [[FlipperKitLayoutPlugin alloc] initWithRootNode: application withDescriptorMapper: layoutDescriptorMapper]];
[client addPlugin: [[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
[client addPlugin: [FlipperReactPerformancePlugin sharedInstance]];
[client addPlugin: [FlipperKitReactPlugin new]];
[client addPlugin: [[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
[client start];
#endif
#endif
}
- (void)application:(UIApplication *)application
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
NSLog(@"didFailToRegisterForRemoteNotificationsWithError %@", error);
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(nonnull NSData *)deviceToken {
[NotificareReactNativeIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo
fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler {
[
NotificareReactNativeIOS
didReceiveRemoteNotification:userInfo
completionHandler:^(id _Nullable response, NSError * _Nullable error) {
if (!error) {
completionHandler(UIBackgroundFetchResultNewData);
} else {
completionHandler(UIBackgroundFetchResultNoData);
}
}
];
}
- (void)application:(UIApplication *)application
handleActionWithIdentifier:(nullable NSString *)identifier
forRemoteNotification:(nonnull NSDictionary *)userInfo
withResponseInfo:(nonnull NSDictionary *)responseInfo
completionHandler:(nonnull void (^)())completionHandler
{
[
[NotificarePushLib shared]
handleActionWithIdentifier:identifier
forRemoteNotification:userInfo
withResponseInfo:responseInfo
completionHandler:^(id _Nullable response, NSError * _Nullable error)
{
completionHandler();
}
];
}
// Deep Link was executed when your app was inactive
- (void)notificarePushLib:(NotificarePushLib *)library
didReceiveLaunchURL:(NSURL *)launchURL {
[NotificareReactNativeIOS handleOpenURL:launchURL withOptions:nil];
}
@end
Android
Click To Expand
Have you converted to AndroidX?
- my application is an AndroidX application?
- I am using
android/gradle.settings
jetifier=true
for Android compatibility? - I am using the NPM package
jetifier
for react-native compatibility?
android/build.gradle
:
apply plugin: "com.android.application"
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'com.google.firebase.firebase-perf'
import com.android.build.OutputFile
/**
* 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. If none specified and
* // "index.android.js" exists, it will be used. Otherwise "index.js" is
* // default. Can be overridden with ENTRY_FILE environment variable.
* entryFile: "index.android.js",
*
* // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format
* bundleCommand: "ram-bundle",
*
* // 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 = [
enableHermes: true, // clean and rebuild if changing
]
apply from: "../../node_modules/react-native/react.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
/**
* The preferred build flavor of JavaScriptCore.
*
* For example, to use the international variant, you can use:
* `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
*
* The international variant includes ICU i18n library and necessary data
* allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
* give correct results when using with locales other than en-US. Note that
* this variant is about 6MiB larger per architecture than default.
*/
def jscFlavor = 'org.webkit:android-jsc:+'
/**
* Whether to enable the Hermes VM.
*
* This should be set on project.ext.react and mirrored here. If it is not set
* on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
* and the benefits of using Hermes will therefore be sharply reduced.
*/
def enableHermes = project.ext.react.get("enableHermes", false);
// Create a variable called keystorePropertiesFile, and initialize it to your
// keystore.properties file, in the rootProject folder.
def buildVarsFile = rootProject.file("build.properties")
// Initialize a new Properties() object called keystoreProperties.
def buildVars = new Properties()
// Load your keystore.properties file into the keystoreProperties object.
buildVars.load(new FileInputStream(buildVarsFile))
android {
compileSdkVersion rootProject.ext.compileSdkVersion
lintOptions {
checkReleaseBuilds false
// Or, if you prefer, you can continue to check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId buildVars['applicationId']
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
missingDimensionStrategy 'react-native-camera', 'general'
renderscriptSupportModeEnabled true
multiDexEnabled true
versionCode buildVars['buildNumber'].toInteger()
versionName buildVars['version']
manifestPlaceholders = [
appAuthRedirectScheme: 'auth.' + buildVars['applicationId']
]
}
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}
}
signingConfigs {
debug {
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
// Note: these values are replaced in prepare script
// Script assumes that these vars occur just once in this file
// If you make changes, makin this assumption false, make sure to change prepare script too
release {
storeFile file('release.keystore')
storePassword buildVars['releaseStorePassword']
keyAlias buildVars['releaseKeyAlias']
keyPassword buildVars['releaseKeyPassword']
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://facebook.github.io/react-native/docs/signed-apk-android.
signingConfig signingConfigs.release
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
packagingOptions {
pickFirst "lib/armeabi-v7a/libc++_shared.so"
pickFirst "lib/arm64-v8a/libc++_shared.so"
pickFirst "lib/x86/libc++_shared.so"
pickFirst "lib/x86_64/libc++_shared.so"
}
// 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:
// https://developer.android.com/studio/build/configure-apk-splits.html
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(':notificare-push-lib-react-native')
implementation fileTree(dir: "libs", include: ["*.jar"])
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules
implementation "androidx.multidex:multidex:2.0.0"
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
// For WebP support, including animated WebP
compile 'com.facebook.fresco:animated-webp:2.0.0'
compile 'com.facebook.fresco:webpsupport:2.0.0'
compile 'com.facebook.fresco:animated-gif:2.0.0'
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
}
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}
if (enableHermes) {
def hermesPath = "../../node_modules/hermes-engine/android/";
debugImplementation files(hermesPath + "hermes-debug.aar")
releaseImplementation files(hermesPath + "hermes-release.aar")
} else {
implementation jscFlavor
}
}
// 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 from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
android/app/build.gradle
:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
buildToolsVersion = "29.0.2"
minSdkVersion = 21
compileSdkVersion = 29
targetSdkVersion = 29
supportLibVersion = "28.0.0"
googlePlayServicesVersion = "12.0.1"
googlePlayServicesAuthVersion = "16.0.1"
}
repositories {
google()
maven {
url 'https://maven.google.com/'
name 'Google'
}
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.2'
classpath 'com.google.gms:google-services:4.3.3'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.2.0'
classpath 'com.google.firebase:perf-plugin:1.3.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
mavenLocal()
maven {
url 'https://www.jitpack.io'
}
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url("$rootDir/../node_modules/react-native/android")
}
maven {
// Android JSC is installed from npm
url("$rootDir/../node_modules/jsc-android/dist")
}
maven {
url "https://github.com/Notificare/notificare-mvn-repo/raw/master/releases"
}
google()
jcenter()
}
}
// got error with react-native-background-color
// Adding this solved issue
// https://stackoverflow.com/questions/50574492/react-native-error-resource-androidstyle-textappearance-material-widget-butto
subprojects {
afterEvaluate {project ->
// force libs to use recent buildtools
if (project.hasProperty("android")) {
android {
compileSdkVersion = 29 // change to match your desired version
buildToolsVersion = "29.0.2" // ....
}
}
}
}
android/settings.gradle
:
rootProject.name = 'Project'
include ':notificare-push-lib-react-native'
project(':notificare-push-lib-react-native').projectDir = new File(rootProject.projectDir, '../node_modules/notificare-push-lib-react-native/android')
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app'
MainApplication.java
:
package nl.project.whitelabel;
import android.app.Application;
import android.content.Context;
import androidx.multidex.MultiDexApplication;
import android.webkit.WebView;
// import re.notifica.reactnative.NotificarePackage;
import re.notifica.reactnative.NotificareReceiver;
import re.notifica.Notificare;
import com.airbnb.android.react.lottie.LottiePackage;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
public class MainApplication extends MultiDexApplication implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
packages.add(new LottiePackage());
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
Notificare.shared().setDebugLogging(BuildConfig.DEBUG);
Notificare.shared().launch(this);
Notificare.shared().createDefaultChannel();
Notificare.shared().setIntentReceiver(NotificareReceiver.class);
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
// Enable debugging of webview using in chrome://inspect
WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG);
}
/**
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
*
* @param context
* @param reactInstanceManager
*/
private static void initializeFlipper(
Context context, ReactInstanceManager reactInstanceManager) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("nl.project.whitelabel.ReactNativeFlipper");
aClass
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
.invoke(null, context, reactInstanceManager);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
AndroidManifest.xml
:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="nl.project.whitelabel"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="auto"
>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<uses-permission android:name="android.permission.CAMERA" />
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:largeHeap="true"
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|uiMode"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize">
<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>
<action android:name="re.notifica.intent.action.NotificationOpened" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:label="filter_react_native">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="${applicationId}" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<activity
android:theme="@style/Theme.Transparent"
android:name="re.notifica.ui.NotificationActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:hardwareAccelerated="true"/>
<activity
android:name="re.notifica.ui.PassbookActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:hardwareAccelerated="true">
<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:host="push.notifica.re"
android:pathPrefix="@string/notificare_app_id"
android:scheme="https" />
</intent-filter>
</activity>
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="@string/facebook_app_id" />
</application>
</manifest>
Environment
Click To Expand
react-native info
output:
System:
OS: macOS 10.15.6
CPU: (8) x64 Intel(R) Core(TM) i5-8279U CPU @ 2.40GHz
Memory: 348.67 MB / 16.00 GB
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 10.16.3 - ~/.nvm/versions/node/v10.16.3/bin/node
Yarn: 1.17.3 - /usr/local/bin/yarn
npm: 6.9.0 - ~/.nvm/versions/node/v10.16.3/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.9.3 - /Users/bobsmits/.rbenv/shims/pod
SDKs:
iOS SDK:
Platforms: iOS 14.2, DriverKit 20.0, macOS 11.0, tvOS 14.2, watchOS 7.1
Android SDK:
API Levels: 28, 29
Build Tools: 28.0.3, 29.0.2
System Images: android-19 | Google APIs Intel x86 Atom, android-22 | Google APIs Intel x86 Atom_64, android-29 | Google Play Intel x86 Atom
Android NDK: Not Found
IDEs:
Android Studio: 3.5 AI-191.8026.42.35.5977832
Xcode: 12.2/12B45b - /usr/bin/xcodebuild
Languages:
Java: 1.8.0_222 - /usr/bin/javac
Python: 2.7.16 - /usr/bin/python
npmPackages:
@react-native-community/cli: Not Found
react: 16.11.0 => 16.11.0
react-native: 0.62.2 => 0.62.2
react-native-macos: Not Found
npmGlobalPackages:
*react-native*: Not Found
- Platform that you're experiencing the issue on:
- iOS
- Android
- iOS but have not tested behavior on Android
- [] Android but have not tested behavior on iOS
- Both I tested mostly on IOS but a short test on Android gave the same result.
react-native-firebase
version you're using that has this issue:8.4.5
Firebase
module(s) you're using that has the issue:dynamic-links, analytics
- Are you using
TypeScript
?N
&VERSION
- 👉 Check out
React Native Firebase
andInvertase
on Twitter for updates on the library.