7

This could be a duplicate BUT any other threads have not provided me a proper answer.

There are answers regarding android native language but none for Flutter(dart).

I have the following Method that works but if i want to resend an OTP to the user phone number How can i do that? Just a simple example code might help.

  Future signInWithPhone(String phone, BuildContext context) async {

    // This triggers if verification passes
    final PhoneVerificationCompleted verificationCompleted = (AuthCredential credential) async {
      Navigator.of(context).pop();

      AuthResult result = await _auth.signInWithCredential(credential);

      FirebaseUser user = result.user;

      if(user != null){
        Navigator.push(context, MaterialPageRoute(
          builder: (context) => HomeScreen(user: user,)
        ));
      }else{
        showDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              title: Text("Alert Dialog"),
              content: Text('Error'),
            );
          }
        );
      }
    };

    // This triggers if verification fails
    PhoneVerificationFailed verificationFailed = (AuthException exception) {
      toast(exception.message, 'long');
    };

    // This is to send code to the user But i dont know how to resend
    final PhoneCodeSent codeSent = (String verificationId, [int forceResendingToken]) {
        var route = MaterialPageRoute(
          builder: (BuildContext context) => LoginPhoneVerify(verificationId, phone)
        );

        Navigator.of(context).push(route);
    };

    // The main function
    await _auth.verifyPhoneNumber(
      phoneNumber: phone,
      timeout: Duration(seconds: 0),
      verificationCompleted: verificationCompleted,
      verificationFailed: verificationFailed,        
      codeSent: codeSent,
      codeAutoRetrievalTimeout: null
    );


  }

I have found something that is for android in the following thread:

https://stackoverflow.com/a/44688838/10114772

private void resendVerificationCode(String phoneNumber, PhoneAuthProvider.ForceResendingToken token) {
    PhoneAuthProvider.getInstance().verifyPhoneNumber(
            phoneNumber,        // Phone number to verify
            60,                 // Timeout duration
            TimeUnit.SECONDS,   // Unit of timeout
            this,               // Activity (for callback binding)
            mCallbacks,         // OnVerificationStateChangedCallbacks
            token);             // ForceResendingToken from callbacks
}

But thats not for flutter please somebody take a look !

MR_AMDEV
  • 1,712
  • 2
  • 21
  • 38
  • The Firebase APIs for Flutter are not much different than Android. If you see an Android solution, there is likely a Flutter equivalent if you just search the API documentation for it. – Doug Stevenson Apr 10 '20 at 00:17
  • Your may be right but i cant figured it out Tried lots of threads and sites – MR_AMDEV Apr 10 '20 at 00:21
  • Well, if you edit the question to include some information about the Android solution, maybe it will be easy for someone else to find the Flutter equivalent. – Doug Stevenson Apr 10 '20 at 00:22
  • here is the documentation but cant figure it out https://pub.dev/documentation/firebase_auth/latest/firebase_auth/FirebaseAuth/verifyPhoneNumber.html – MR_AMDEV Apr 10 '20 at 00:22
  • @DougStevenson i have included the android solution – MR_AMDEV Apr 10 '20 at 00:38
  • The API docs you linked to look almost exactly the same as the Android version. What about it isn't working the way you expect? – Doug Stevenson Apr 10 '20 at 01:43
  • In flutter the `resendVerificationCode` is not considered a function. – MR_AMDEV Apr 10 '20 at 01:45
  • The Android code you linked to is calling `PhoneAuthProvider.getInstance().verifyPhoneNumber`, which looks the same as the Flutter API you linked to. resendVerificationCode is just a wrapper function. – Doug Stevenson Apr 10 '20 at 01:47
  • The error is `The method 'getInstance' isn't defined for the class 'PhoneAuthProvider'. ` – MR_AMDEV Apr 10 '20 at 01:50
  • Your code is calling it right now as `_auth.verifyPhoneNumber`. What's not working the way you expect? Are you checking for errors? What's the result? – Doug Stevenson Apr 10 '20 at 01:53
  • hmm I got it but that is just the same function as in my class `_auth.verifyPhoneNumber` So it means if we want to resend the OTP code we have to simply recall the wrapper method `signInWithPhone`. But i am thinking what is the purpose forceResendingToken ? – MR_AMDEV Apr 10 '20 at 02:05

5 Answers5

6

You have to record the value of resendToken from the codesent callback and pass it to the forceresendingtoken. Also, the inbuilt timeout duration is 30 seconds So make sure you tap on resend button after timeout seconds, you may use timerbutton package it's very handy in this case.

Firebase sends 3x same SMS code and then change it to different.

    String _verificationId = "";
    int? _resendToken;

    Future<bool> sendOTP({required String phone}) async {
      await FirebaseAuth.instance.verifyPhoneNumber(
        phoneNumber: phone,
        verificationCompleted: (PhoneAuthCredential credential) {},
        verificationFailed: (FirebaseAuthException e) {},
        codeSent: (String verificationId, int? resendToken) async {
        _verificationId = verificationId;
        _resendToken = resendToken;
        },
        timeout: const Duration(seconds: 25),
        forceResendingToken: _resendToken,
        codeAutoRetrievalTimeout: (String verificationId) {
        verificationId = _verificationId;
      },
     );
   debugPrint("_verificationId: $_verificationId");
   return true;
  }
Yatendra Kumar
  • 118
  • 1
  • 6
4

So after going through the documentation according to me, recalling

verifyPhoneNumber()

method will resend the OTP code.

MR_AMDEV
  • 1,712
  • 2
  • 21
  • 38
  • Hey, I tried your solution - it does send the OTP code, but only if I wait for some time after receiving the previous code, do you know how long it waits? (I canceled auto retrieval to check this feature so the timeout is currently 0). – Guy Sep 23 '20 at 17:29
  • you have to wait 30 seconds, to resending the token disable your UI for resend token and enable it after 30 seconds it will work – Fakhar Ilyas Jun 02 '22 at 20:02
4

Record the value of forceResendingToken as resendToken from codeSent callback while sending the otp for first time, then to resend the otp, add one extra parameter forceResendingToken: resendToken in auth.verifyPhoneNumber() function.

ak100
  • 245
  • 2
  • 3
0

I had the same problem, i just disabled the resent button until time out and showed a countdown timer for same duration, after timeout you can enable the resent button and user can resend the code. it worked for me.

xbadal
  • 1,284
  • 2
  • 11
  • 24
0

my solution

String Vid = '';
     int resendToken = 0;

    Future<void> phoneSignIn() async {
        await auth.verifyPhoneNumber(
            phoneNumber: phonenumber,
            verificationCompleted: youCompleted,
            verificationFailed: youFailed,
            codeSent: CodeSent,
            timeout: const Duration(seconds: 60),
            codeAutoRetrievalTimeout: youCodeTimeout,
            forceResendingToken: resendToken);
      }

add code

CodeSent(String verificationId, int? forceResendingToken) async {
        setState(() {
          Vid = verificationId;
          resendToken = forceResendingToken!;
        });
      }

and

 Container(
               padding: const EdgeInsets.only(top: 5),
                    alignment: Alignment.topLeft,
                         child: RichText(
                             text: TextSpan(children: [
                                   TextSpan(
                                        text: 'Code didn't send ?'
                                        ),
                                    TextSpan(
                                        recognizer: new TapGestureRecognizer()
                                          ..onTap = () {
                                            phoneSignIn();
                                          },
                                        text: 'Resend'
                                       ),
                                  ]),
                                )),