Open In App

How to Get OTP Autofill in Flutter?

Last Updated : 24 Sep, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

These days we see several times that as we approach getting signed-in in many applications we need to verify our phone numbers. However, we can do so in mainly two ways: by making a phone call or by an OTP — sent as an SMS to our phone numbers. So in this article, we’re going to discuss how we can fill up the OTP fields of our screen(Flutter UI) automatically as the OTP SMS comes. A sample video is given below to get an idea about what we are going to do in this article.

Step By Step Implementation

Step 1: Set Up Firebase

Create a new project on the Firebase Console (https://console.firebase.google.com/). Add your Android and iOS app to the Firebase project and follow the setup instructions to integrate Firebase SDKs into your Flutter app.

Step 2: Set Up Firebase: Implement Phone Number Verification

Use the firebase_auth package in Flutter to interact with Firebase Authentication. Request the user’s phone number and initiate the OTP verification process. You can use the FirebaseAuth.instance.verifyPhoneNumber method to send an OTP to the user’s phone number.

Step 3: Handle OTP Verification

After sending the OTP, Firebase will send an SMS containing the OTP to the user’s phone. Use the firebase_auth package to handle OTP verification. The verifyPhoneNumber method returns a PhoneVerificationCompleted callback when the verification is complete.

Step 4: Handle Verification Failures

There can be scenarios where OTP verification fails (e.g., wrong OTP entered or network issues). You should handle these cases using the PhoneVerificationFailed and PhoneCodeAutoRetrievalTimeout callbacks.

Step 5: Complete the Authentication Process

Once the OTP is verified successfully, you will receive a verification ID. Use this verification ID along with the user-entered OTP to create a PhoneAuthCredential. Finally, call signInWithCredential from the FirebaseAuth instance to complete the authentication process.

Otp Autofill

Now, add telephony and otp_text_field packages to your project by adding the following lines on pubspec.yaml file:

Dart




telephony: ^0.2.0
otp_text_field: ^1.1.3


Here, telephony is to listen to incoming OTP message and otp_text_field packages is for OTP input boxes. Add this permission and tags on AndroidManifest.xml file at android/app/src/main folder:

XML




<manifest>
    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
  
    <application>
        ...
        ...
  
        <receiver android:name="com.shounakmulay.telephony.sms.IncomingSmsReceiver"
            android:permission="android.permission.BROADCAST_SMS" android:exported="true">
            <intent-filter>
            <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
            </intent-filter>
        </receiver>
  
    </application>
</manifest>


Declare the required variables:

Dart




Telephony telephony = Telephony.instance;
OtpFieldController otpbox = OtpFieldController();


Listen to the incoming OTP SMS:

Dart




telephony.listenIncomingSms(
    onNewMessage: (SmsMessage message) {
        print(message.address); // +977981******67, sender nubmer
        print(message.body);    // Your OTP code is 34567
        print(message.date);    // 1659690242000, timestamp
          
          // get the message
        String sms = message.body.toString(); 
  
        if(message.body!.contains('yourFirebaseProjectName.firebaseapp.com')){
              // verify SMS is sent for OTP with sender number
              String otpcode = sms.replaceAll(new RegExp(r'[^0-9]'),'');
              // prase code from the OTP sms
              otpbox.set(otpcode.split("")); 
              // split otp code to list of number
              // and populate to otb boxes
              setState(() {
                  // refresh UI
              });
  
        }else{
            print("Normal message.");
        }
    },
    listenInBackground: false,
);


Set OTP boxes input on your widget tree(Autofill Otp):

Dart




OTPTextField(
                outlineBorderRadius: 10,
                controller: otpbox,
                length: 6,
                width: MediaQuery.of(context).size.width,
                fieldWidth: 50,
                style: TextStyle(fontSize: 17),
                textFieldAlignment: MainAxisAlignment.spaceAround,
                fieldStyle: FieldStyle.box,
                onCompleted: (pin) {
                  otp = pin;
  
                },
              ),


Full App Example Code (only after completing firebase auth OTP):

Dart




class OtpPhoneWidget extends StatefulWidget {
  const OtpPhoneWidget({
    Key? key,
  }) : super(key: key);
  
  @override
  _OtpPhoneWidgetState createState() => _OtpPhoneWidgetState();
}
  
class _OtpPhoneWidgetState extends State<OtpPhoneWidget>
    with TickerProviderStateMixin {
  
  String otp = '';
  Telephony telephony = Telephony.instance;
  OtpFieldController otpbox = OtpFieldController();
  
  final scaffoldKey = GlobalKey<ScaffoldState>();
  @override
  void initState() {
    telephony.listenIncomingSms(
      onNewMessage: (SmsMessage message) {
        print(message.address); 
        print(message.body);
  
        String sms = message.body.toString();
  
        if (message.body!.contains('yourFirebaseProjectName.firebaseapp.com')) {
            
          String otpcode = sms.replaceAll(new RegExp(r'[^0-9]'), '');
          otpbox.set(otpcode.split(""));
  
          setState(() {
            // refresh UI
          });
        } else {
          print("error");
        }
      },
      listenInBackground: false,
    );
  }
    
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.blue,
        title: Text('Otp Aut0fill'),
      ),
      body: Center(
        child: Column(
          children: [
            OTPTextField(
                outlineBorderRadius: 10,
                controller: otpbox,
                length: 6,
                width: MediaQuery.of(context).size.width,
                fieldWidth: 50,
                style: TextStyle(fontSize: 17),
                textFieldAlignment: MainAxisAlignment.spaceAround,
                fieldStyle: FieldStyle.box,
                onCompleted: (pin) {
                  otp = pin;
  
                },
              ),
          ],
        ),
      ),
    );
  }
}


Output:



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads