Chris Maverick
Chris Maverick

Reputation: 928

Flutter Firebase Verify Phone Completer got messed up

I'm trying to verify phone with Firebase.

The first verification (the first verifyPhoneNumberFirebase call was okay (open the captcha, did not verify but press back, still go to codeSent, don't know why).

But the second verification (the second verifyPhoneNumberFirebase, which happened after the first one about few seconds) got timed out, ran codeAutoRetrievalTimeout. But the weird thing is the completer got completed, with the result of the previous call (codeSent) even though it got re-inited. Here's the code

Future<DataResponse> verifyPhoneNumberFirebase({String phoneNumb}) async {
    final completer = Completer<DataResponse>(); /// <--- init and re-init
    _auth
        .verifyPhoneNumber(
      phoneNumber: phoneNumb,
      verificationCompleted: (PhoneAuthCredential credential) {
        completer.complete(successSomething(verificationId));
      },
      verificationFailed: (FirebaseAuthException e) {
        completer.complete(errorHandling('error');
        }
      },
      codeSent: (String verificationId, int resendToken) {
        completer.complete(successSomething(verificationId)); 
         /// the first complete, 
         /// and somehow the second complete, 
         /// even though it did not go to this line in the second call
      },
      codeAutoRetrievalTimeout: (String verificationId) {
        completer.complete(errorHandling('error'); /// <----- already completed ???
      },
    );
    return completer.future;
  }

Here the log

[ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Bad state: Future already completed
_AsyncCompleter.complete (dart:async/future_impl.dart:45:31)
...

Right now I have no idea how to get the codeAutoRetrievalTimeout output.

Upvotes: 0

Views: 656

Answers (1)

Victor Eronmosele
Victor Eronmosele

Reputation: 7716

The error is showing up because you're using the Completer in the verificationCompleted callback after it has been used in the codeSent callback.

You can remove the completer.complete from the codeSent block since it is not completing the operation at that point.

Here's an update to your _auth.verifyPhoneNumber code:

     _auth
            .verifyPhoneNumber(
          phoneNumber: phoneNumb,
          verificationCompleted: (PhoneAuthCredential credential) {
            completer.complete(successSomething(verificationId));
          },
          verificationFailed: (FirebaseAuthException e) {
            completer.complete(errorHandling('error');
            }
          },
          codeSent: (String verificationId, int resendToken) {
            successSomething(verificationId); // Remove completer.complete
          },
          codeAutoRetrievalTimeout: (String verificationId) {
            completer.complete(errorHandling('error'); 
          },
        );

Upvotes: 1

Related Questions