Flutter一次性密码自动填充插件otp_autofill的使用

发布于 1周前 作者 gougou168 来自 Flutter

Flutter一次性密码自动填充插件otp_autofill的使用

概述

otp_autofill 插件由 Surf 开发,用于在Flutter应用中实现一次性密码(OTP)的自动填充功能。该插件利用了Android平台的SMS User Consent API和SMS Retriever API,以及iOS平台内置的短信自动填充功能。

主要特性

  • Android: 使用Google的SMS User Consent API和SMS Retriever API来监听并获取短信中的验证码。
  • iOS: 通过TextField组件直接支持短信验证码的自动填充。
  • 跨平台支持: 提供了一致的API接口,方便开发者在不同平台上实现相同的逻辑。

安装与配置

添加依赖

首先,在你的 pubspec.yaml 文件中添加 otp_autofill 依赖:

dependencies:
  otp_autofill: ^latest_version # 替换为最新版本号

然后执行 flutter pub get 更新依赖。

Android配置

确保你的 android/app/build.gradle 文件中设置了 minSdkVersion 至少为19:

android {
    ...
    defaultConfig {
        ...
        minSdkVersion 19
        ...
    }
    ...
}

使用示例

以下是一个完整的例子,展示了如何在Flutter应用程序中使用 otp_autofill 插件来接收并处理短信验证码。

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:otp_autofill/otp_autofill.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final scaffoldKey = GlobalKey<ScaffoldState>();
  late OTPTextEditController controller;
  late OTPInteractor _otpInteractor;

  @override
  void initState() {
    super.initState();
    _initInteractor();
    controller = OTPTextEditController(
      codeLength: 5,
      onCodeReceive: (code) {
        print('Your Application receive code - $code');
        // 这里可以处理接收到的验证码
      },
      otpInteractor: _otpInteractor,
    )..startListenUserConsent(
        (code) {
          final exp = RegExp(r'(\d{5})');
          return exp.stringMatch(code ?? '') ?? '';
        },
        strategies: [
          SampleStrategy(), // 自定义策略类
        ],
      );
  }

  Future<void> _initInteractor() async {
    _otpInteractor = OTPInteractor();
    final appSignature = await _otpInteractor.getAppSignature();
    if (kDebugMode) {
      print('Your app signature: $appSignature');
    }
  }

  @override
  void dispose() {
    controller.stopListen();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        key: scaffoldKey,
        appBar: AppBar(
          title: Text('Plugin example app'),
        ),
        body: Center(
          child: Padding(
            padding: EdgeInsets.all(40.0),
            child: TextField(
              textAlign: TextAlign.center,
              keyboardType: TextInputType.number,
              controller: controller,
            ),
          ),
        ),
      ),
    );
  }
}

// 自定义策略类
class SampleStrategy extends OTPStrategy {
  @override
  Future<String> listenForCode() async {
    // 模拟接收到一个验证码
    await Future.delayed(Duration(seconds: 4));
    return 'Your code is 54321';
  }
}

关键方法说明

  • OTPInteractor.getAppSignature(): 获取应用程序签名字符串,用于识别发送给用户的短信内容。
  • OTPTextEditController.startListenUserConsent(): 开始监听用户同意后的短信验证码,并通过正则表达式提取出数字部分。
  • controller.stopListen(): 停止监听,通常在页面销毁时调用以释放资源。

注意事项

  • 对于Android平台,需要确保短信格式符合Google的要求,特别是包含特定的应用签名字符串。
  • 在iOS上,短信必须包含单词 “code” 或其翻译,并且只能有一串连续的数字作为验证码。

希望这个指南能够帮助你快速上手 otp_autofill 插件!如果有任何问题或建议,请随时查阅官方文档或参与社区讨论。


更多关于Flutter一次性密码自动填充插件otp_autofill的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter一次性密码自动填充插件otp_autofill的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中集成和使用otp_autofill插件来实现一次性密码(OTP)自动填充功能的代码示例。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加otp_autofill依赖:

dependencies:
  flutter:
    sdk: flutter
  otp_autofill: ^x.y.z  # 替换为最新版本号

然后运行flutter pub get来安装依赖。

2. 导入插件

在你的Dart文件中导入otp_autofill插件:

import 'package:otp_autofill/otp_autofill.dart';

3. 使用OTP自动填充

以下是一个简单的示例,展示如何在Flutter应用中实现OTP自动填充功能。假设你有一个包含6个TextField的OTP输入表单。

import 'package:flutter/material.dart';
import 'package:otp_autofill/otp_autofill.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('OTP Autofill Example'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: OTPScreen(),
        ),
      ),
    );
  }
}

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

class _OTPScreenState extends State<OTPScreen> {
  final List<TextEditingController> _controllers = List.generate(6, () => TextEditingController());

  @override
  void dispose() {
    _controllers.forEach((controller) => controller.dispose());
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: List.generate(6, (index) {
        return OTPTextField(
          controller: _controllers[index],
          length: 1,
          onFilled: (value) {
            if (index < 5) {
              // Focus to the next text field
              FocusScope.of(context).requestFocus(_getNextFocusNode(index));
            } else {
              // All fields are filled, perform action
              print('OTP: ${_controllers.map((controller) => controller.text).join()}');
            }
          },
          keyboardType: TextInputType.number,
          decoration: InputDecoration(
            border: OutlineInputBorder(),
            labelText: 'Digit ${index + 1}',
          ),
        );
      }),
    );
  }

  FocusNode _getNextFocusNode(int currentIndex) {
    final focusNodes = List.generate(6, (index) => FocusNode());
    return focusNodes[currentIndex + 1];
  }
}

class OTPTextField extends StatelessWidget {
  final TextEditingController controller;
  final int length;
  final VoidCallback onFilled;
  final TextInputType keyboardType;
  final InputDecoration decoration;

  OTPTextField({
    required this.controller,
    required this.length,
    required this.onFilled,
    required this.keyboardType,
    required this.decoration,
  });

  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: controller,
      maxLength: length,
      keyboardType: keyboardType,
      decoration: decoration,
      inputFormatters: [
        FilteringTextInputFormatter.digitsOnly,
        LengthLimitingTextInputFormatter(length),
      ],
      onChanged: (value) {
        if (value.length == length) {
          onFilled();
        }
      },
      // Enable OTP auto-fill
      autofillHints: [AutofillHints.oneTimeCode],
    );
  }
}

注意事项

  1. Focus Management: 在上面的示例中,我们并没有实际管理FocusNode的创建和连接。为了简化示例,FocusNode部分仅作为占位符。在实际应用中,你需要确保每个TextField都有对应的FocusNode,并在onFilled回调中正确设置下一个FocusNode。

  2. AutofillHints: 确保在TextField中设置了autofillHints: [AutofillHints.oneTimeCode],这是启用OTP自动填充的关键。

  3. InputFormatters: 使用FilteringTextInputFormatter.digitsOnlyLengthLimitingTextInputFormatter来确保用户只能输入数字和限制输入长度。

  4. 测试和验证: 在实际应用中,你应该在不同设备和操作系统上测试OTP自动填充功能,以确保其正常工作。

希望这个示例能帮助你在Flutter项目中集成OTP自动填充功能!

回到顶部