Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[🔥][🐛] [Android] App crashing on ConcurrentModificationException (ReactNativeFirebaseAuthModule) #6798

Closed
2 of 10 tasks
jianhui-chan opened this issue Dec 23, 2022 · 19 comments · Fixed by #6848
Closed
2 of 10 tasks
Labels
impact: crash Behaviour causing app to crash. platform: android plugin: authentication Firebase Authentication type: bug New bug report

Comments

@jianhui-chan
Copy link

Issue

Hello,

We've been seeing reports in Sentry that many of our Android users are experiencing crashes due to a ConcurrentModificationException happening when the onIdTokenChanged listener is being registered.
We have not been able to replicate it locally so we're not exactly sure how this is happening as well.

Here is the stack trace for the error:

java.util.ConcurrentModificationException: null
    at java.util.ArrayList$Itr.next(ArrayList.java:860)
    at io.invertase.firebase.auth.ReactNativeFirebaseAuthModule.convertProviderData(ReactNativeFirebaseAuthModule.java:1768)
    at io.invertase.firebase.auth.ReactNativeFirebaseAuthModule.firebaseUserToMap(ReactNativeFirebaseAuthModule.java:1869)
    at io.invertase.firebase.auth.ReactNativeFirebaseAuthModule.lambda$addIdTokenListener$1$io-invertase-firebase-auth-ReactNativeFirebaseAuthModule(ReactNativeFirebaseAuthModule.java:191)
    at io.invertase.firebase.auth.ReactNativeFirebaseAuthModule$$ExternalSyntheticLambda26.onIdTokenChanged
    at com.google.firebase.auth.zzl.run(com.google.firebase:firebase-auth@@21.0.8:4)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:192)
    at android.app.ActivityThread.main(ActivityThread.java:6711)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:826)

The behaviour we are observing (through Sentry) is as follows:

  1. User opens the app
  2. App gets foregrounded
  3. App crashes with ConcurrentModificationException

Here is how we are registering the listener:
In componentDidMount, we are checking (via remote config) if firebase login is enabled and then registering the listener if it is enabled.

    const firebaseLoginEnabledFlag = remoteConfig().getValue(
      'firebase_login_enabled',
    );
    console.log('firebase_login_enabled', firebaseLoginEnabledFlag);
    const firebaseLoginEnabled = firebaseLoginEnabledFlag.asBoolean();
    updateGlobal({firebaseLoginEnabled});

    // Register Firebase token change listener
    if (firebaseLoginEnabled) {
      if (!this.unsubscribe) {
        this.unsubscribe = auth().onIdTokenChanged(
          this.handleFirebaseTokenUpdate,
        );
      }
    }

Project Files

Javascript

Click To Expand

package.json:

{
  "name": "workmate",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "android": "react-native run-android --variant=devDebug --appIdSuffix=develop",
    "android-demo": "react-native run-android --variant=demoDebug --appIdSuffix=demo",
    "android-prod": "react-native run-android --variant=prodDebug",
    "ios": "react-native run-ios --scheme=WorkmateDev",
    "ios-demo": "react-native run-ios --scheme=WorkmateDemo",
    "ios-prod": "react-native run-ios --scheme=Workmate",
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint .",
    "ts-migrate": "ts-migrate"
  },
  "dependencies": {
    "@datadog/mobile-react-native": "^1.0.0-rc9",
    "@datadog/mobile-react-navigation": "^1.0.0-rc9",
    "@invertase/react-native-apple-authentication": "^2.1.5",
    "@react-native-async-storage/async-storage": "^1.17.7",
    "@react-native-clipboard/clipboard": "^1.9.0",
    "@react-native-community/checkbox": "^0.5.12",
    "@react-native-community/datetimepicker": "^6.1.4",
    "@react-native-community/masked-view": "^0.1.6",
    "@react-native-community/netinfo": "^5.8.0",
    "@react-native-community/push-notification-ios": "^1.10.1",
    "@react-native-firebase/analytics": "^14.11.0",
    "@react-native-firebase/app": "^14.11.0",
    "@react-native-firebase/auth": "^14.11.0",
    "@react-native-firebase/crashlytics": "^14.11.0",
    "@react-native-firebase/in-app-messaging": "^14.11.0",
    "@react-native-firebase/messaging": "^14.11.0",
    "@react-native-firebase/remote-config": "^14.11.0",
    "@react-native-google-signin/google-signin": "^7.0.1",
    "@react-native-picker/picker": "^2.4.2",
    "@react-navigation/bottom-tabs": "^5.11.11",
    "@react-navigation/material-top-tabs": "5.3.15",
    "@react-navigation/native": "^5.9.4",
    "@react-navigation/stack": "^5.14.5",
    "@segment/analytics-react-native": "^2.2.2",
    "@segment/sovran-react-native": "^0.2.8",
    "@sentry/cli": "^1.68.0",
    "@sentry/react-native": "^3.1.0",
    "@stream-io/flat-list-mvcp": "^0.10.1",
    "@twilio/conversations": "^2.1.0",
    "axios": "^0.21.1",
    "axios-auth-refresh": "^3.2.1",
    "axios-retry": "^3.1.9",
    "babel-runtime": "^6.26.0",
    "buffer": "^5.6.0",
    "cdigit": "^3.1.2",
    "eslint-plugin-react": "^7.18.3",
    "events": "^3.1.0",
    "formik": "^2.1.4",
    "graphql": "^16.6.0",
    "graphql-request": "^4.3.0",
    "graphql-tag": "^2.12.6",
    "humps": "^2.0.1",
    "i18next": "^19.3.2",
    "libphonenumber-js": "^1.9.42",
    "lodash": "^4.17.21",
    "moment": "^2.24.0",
    "numeral": "^2.0.6",
    "react": "17.0.2",
    "react-i18next": "^11.3.3",
    "react-native": "0.67.4",
    "react-native-autoheight-webview": "^1.6.1",
    "react-native-background-actions": "^2.6.2",
    "react-native-base64": "0.0.2",
    "react-native-bidirectional-infinite-scroll": "^0.3.3",
    "react-native-bootsplash": "^2.1.0",
    "react-native-branch": "^5.0.1",
    "react-native-camera": "^3.43.6",
    "react-native-code-push": "^7.0.4",
    "react-native-config": "^1.4.5",
    "react-native-confirmation-code-field": "^7.2.0",
    "react-native-country-picker-modal": "^2.0.0",
    "react-native-dash": "0.0.11",
    "react-native-datepicker": "^1.7.2",
    "react-native-device-info": "^8.7.1",
    "react-native-elements": "^1.2.7",
    "react-native-fast-image": "^8.5.11",
    "react-native-fbsdk-next": "7.0.1",
    "react-native-geolocation-service": "^5.2.0",
    "react-native-gesture-handler": "^1.10.3",
    "react-native-get-random-values": "^1.7.0",
    "react-native-html-to-pdf": "^0.12.0",
    "react-native-hyperlink": "0.0.19",
    "react-native-image-picker": "^3.3.2",
    "react-native-image-viewing": "^0.2.1",
    "react-native-keyboard-aware-scroll-view": "0.9.5",
    "react-native-lightbox": "^0.8.1",
    "react-native-linear-gradient": "^2.5.6",
    "react-native-localize": "^1.3.4",
    "react-native-maps": "^1.2.0",
    "react-native-mask-text": "^0.7.0",
    "react-native-mmkv-storage": "^0.7.6",
    "react-native-offline": "^5.8.0",
    "react-native-permissions": "^3.0.5",
    "react-native-picker-select": "^6.5.0",
    "react-native-print": "^0.10.0",
    "react-native-push-notification": "^8.1.1",
    "react-native-qrcode-svg": "^6.0.6",
    "react-native-reanimated": "^2.8.0",
    "react-native-safe-area-context": "^0.7.3",
    "react-native-scalable-image": "^1.0.0",
    "react-native-screens": "^2.0.0-beta.10",
    "react-native-send-intent": "^1.3.0",
    "react-native-signature-capture": "^0.4.12",
    "react-native-svg": "^12.1.1",
    "react-native-tab-view": "^2.16.0",
    "react-native-testing-library": "^1.13.2",
    "react-native-toast-notifications": "^3.1.1",
    "react-native-vector-icons": "^9.2.0",
    "react-native-webview": "^11.6.5",
    "react-query": "^3.34.19",
    "react-redux": "^7.2.0",
    "redux": "^4.0.5",
    "redux-logger": "^3.0.6",
    "redux-persist": "^6.0.0",
    "redux-thunk": "^2.3.0",
    "reselect": "^4.0.0",
    "rn-fetch-blob": "^0.13.0-beta.2",
    "rrule": "^2.6.4",
    "semver-compare": "^1.0.0",
    "twilio-chat": "^5.0.0",
    "use-count-up": "^2.3.1",
    "uuid": "^8.3.2",
    "yup": "^0.28.3"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@babel/runtime": "^7.12.5",
    "@react-native-community/eslint-config": "^2.0.0",
    "@types/jest": "^27.4.0",
    "@types/lodash": "^4.14.180",
    "@types/react": "^17.0.39",
    "@types/react-native": "^0.66.16",
    "@types/react-native-html-to-pdf": "^0.8.1",
    "@types/react-redux": "^7.1.23",
    "@types/react-test-renderer": "^17.0.1",
    "@types/yup": "^0.29.13",
    "@typescript-eslint/eslint-plugin": "^5.12.1",
    "@typescript-eslint/parser": "^5.12.1",
    "babel-eslint": "^10.1.0",
    "babel-jest": "26.6.3",
    "babel-plugin-module-resolver": "^4.1.0",
    "eslint": "7.14.0",
    "eslint-config-prettier": "6.10.0",
    "eslint-import-resolver-node": "^0.3.3",
    "eslint-import-resolver-typescript": "^2.5.0",
    "eslint-plugin-import": "^2.25.4",
    "eslint-plugin-prettier": "3.1.2",
    "fast-csv": "^4.3.6",
    "jest": "^26.6.3",
    "jest-extended": "^0.11.5",
    "metro-react-native-babel-preset": "^0.66.2",
    "prettier": "1.19.1",
    "react-dom": "^17.0.2",
    "react-native-clean-project": "^3.3.0",
    "react-native-codegen": "^0.0.7",
    "react-test-renderer": "17.0.2",
    "ts-migrate": "^0.1.28",
    "typescript": "^4.5.5"
  },
  "jest": {
    "preset": "react-native",
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js",
      "jsx",
      "json",
      "node"
    ],
    "setupFilesAfterEnv": [
      "jest-extended",
      "./jest.setup.js"
    ],
    "transformIgnorePatterns": [
      "node_modules/(?!(@?(react-native|invertase)(-[^/]+)?)/)"
    ],
    "moduleNameMapper": {
      "^@/(.*)$": "<rootDir>/$1"
    }
  }
}

firebase.json for react-native-firebase v6:

{}

iOS

Click To Expand

ios/Podfile:

  • I'm not using Pods
  • I'm using Pods and my Podfile looks like:
  • [ ]
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
platform :ios, '13.0'

def all_pods
  # Pods for Workmate

  permissions_path = '../node_modules/react-native-permissions/ios'

  pod 'Permission-Camera', :path => "#{permissions_path}/Camera"
  pod 'Permission-LocationAlways', :path => "#{permissions_path}/LocationAlways"
  pod 'Permission-LocationWhenInUse', :path => "#{permissions_path}/LocationWhenInUse"
  pod 'Permission-MediaLibrary', :path => "#{permissions_path}/MediaLibrary"
  pod 'Permission-Notifications', :path => "#{permissions_path}/Notifications"
  pod 'Permission-PhotoLibrary', :path => "#{permissions_path}/PhotoLibrary"

  # React Native Maps dependencies
  rn_maps_path = '../node_modules/react-native-maps'
  pod 'react-native-google-maps', :path => rn_maps_path
  pod 'GoogleMaps', '7.0.0'
  pod 'Google-Maps-iOS-Utils'
  pod 'react-native-camera', :path => '../node_modules/react-native-camera'

  pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text', :modular_headers => true
end

def update_deployment_target(installer)
  return if !installer
  project = installer.pods_project
  project_deployment_target = project.build_configurations.first.build_settings['IPHONEOS_DEPLOYMENT_TARGET']
  puts "Make sure all pods deployment target is #{project_deployment_target.green}"
  project.targets.each do |target|
    puts "  #{target.name}".blue
    target.build_configurations.each do |config|
      # https://github.com/facebook/react-native/issues/32496 - Drop armv7 support for building with xcode 13.x.x
      config.build_settings['ARCHS'] = '${ARCHS_STANDARD_64_BIT}'
      old_target = config.build_settings['IPHONEOS_DEPLOYMENT_TARGET']
      new_target = project_deployment_target
      next if old_target == new_target
      puts "    #{config.name}: #{old_target.yellow} -> #{new_target.green}"
      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = new_target
    end
  end
end

target 'Workmate' do
  $FirebaseSDKVersion = '8.9.0'
  all_pods

  config = use_native_modules!
  use_react_native!(
    :path => config[:reactNativePath],
    # to enable hermes on iOS, change `false` to `true` and then install pods
    :hermes_enabled => false
  )
  use_flipper!()

  post_install do |installer|
    react_native_post_install(installer)
    __apply_Xcode_12_5_M1_post_install_workaround(installer)
    update_deployment_target(installer)
    # https://github.com/facebook/react-native/issues/32253
    # Apple Silicon builds require a library path tweak for Swift library discovery or "symbol not found" for swift things
    installer.aggregate_targets.each do |aggregate_target| 
      aggregate_target.user_project.native_targets.each do |target|
        target.build_configurations.each do |config|
          config.build_settings['LIBRARY_SEARCH_PATHS'] = ['$(SDKROOT)/usr/lib/swift', '$(inherited)']
        end
      end
      aggregate_target.user_project.save
    end

    # ...but if you bump iOS deployment target, Flipper barfs again "Time.h:52:17: error: typedef redefinition with different types"
    # We need to make one crude patch to RCT-Folly - set `__IPHONE_10_0` to our iOS target + 1
    # https://github.com/facebook/flipper/issues/834
    `sed -i -e  $'s/__IPHONE_10_0/__IPHONE_12_0/' #{installer.sandbox.root}/RCT-Folly/folly/portability/Time.h`
  end
end

target 'WorkmateDemo' do
  $FirebaseSDKVersion = '8.9.0'
  all_pods
  config = use_native_modules!
  use_react_native!(
    :path => config[:reactNativePath],
    # to enable hermes on iOS, change `false` to `true` and then install pods
    :hermes_enabled => false
  )
  use_flipper!()
end


target 'WorkmateDev' do
  $FirebaseSDKVersion = '8.9.0'
  all_pods
  config = use_native_modules!
  use_react_native!(
    :path => config[:reactNativePath],
    # to enable hermes on iOS, change `false` to `true` and then install pods
    :hermes_enabled => false
  )
  use_flipper!()
end

AppDelegate.m:

#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <RNCPushNotificationIOS.h>
#import <UserNotifications/UserNotifications.h>
#import <Firebase.h>
#import <react-native-branch/RNBranch/RNBranch.h>
#import <GoogleMaps/GoogleMaps.h>
#import "ReactNativeConfig.h"
#import <CodePush/CodePush.h>

#import "RNBootSplash.h"


#if DEBUG
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>
static void InitializeFlipper(UIApplication *application) {
  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:[FlipperKitReactPlugin new]];
  [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
  [client start];
}
#endif

@implementation AppDelegate

// Required to register for notifications
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
  [RNCPushNotificationIOS didRegisterUserNotificationSettings:notificationSettings];
}
// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
  [RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
  [RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
  [RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}
// Required for the localNotification event.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void (^)(void))completionHandler
{
  [RNCPushNotificationIOS didReceiveNotificationResponse:response];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#if DEBUG
  InitializeFlipper(application);
#endif

  NSString *apiUrl = [ReactNativeConfig envFor:@"GOOGLE_API_KEY_IOS"];
  [GMSServices provideAPIKey:apiUrl];
  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"Workmate"
                                            initialProperties:nil];

  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  [RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView]; // <- initialization using the storyboard file name

  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];

  // Define UNUserNotificationCenter
  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
  center.delegate = self;
  if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
  }
  //TODO: Uncomment this line to use the test key instead of the live one.
  // [RNBranch useTestInstance];
  [RNBranch initSessionWithLaunchOptions:launchOptions isReferrable:YES];
  return YES;
}

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
    if (![RNBranch.branch application:app openURL:url options:options]) {
        // do other deep link routing for the Facebook SDK, Pinterest SDK, etc
    }
    return YES;
}

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
    return [RNBranch continueUserActivity:userActivity];
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [CodePush bundleURL];
#endif
}

// Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
  completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}

@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:

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

buildscript {
    ext {
        googlePlayServicesVersion = "17.0.0" // default: "+"
        googlePlayServicesVisionVersion = "19.0.0"
        firebaseVersion = "17.3.4" // default: "+"
        kotlinVersion = "1.6.21"
        buildToolsVersion = "30.0.2"
        minSdkVersion = 21
        compileSdkVersion = 31
        targetSdkVersion = 31
        ndkVersion = "21.4.7075529"
    }
    repositories {
        google()
        mavenCentral()
        maven {
          url 'https://maven.fabric.io/public'
        }
    }
    dependencies {
        classpath 'com.google.gms:google-services:4.3.3'
        classpath 'io.fabric.tools:gradle:1.28.1'

        classpath("com.android.tools.build:gradle:4.2.2")
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        mavenLocal()
        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")
        }

        mavenCentral {
            // We don't want to fetch react-native from Maven Central as there are
            // older versions over there.
            content {
                excludeGroup "com.facebook.react"
            }
        }

        google()
        maven { url 'https://www.jitpack.io' }
    }
    configurations.all {
        resolutionStrategy {
            dependencySubstitution {
                substitute module("com.redmadrobot:input-mask-android:6.0.0") using module('com.github.RedMadRobot:input-mask-android:6.0.0')
                substitute module("org.bouncycastle:bcprov-jdk15on:1.65") using module("org.bouncycastle:bcprov-jdk15to18:1.68")
            }
        }
    }
}

android/app/build.gradle:

apply plugin: "com.android.application"
apply plugin: 'io.fabric'

project.ext.envConfigFiles = [
    dev: ".env.dev",
    demo: ".env.demo",
    prod: ".env.prod",
]

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

crashlytics {
  enableNdk true
}

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"
apply from: "../../node_modules/@sentry/react-native/sentry.gradle"
apply from: "../../node_modules/react-native-code-push/android/codepush.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 that value will be read 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);

/**
 * Architectures to build native code for in debug.
 */
def nativeArchitectures = project.getProperties().get("reactNativeDebugArchitectures")

android {
    compileSdkVersion rootProject.ext.compileSdkVersion

    defaultConfig {
        applicationId "com.helpster.partner"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 99999 // This will be replaced in Bitrise
        versionName "9.9.9" // This will be replaced in Bitrise
        multiDexEnabled true
        resValue "string", "build_config_package", "com.helpster.partner"
        resValue 'string', "CODE_PUSH_APK_BUILD_TIME", String.format("\"%d\"", System.currentTimeMillis())
        missingDimensionStrategy 'react-native-camera', 'general'
    }
    flavorDimensions "default"
    productFlavors {
        dev {
            applicationIdSuffix ".develop"
        }
        demo {
            applicationIdSuffix ".demo"
        }
        prod {
        }
    }
    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
        }
    }
    signingConfigs {
        release {
            if (project.hasProperty('UPLOAD_STORE_FILE')) {
                storeFile file(UPLOAD_STORE_FILE)
                storePassword UPLOAD_STORE_PASSWORD
                keyAlias UPLOAD_KEY_ALIAS
                keyPassword UPLOAD_KEY_PASSWORD
            }
        }
        debug {
            storeFile file('debug.keystore')
            storePassword 'android'
            keyAlias 'androiddebugkey'
            keyPassword 'android'
        }
    }
    buildTypes {
        debug {
            signingConfig signingConfigs.debug
            if (nativeArchitectures) {
                ndk {
                    abiFilters nativeArchitectures.split(',')
                }
            }
        }
        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 fileTree(dir: "libs", include: ["*.jar"])
    //noinspection GradleDynamicVersion
    implementation "com.facebook.react:react-native:+"  // From node_modules
    implementation 'com.android.support:multidex:1.0.3'
    implementation 'androidx.multidex:multidex:2.0.1'
    // For duplicate dependency error https://github.com/firebase/firebase-android-sdk/issues/1575
    implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'

    implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"

    implementation 'com.facebook.android:facebook-android-sdk:latest.release'
    // SingpassWebViewClient
    implementation "io.github.singpass:singpass-webview-client:1.2.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.implementation
    into 'libs'
}

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
apply plugin: 'com.google.gms.google-services'

android/settings.gradle:

include ':react-native-send-intent'
project(':react-native-send-intent').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-send-intent/android')
include ':react-native-camera'
project(':react-native-camera').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-camera/android')
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app', ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')
include ':react-native-html-to-pdf'
project(':react-native-html-to-pdf').projectDir = new File(rootProject.projectDir,'../node_modules/react-native-html-to-pdf/android')

MainApplication.java:

package com.helpster.partner;

import android.app.Application;
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.burnweb.rnsendintent.RNSendIntentPackage;
import org.reactnative.camera.RNCameraPackage;
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;
import androidx.multidex.MultiDexApplication;
import io.branch.rnbranch.RNBranchPackage;
import io.invertase.firebase.app.ReactNativeFirebaseAppPackage;
import io.branch.referral.Branch;
import com.microsoft.codepush.react.CodePush;
import com.ammarahmed.mmkv.RNMMKVJSIModulePackage;
import com.facebook.react.bridge.JSIModulePackage;

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 MyReactNativePackage());
          return packages;
        }

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

        // Override the getJSBundleFile method in order to let
        // the CodePush runtime determine where to get the JS
        // bundle location from on each app start
        @Override
        protected String getJSBundleFile() {
            return CodePush.getJSBundleFile();
        }

        // For react-native-mmkv-storage
        // https://rnmmkv.vercel.app/#/gettingstarted
        @Override
        protected JSIModulePackage getJSIModulePackage() {
          return new RNMMKVJSIModulePackage();
        }
      };

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

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

  /**
   * 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("com.helpster.partner.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" xmlns:tools="http://schemas.android.com/tools" package="com.helpster.partner">

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.CAMERA" />

    <uses-permission android:name="android.permission.VIBRATE"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <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"
                 android:requestLegacyExternalStorage="true"
              > 
              <meta-data 
                android:name="com.google.firebase.messaging.default_notification_icon"
                android:resource="@mipmap/workmate_logo_transparent" />
              <meta-data 
                tools:replace="android:resource"
                android:name="com.google.firebase.messaging.default_notification_color"
                android:resource="@color/brand_green" />
        <!-- Branch init -->
        <meta-data android:name="io.branch.sdk.BranchKey" android:value="@string/BRANCH_KEY"/>

        <activity android:name=".MainActivity" android:launchMode="singleTask" android:label="@string/app_name"
                  android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
                  android:windowSoftInputMode="adjustResize" android:exported="true"/>

        <activity android:name="com.zoontek.rnbootsplash.RNBootSplashActivity" android:theme="@style/BootTheme"
                  android:launchMode="singleTask"  android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>

            <!-- Branch URI Scheme -->
            <intent-filter>
                <data android:scheme="@string/BRANCH_URI_SCHEME"/>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
            </intent-filter>

            <!-- Branch App Links (optional) -->
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:scheme="https" android:host="@string/BRANCH_LINK_DOMAIN"/>
                <data android:scheme="https" android:host="@string/BRANCH_ALTERNATE_LINK_DOMAIN"/>
            </intent-filter>
        </activity>

        <meta-data android:name="com.google.android.geo.API_KEY" android:value="@string/GOOGLE_API_KEY_ANDROID"/>
        <uses-library android:name="org.apache.http.legacy" android:required="false"/>

        <!-- Facebook SDK -->
        <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
        <meta-data android:name="com.facebook.sdk.ClientToken" android:value="@string/facebook_client_token"/>

        <activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
        <service android:name="com.asterinet.react.bgactions.RNBackgroundActionsTask" />

    </application>

    <queries>
        <intent>
            <action android:name="android.intent.action.MAIN" />
        </intent>
    </queries>

</manifest>


Environment

Click To Expand

As mentioned, we've not been able to replicate this locally but this is a list of devices that have been experiencing this issue: image

  • 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
  • react-native-firebase version you're using that has this issue:
    • ^14.11.0
  • Firebase module(s) you're using that has the issue:
    • @react-native-firebase/auth
  • Are you using TypeScript?
    • Y & ^4.5.5


@jianhui-chan jianhui-chan added help: needs-triage Issue needs additional investigation/triaging. type: bug New bug report labels Dec 23, 2022
@mikehardy
Copy link
Collaborator

Hi there, I can look at this a bit later but please respond first and let me know if you still reproduce this on current versions, troubleshooting older versions is inefficient and not something we do in general

@jianhui-chan
Copy link
Author

Thanks for looking into this @mikehardy. We're currently only using 14.11.0 in production but I'll try reproducing this on the current version as well.

@lwts
Copy link

lwts commented Jan 19, 2023

+1 we are also seeing this behavior, we're unable to reproduce it locally but its flaring up on our crashlytics reports, running the latest versions.

Identical behavior as above where a user has just opened the app, user is signed in and then immediately crashes with ConcurrentModificationException.

@svtags
Copy link

svtags commented Jan 19, 2023

+1 were also encountering this error in production. Same error stack. Unfortunately we are unable to replicate it locally but in production it crashes after the splash screen. Here's the error stack in crash reporting tool.

java.util.ConcurrentModificationException: Application crash detected: java.util.ConcurrentModificationException
java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.next(ArrayList.java:860)
	at io.invertase.firebase.auth.ReactNativeFirebaseAuthModule.convertProviderData(ReactNativeFirebaseAuthModule.java:1750)
	at io.invertase.firebase.auth.ReactNativeFirebaseAuthModule.firebaseUserToMap(ReactNativeFirebaseAuthModule.java:1851)
	at io.invertase.firebase.auth.ReactNativeFirebaseAuthModule.lambda$addIdTokenListener$1$ReactNativeFirebaseAuthModule(ReactNativeFirebaseAuthModule.java:191)
	at io.invertase.firebase.auth.-$$Lambda$ReactNativeFirebaseAuthModule$0sGV_gySlJ2impzgzgPA-PRsabI.onIdTokenChanged(Unknown Source:4)
	at com.google.firebase.auth.zzm.run(com.google.firebase:firebase-auth@@21.0.3:4)
	at android.os.Handler.handleCallback(Handler.java:938)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:233)
	at android.os.Looper.loop(Looper.java:344)
	at android.app.ActivityThread.main(ActivityThread.java:8212)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:584)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1034)

@isystem20
Copy link

+1 We are also encountering this error. @jianhui-chan were you able to mitigate the issue on your end?

@jianhui-chan
Copy link
Author

@isystem20 nope, I haven't found a solution for this issue

@lwts
Copy link

lwts commented Jan 20, 2023

We're now seeing this crash hit around 8% of our active users.

@mikehardy
Copy link
Collaborator

No one has confirmed this happens on current stable versions. Someone please confirm this happens with current stable versions.

@lwts
Copy link

lwts commented Jan 20, 2023

Sorry this is happening for us on 16.5.0, RN 0.71.0. Will do another release today with 16.5.1 to see if this has an impact.

@mikehardy
Copy link
Collaborator

@lwts thanks for confirming! 16.5.1 will not have an impact here, nothing in the area that would throw this stack changed. Always excited to have confirmation + stack traces but of course sorry this is happening for folks. I'll take a look

@mikehardy mikehardy added Workflow: Needs Review Pending feedback or review from a maintainer. platform: android plugin: authentication Firebase Authentication impact: crash Behaviour causing app to crash. labels Jan 21, 2023
mikehardy added a commit that referenced this issue Jan 21, 2023
The auth provider data may apparently be modified while being iterated to send to
listeners, resulting in a classic ConcurrentModificationException crash

Using a shallow copy of the collection for iteration should be a functional equivalent,
but without the unwanted "feature" of crashing

Fixes #6798
@mikehardy
Copy link
Collaborator

The patch to fix this is I think fairly trivial. I've posted a PR for it here, and I would love if someone could try the patch set containing the fix (via patch-package) to make sure this fixes things for them.

The patch set will be available here once the github actions workflow is done generating it: https://github.com/invertase/react-native-firebase/actions/runs/3975850361

@lwts
Copy link

lwts commented Jan 21, 2023

Awesome thanks for the quick turnaround - implementing now and then we'll do a small scale roll out to check it fixes it. Should be able to get an idea within around 6 or so hours.

EDIT: Looking good so far, has not reappeared. Will check again in the morning (8 or so hours) to confirm with newly updated users that nothing's popped up.

@mikehardy
Copy link
Collaborator

Great - I took a break over the holidays but just did a release when I came back to make sure all the release machinery was 💯 and the queue was clear. So this will be a trivial patch release + easy to do as soon as you confirm. I could honestly do it now but as long as I have a motivated tester with the patch, might as well wait for the real results. Thanks for testing!

@lwts
Copy link

lwts commented Jan 23, 2023

Yeah it's still looking clear with a much larger roll out now so probs good to release. Thanks!

@mikehardy
Copy link
Collaborator

Okay, I'll merge that and do a release - thanks again for testing+reporting

Just so you are aware as maybe you can avoid extra work? - the release will be literally nothing but the current stable release (16.5.1) plus the patch-package you already integrated, and nothing else. It will be 16.5.2.

Stated differently, if you have 16.5.1+those patches you already have 16.5.2 as it will be released so if you want to avoid re-releasing you might save some technically-duplicate effort.

Obviously do whatever your release policies call for though :-). Cheers

mikehardy added a commit that referenced this issue Jan 23, 2023
The auth provider data may apparently be modified while being iterated to send to
listeners, resulting in a classic ConcurrentModificationException crash

Using a shallow copy of the collection for iteration should be a functional equivalent,
but without the unwanted "feature" of crashing

Fixes #6798
@mikehardy mikehardy removed help: needs-triage Issue needs additional investigation/triaging. Workflow: Needs Review Pending feedback or review from a maintainer. labels Jan 24, 2023
@michaelpomogajko
Copy link

Does this patch work for 14.11.1 as well?

@mikehardy
Copy link
Collaborator

@MishaFrenkman you'll have to try it and see, v14 is no longer supported. The code has not changed that much, I give it a 95% of applying cleanly, 5% of just needing a slight tweak in order to work. Shouldn't be too bad

@michaelpomogajko
Copy link

I wasn't able to do the patch as is on v14, but the origin bug report is referencing v14 as well. @jianhui-chan were you able to get the patch running or did you just upgrade to newer version? Thanks

@NiccoloCase
Copy link

same issue for us, any update?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
impact: crash Behaviour causing app to crash. platform: android plugin: authentication Firebase Authentication type: bug New bug report
Projects
None yet
7 participants