You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中Firebase Phone Auth实现OTP输入框自动填充求助

解决Flutter Firebase Phone Auth OTP自动填充问题

1. 先搞定平台配置(这步必须做)

Android端

  • 打开android/app/src/main/AndroidManifest.xml,给OTP页面对应的Activity(一般是MainActivity)加个intent-filter,让系统能把短信里的OTP定向到你的应用:
<activity
    android:name=".MainActivity"
    android:exported="true">
    <!-- 保留原有配置 -->
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <!-- 替换成你的应用包名,比如com.example.myapp -->
        <data android:scheme="your_package_name" />
    </intent-filter>
</activity>
  • 另外注意短信格式:Firebase默认的短信是[你的应用名] 你的验证码是 123456。,这个格式系统能识别;如果自定义短信模板,必须包含“验证码”或“code”这类关键词,且数字位数和你的OTP输入框一致(比如6位)。

iOS端

  • 打开ios/Runner/Info.plist,添加以下配置,允许应用读取并处理OTP:
<key>NSUserActivityTypes</key>
<array>
    <string>$(PRODUCT_BUNDLE_IDENTIFIER).otp-authentication</string>
</array>
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <!-- 替换成你的应用Bundle ID,比如com.example.myapp -->
            <string>your_bundle_id</string>
        </array>
    </dict>
</array>
  • iOS 12+支持自动填充,后续代码里要给OTP输入框设置正确的textContentType。

2. 代码层面实现自动填充

方法一:用Firebase Auth自带的自动监听

Firebase的verifyPhoneNumber本身就有自动捕获OTP的回调,不用自己读短信。修改你的AuthController里的signInWithPhoneNumber方法:

Future<void> signInWithPhoneNumber(String phoneNumber, BuildContext context) async {
  await FirebaseAuth.instance.verifyPhoneNumber(
    phoneNumber: phoneNumber,
    verificationCompleted: (PhoneAuthCredential credential) async {
      // 系统自动获取到OTP时触发
      await FirebaseAuth.instance.signInWithCredential(credential);
      // 把OTP传到OTP页面填充(这里用GetX做状态管理示例,你可以换成自己的状态管理方式)
      if (context.mounted) {
        String otp = credential.smsCode!;
        Get.find<AuthController>().autoFilledOTP = otp;
        Navigator.push(context, MaterialPageRoute(builder: (_) => OTPScreen()));
      }
    },
    verificationFailed: (FirebaseAuthException e) {
      print(e.message); // 处理验证失败逻辑
    },
    codeSent: (String verificationId, int? resendToken) {
      _verificationId = verificationId;
      Navigator.push(context, MaterialPageRoute(builder: (_) => OTPScreen()));
    },
    codeAutoRetrievalTimeout: (String verificationId) {
      _verificationId = verificationId;
    },
    timeout: const Duration(seconds: 60),
  );
}

方法二:适配otp_text_field组件填充

在OTPScreen里用组件的控制器来设置自动获取到的OTP:

import 'package:otp_text_field/otp_text_field.dart';
import 'package:otp_text_field/style.dart';

class OTPScreen extends StatefulWidget {
  @override
  State<OTPScreen> createState() => _OTPScreenState();
}

class _OTPScreenState extends State<OTPScreen> {
  late OTPController otpController;

  @override
  void initState() {
    super.initState();
    otpController = OTPController();
    // 从AuthController拿到自动填充的OTP,填充到输入框
    String? autoOtp = Get.find<AuthController>().autoFilledOTP;
    if (autoOtp != null) {
      otpController.set(autoOtp.split(''));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          OTPTextField(
            controller: otpController,
            length: 6,
            width: MediaQuery.of(context).size.width,
            fieldWidth: 50,
            style: const TextStyle(fontSize: 17),
            textFieldAlignment: MainAxisAlignment.spaceAround,
            fieldStyle: FieldStyle.box,
            textInputType: TextInputType.number,
            // iOS必须加这个,让系统识别是OTP输入框
            textContentType: TextContentType.oneTimeCode,
            onCompleted: (pin) {
              Get.find<AuthController>().verifyOTP(pin);
            },
          ),
        ],
      ),
    );
  }
}

方法三:用插件手动读短信(备选,不推荐)

如果上面的方法都不行,可以用sms_autofill插件辅助:

  1. 安装插件:flutter pub add sms_autofill
  2. 在OTPScreen里使用:
import 'package:sms_autofill/sms_autofill.dart';
import 'package:otp_text_field/otp_text_field.dart';

class OTPScreen extends StatefulWidget {
  @override
  State<OTPScreen> createState() => _OTPScreenState();
}

class _OTPScreenState extends State<OTPScreen> with CodeAutoFill {
  late OTPController otpController;

  @override
  void initState() {
    super.initState();
    otpController = OTPController();
    listenForCode(); // 开始监听短信
  }

  @override
  void codeUpdated() {
    // 拿到短信里的OTP,直接填充
    if (code != null) {
      otpController.set(code!.split(''));
    }
  }

  @override
  void dispose() {
    cancel(); // 销毁时取消监听
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          OTPTextField(
            controller: otpController,
            length: 6,
            // 其他配置同上
          ),
        ],
      ),
    );
  }
}

3. 踩坑提醒

  • 测试用的设备要开系统默认短信应用,第三方短信APP可能会拦截自动填充。
  • Android模拟器上要手动发符合格式的短信,比如[MyApp] 你的验证码是 123456。
  • iOS要开启“自动填充密码”功能(设置→密码→自动填充密码)。

内容的提问来源于stack exchange,提问作者alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 10:48:35