firebase / flutterfire

🔥 A collection of Firebase plugins for Flutter apps.
https://firebase.google.com/docs/flutter/setup
BSD 3-Clause "New" or "Revised" License
8.72k stars 3.97k forks source link

firebase Auth My app has been uploaded 10 times before and the Apple ios reviewers reject it because of this reason Guideline 2.1 - Performance - App Completeness #9616

Closed abasahmed closed 2 years ago

abasahmed commented 2 years ago

Bug report

Describe the bug My app is developed with flutter and firebase Auth My app has been uploaded 10 times before and the reviewers reject it because of this reason Guideline 2.1 - Performance - App Completeness

We continue to see the same bug in your app. Specifically, an activity indicator kept spinning indefinitely when we attempted to login with the demo credentials provided. Please review the details below and complete the next steps.

Review device details:

Device type: iPhone OS version ios 16.0

I think this is because it does not send a request to Firebase to request a verification code (OTP)

and i was do this:

image

and apple team provide me this screenshot:

image### Steps to reproduce

my code is:

Click To Expand ``` **AppDelegate.swift** import UIKit import Flutter import GoogleMaps import Firebase import FirebaseMessaging import GoogleMobileAds @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { GMSServices.provideAPIKey("AIzaSyB4fSpdG4cDkjB8-L_ntu8l443eMjb9FYE") FirebaseApp.configure() GADMobileAds.sharedInstance().start(completionHandler: nil) GeneratedPluginRegistrant.register(with: self) if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate } return super.application(application, didFinishLaunchingWithOptions: launchOptions) } override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { let firebaseAuth = Auth.auth() if (firebaseAuth.canHandleNotification(userInfo)){ print("7777777777777777777777777777777777777777777777777777777777777777") print(userInfo) return } } override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { //new let firebaseAuth = Auth.auth() firebaseAuth.setAPNSToken(deviceToken, type: AuthAPNSTokenType.unknown); Messaging.messaging().apnsToken = deviceToken //------- print("Token: \(deviceToken)") super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) } } **DART** import 'dart:developer' as developer; import 'dart:math'; import 'package:car_seller/components/colors.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:firebase_phone_auth_handler/firebase_phone_auth_handler.dart'; import 'package:flutter/material.dart'; //import 'package:car_seller/screens/home_screen.dart'; import 'package:car_seller/widgets/custom_loader.dart'; import 'package:car_seller/widgets/pin_input_field.dart'; import '../services/checkUserData.dart'; import '../utils/helpers.dart'; class VerifyPhoneNumberScreen extends StatefulWidget { static const id = 'VerifyPhoneNumberScreen'; final String phoneNumber; const VerifyPhoneNumberScreen({ Key? key, required this.phoneNumber, }) : super(key: key); @override State createState() => _VerifyPhoneNumberScreenState(); } class _VerifyPhoneNumberScreenState extends State with WidgetsBindingObserver { bool isKeyboardVisible = false; late final ScrollController scrollController; @override void initState() { scrollController = ScrollController(); WidgetsBinding.instance!.addObserver(this); log(widget.phoneNumber); super.initState(); } @override void dispose() { WidgetsBinding.instance!.removeObserver(this); scrollController.dispose(); super.dispose(); } @override void didChangeMetrics() { final bottomViewInsets = WidgetsBinding.instance!.window.viewInsets.bottom; isKeyboardVisible = bottomViewInsets > 0; } // scroll to bottom of screen, when pin input field is in focus. Future _scrollToBottomOnKeyboardOpen() async { while (!isKeyboardVisible) { await Future.delayed(const Duration(milliseconds: 50)); } await Future.delayed(const Duration(milliseconds: 250)); await scrollController.animateTo( scrollController.position.maxScrollExtent, duration: const Duration(milliseconds: 250), curve: Curves.easeIn, ); } @override Widget build(BuildContext context) { return SafeArea( child: FirebasePhoneAuthHandler( phoneNumber: widget.phoneNumber, signOutOnSuccessfulVerification: false, linkWithExistingUser: false, autoRetrievalTimeOutDuration: const Duration(seconds: 60), otpExpirationDuration: const Duration(seconds: 60), onCodeSent: () { log(VerifyPhoneNumberScreen.id, msg: 'OTP sent!'); }, onLoginSuccess: (userCredential, autoVerified) async { log( VerifyPhoneNumberScreen.id, msg: autoVerified ? 'OTP was fetched automatically!' : 'OTP was verified manually!', ); showSnackBar('Phone number verified successfully!'); log( VerifyPhoneNumberScreen.id, msg: 'Login Success UID: ${userCredential.user?.uid}', ); var value = userCredential; /* Navigator.pushNamedAndRemoveUntil( context, HomeScreen.id, (route) => false, ); */ if (value.user != null) { print('user logged in'); FirebaseFirestore.instance.collection('users').doc(value.user?.phoneNumber).get().then((DocumentSnapshot documentSnapshot) { if (documentSnapshot.exists) { print('Document exists '); Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) { return CheckUserData(); }, ), ); } else if (!documentSnapshot.exists) { print('Document not exists '); Random random = new Random(); int randomNumber = random.nextInt(100000); FirebaseFirestore.instance .collection('users') .doc(FirebaseAuth.instance.currentUser?.phoneNumber) .set({'phone': FirebaseAuth.instance.currentUser?.phoneNumber, 'userType': 'user', 'name': 'guest$randomNumber', 'tokenChanged': 0, 'liked': [], 'blacklistR': []}); try { FirebaseMessaging.instance.getToken().then((event) { developer.log(event.toString()); FirebaseFirestore.instance.collection('users').doc(FirebaseAuth.instance.currentUser?.phoneNumber).update({ 'token': event, //'tokenChanged': (documentSnapshot.get('tokenChanged') ?? 0) + 1, }); }); } on Exception catch (e) { developer.log('*********************************'); throw e; } Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) { return CheckUserData(); }, ), ); } else { print('Erooooooooooooooooooooor'); } // ignore: invalid_return_type_for_catch_error }).catchError((error) => print('Something wrong ........ $error}')); print('PASS TO HOME//////////////////////$value'); } else { // showToast("الكود غير صحيح", kPrimaryColor); print('Nulllllllll in checking'); Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) { return CheckUserData(); }, ), ); } }, onLoginFailed: (authException, stackTrace) { log( VerifyPhoneNumberScreen.id, msg: authException.message, error: authException, stackTrace: stackTrace, ); switch (authException.code) { case 'invalid-phone-number': // invalid phone number return showSnackBar('Invalid phone number!'); case 'invalid-verification-code': // invalid otp entered return showSnackBar('The entered OTP is invalid!'); // handle other error codes default: showSnackBar('Something went wrong!'); // handle error further if needed } }, onError: (error, stackTrace) { log( VerifyPhoneNumberScreen.id, error: error, stackTrace: stackTrace, ); showSnackBar('An error occurred!'); }, builder: (context, controller) { return Scaffold( appBar: AppBar( leadingWidth: 0, leading: const SizedBox.shrink(), title: const Text('التحقق من رقم الهاتف'), actions: [ if (controller.codeSent) TextButton( onPressed: controller.isOtpExpired ? () async { log(VerifyPhoneNumberScreen.id, msg: 'Resend OTP'); await controller.sendOTP(); } : null, child: Text( controller.isOtpExpired ? 'إعادة الارسال' : '${controller.otpExpirationTimeLeft.inSeconds}s', style: const TextStyle(color: Color.fromARGB(255, 0, 3, 5), fontSize: 18), ), ), const SizedBox(width: 5), ], ), body: controller.isSendingCode ? Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: const [ CustomLoader(), SizedBox(height: 50), Center( child: Text( 'يتم الان إرسال رمز التحقق', style: TextStyle(fontSize: 25), ), ), ], ) : ListView( padding: const EdgeInsets.all(20), controller: scrollController, children: [ Directionality( textDirection: TextDirection.rtl, child: Column( children: [ Text( ' ارسلنا رمز التحقق فى رسالة نصية الى هذا الهاتف', style: TextStyle(fontSize: 22), ), Text( " ${widget.phoneNumber}", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 22, color: kPrimaryColor), textDirection: TextDirection.ltr, ), ], ), ), const SizedBox(height: 10), const Divider(), if (controller.isListeningForOtpAutoRetrieve) Column( children: const [ CustomLoader(), SizedBox(height: 50), Text( 'فى إنتظار رمز التحقق والدخول تلقائياً', textAlign: TextAlign.center, style: TextStyle( fontSize: 25, fontWeight: FontWeight.w600, ), ), SizedBox(height: 15), Divider(), Directionality(textDirection: TextDirection.rtl, child: Text('او اكتبه بنفسك', textAlign: TextAlign.center)), Divider(), ], ), const SizedBox(height: 15), Directionality( textDirection: TextDirection.rtl, child: const Text( 'ادخل رمز التحقق بنفسك', style: TextStyle( fontSize: 20, fontWeight: FontWeight.w600, ), ), ), const SizedBox(height: 15), Container( decoration: BoxDecoration( color: Color.fromARGB(255, 238, 238, 238), borderRadius: BorderRadius.circular(8), ), child: Padding( padding: const EdgeInsets.all(8.0), child: PinInputField( length: 6, onFocusChange: (hasFocus) async { if (hasFocus) await _scrollToBottomOnKeyboardOpen(); }, onSubmit: (enteredOtp) async { final verified = await controller.verifyOtp(enteredOtp); if (verified) { // number verify success // will call onLoginSuccess handler } else { // phone verification failed // will call onLoginFailed or onError callbacks with the error } }, ), ), ), ], ), ); }, ), ); } } ```


Additional context

Can any one help me?


Flutter doctor

Run flutter doctor and paste the output below:

Click To Expand ``` Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, 2.10.2, on macOS 11.6 20G165 darwin-x64, locale en-EG) [✓] Android toolchain - develop for Android devices (Android SDK version 32.1.0-rc1) [✓] Xcode - develop for iOS and macOS (Xcode 13.2.1) [✓] Chrome - develop for the web [✓] Android Studio (version 2021.1) [✓] VS Code [✓] Connected device (2 available) [✓] HTTP Host Availability • No issues found! ```

Flutter dependencies

Run flutter pub deps -- --style=compact and paste the output below: Dart SDK 2.16.1 Flutter SDK 2.10.2 car_seller 3.3.5+47

dependencies:

dev dependencies:

transitive dependencies:

2022-09-24 06:36:34.893953+0200 Runner[46535:1684110] Metal API Validation Enabled
2022-09-24 06:36:35.085606+0200 Runner[46535:1684369] 9.3.0 - [GoogleUtilities/AppDelegateSwizzler][I-SWZ001011] App Delegate Proxy is disabled.
2022-09-24 06:36:35.570602+0200 Runner[46535:1684362] 9.3.0 - <AppMeasurement>[I-ACS025027] Deferring to Google Analytics for Firebase for event data collection. https://goo.gl/YNbdK2
2022-09-24 06:36:35.608990+0200 Runner[46535:1684110] [ViewportSizing] maximumViewportInset cannot be larger than frame
2022-09-24 06:36:35.609126+0200 Runner[46535:1684110] [ViewportSizing] minimumViewportInset cannot be larger than frame
2022-09-24 06:36:35.643064+0200 Runner[46535:1684373] flutter: ////////////////////////////////////////////////////////FirebaseAuth.instance.currentUser?.uid/null
2022-09-24 06:36:35.643223+0200 Runner[46535:1684373] flutter: ////////////////////////////////////////////////////////FirebaseAuth.instance.currentUser?.phoneNumber/null
2022-09-24 06:36:35.649539+0200 Runner[46535:1684373] flutter: ConnectivityStatus.WiFi
Token: 32 bytes
2022-09-24 06:36:38.675954+0200 Runner[46535:1684373] flutter: Platform.isAndroid: false
2022-09-24 06:36:38.711935+0200 Runner[46535:1684373] flutter: User granted permission: AuthorizationStatus.authorized
2022-09-24 06:36:38.712162+0200 Runner[46535:1684373] flutter: User granted permission
2022-09-24 06:36:38.712658+0200 Runner[46535:1684373] flutter: here 3.3.9
2022-09-24 06:36:38.712790+0200 Runner[46535:1684373] flutter: there 3.3.5
2022-09-24 06:36:38.907087+0200 Runner[46535:1684373] flutter: geting null
2022-09-24 06:36:38.907242+0200 Runner[46535:1684373] flutter: Document doesn't exist
2022-09-24 06:36:38.909422+0200 Runner[46535:1684373] flutter: here 3.3.9
2022-09-24 06:36:38.909569+0200 Runner[46535:1684373] flutter: there 3.3.5
2022-09-24 06:36:39.108422+0200 Runner[46535:1684373] flutter: here 3.3.9
2022-09-24 06:36:39.108617+0200 Runner[46535:1684373] flutter: there 3.3.5
2022-09-24 06:36:39.382307+0200 Runner[46535:1684110] <Google> To get test ads on this device, set: 
Objective-C
    GADMobileAds.sharedInstance.requestConfiguration.testDeviceIdentifiers = @[ @"a6abefc6bb0792de2b04ec4c48b78fa7" ];
Swift
    GADMobileAds.sharedInstance().requestConfiguration.testDeviceIdentifiers = [ @"a6abefc6bb0792de2b04ec4c48b78fa7" ]
2022-09-24 06:36:39.383025+0200 Runner[46535:1684110] <Google> Note that test device identifiers may be reset when uninstalling and reinstalling the application.
2022-09-24 06:37:06.890761+0200 Runner[46535:1684473] [connection] nw_resolver_start_query_timer_block_invoke [C4.1] Query fired: did not receive all answers in time for firebaselogging-pa.googleapis.com:443
2022-09-24 06:37:35.360331+0200 Runner[46535:1684373] flutter: Ad impression.Instance of 'BannerAd';;
2022-09-24 06:37:39.314299+0200 Runner[46535:1684373] flutter: Ad impression.Instance of 'BannerAd';;
2022-09-24 06:37:40.721584+0200 Runner[46535:1684373] flutter: Ad impression.Instance of 'BannerAd';;
2022-09-24 06:37:41.917670+0200 Runner[46535:1684373] flutter: Ad impression.Instance of 'BannerAd';;
2022-09-24 06:38:22.155224+0200 Runner[46535:1684373] flutter: 3
2022-09-24 06:38:23.316950+0200 Runner[46535:1684373] flutter: Pressed !
2022-09-24 06:38:23.325007+0200 Runner[46535:1684373] flutter: user signOUT done
2022-09-24 06:38:25.050984+0200 Runner[46535:1684373] flutter: Go L
2022-09-24 06:38:30.995962+0200 Runner[46535:1684110] Can't find keyplane that supports type 4 for keyboard iPhone-PortraitTruffle-NumberPad; using 27071_PortraitTruffle_iPhone-Simple-Pad_Default
2022-09-24 06:38:32.984268+0200 Runner[46535:1684373] flutter: +200
2022-09-24 06:38:33.470923+0200 Runner[46535:1684373] flutter: +2001
2022-09-24 06:38:34.252917+0200 Runner[46535:1684373] flutter: +20010
2022-09-24 06:38:36.026988+0200 Runner[46535:1684373] flutter: +200103
2022-09-24 06:38:36.685810+0200 Runner[46535:1684373] flutter: +2001030
2022-09-24 06:38:36.891879+0200 Runner[46535:1684373] flutter: +20010300
2022-09-24 06:38:38.255201+0200 Runner[46535:1684373] flutter: +200103002
2022-09-24 06:38:39.783675+0200 Runner[46535:1684373] flutter: +2001030020
2022-09-24 06:38:42.077446+0200 Runner[46535:1684373] flutter: +20010300201
2022-09-24 06:38:42.477921+0200 Runner[46535:1684373] flutter: +200103002015
2022-09-24 06:38:43.842853+0200 Runner[46535:1684373] flutter: +201030020158
2022-09-24 06:39:06.400219+0200 Runner[46535:1684373] flutter: 414.0
7777777777777777777777777777777777777777777777777777777777777777
[AnyHashable("com.google.firebase.auth"): {
    warning = "This fake notification should be forwarded to Firebase Auth.";
}]
2022-09-24 06:39:45.777509+0200 Runner[46535:1684110] Can't find keyplane that supports type 4 for keyboard iPhone-PortraitTruffle-NumberPad; using 27071_PortraitTruffle_iPhone-Simple-Pad_Default
2022-09-24 06:39:46.802499+0200 Runner[46535:1684373] flutter: +200103002015

2022-09-24 06:40:02.663009+0200 Runner[46535:1684110] Can't find keyplane that supports type 4 for keyboard iPhone-PortraitTruffle-NumberPad; using 27071_PortraitTruffle_iPhone-Simple-Pad_Default
2022-09-24 06:40:11.980392+0200 Runner[46535:1684110] Can't find keyplane that supports type 4 for keyboard iPhone-PortraitTruffle-NumberPad; using 27071_PortraitTruffle_iPhone-Simple-Pad_Default
2022-09-24 06:40:16.168574+0200 Runner[46535:1684373] flutter: user logged in
2022-09-24 06:40:16.170578+0200 Runner[46535:1684373] flutter: PASS TO HOME//////////////////////UserCredential(additionalUserInfo: AdditionalUserInfo(isNewUser: false, profile: {}, providerId: phone, username: null), credential: null, user: User(displayName: null, email: null, emailVerified: false, isAnonymous: false, metadata: UserMetadata(creationTime: 2022-04-24 20:28:19.239, lastSignInTime: 2022-09-24 06:40:15.544), phoneNumber: +201000000000, photoURL: null, providerData, [UserInfo(displayName: null, email: null, phoneNumber: +201000000000, photoURL: null, providerId: phone, uid: null)], refreshToken: , tenantId: null, uid: 0OyAlz9hN6hZeJq5elDxoQ6VHfq1))
2022-09-24 06:40:16.521737+0200 Runner[46535:1684373] flutter: Document exists
2022-09-24 06:40:16.543157+0200 Runner[46535:1684373] flutter: Platform.isAndroid: false
2022-09-24 06:40:16.565237+0200 Runner[46535:1684373] flutter: here 3.3.9
2022-09-24 06:40:16.565531+0200 Runner[46535:1684373] flutter: there 3.3.5
2022-09-24 06:40:16.588670+0200 Runner[46535:1684373] flutter: User granted permission: AuthorizationStatus.authorized
2022-09-24 06:40:16.590467+0200 Runner[46535:1684373] flutter: User granted permission
2022-09-24 06:40:16.720766+0200 Runner[46535:1684373] flutter: geting +201000000000
2022-09-24 06:40:16.720925+0200 Runner[46535:1684373] flutter: Document exists
2022-09-24 06:40:16.723799+0200 Runner[46535:1684373] flutter: here 3.3.9
2022-09-24 06:40:16.723972+0200 Runner[46535:1684373] flutter: there 3.3.5
2022-09-24 06:40:16.758994+0200 Runner[46535:1684373] flutter: here 3.3.9
2022-09-24 06:40:16.759223+0200 Runner[46535:1684373] flutter: there 3.3.5
2022-09-24 06:40:17.046022+0200 Runner[46535:1684373] flutter: []
2022-09-24 06:41:13.393447+0200 Runner[46535:1684373] flutter: Ad impression.Instance of 'BannerAd';;
2022-09-24 06:41:15.613280+0200 Runner[46535:1684373] flutter: Ad impression.Instance of 'BannerAd';;
2022-09-24 06:41:17.701804+0200 Runner[46535:1684373] flutter: Ad impression.Instance of 'BannerAd';;
2022-09-24 06:41:20.109663+0200 Runner[46535:1684373] flutter: Ad impression.Instance of 'BannerAd';;
2022-09-24 06:42:17.266346+0200 Runner[46535:1684373] flutter: 3
2022-09-24 06:42:18.587268+0200 Runner[46535:1684373] flutter: Pressed !
2022-09-24 06:42:18.631083+0200 Runner[46535:1684373] flutter: user signOUT done
2022-09-24 06:42:18.649660+0200 Runner[46535:1684373] flutter: User nullllllllllllllllllllllllllll

2022-09-24 06:42:19.944537+0200 Runner[46535:1684373] flutter: Go L
2022-09-24 06:42:22.371381+0200 Runner[46535:1684110] Can't find keyplane that supports type 4 for keyboard iPhone-PortraitTruffle-NumberPad; using 27071_PortraitTruffle_iPhone-Simple-Pad_Default

2022-09-24 06:42:28.296445+0200 Runner[46535:1684373] flutter: +201111111111
2022-09-24 06:42:33.885626+0200 Runner[46535:1684373] flutter: 414.0
2022-09-24 06:42:36.465860+0200 Runner[46535:1686651] [connection] nw_resolver_start_query_timer_block_invoke [C13.1] Query fired: did not receive all answers in time for www.googleapis.com:443
2022-09-24 06:42:50.062812+0200 Runner[46535:1684110] Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service
2022-09-24 06:42:50.065392+0200 Runner[46535:1684110] Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service
2022-09-24 06:42:50.089717+0200 Runner[46535:1684110] Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service
2022-09-24 06:42:50.090214+0200 Runner[46535:1684110] Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service


darshankawar commented 2 years ago

@abasahmed You seem to be on very old version of the framework, Channel stable, 2.10.2,. Current version is 3.3.2 which you should upgrade to, to get latest features offered by plugins.

Also, it isn't exactly clear what's the error could be, may or may not be related to firebase auth plugin but more of code implementation or config / setting issue.

I suggest you to ask this question on support channels like StackOverflow for further resolution.

Closing from here.