如何从短信中获取 OTP - 自动填充

Kha*_*med 18 autofill one-time-password dart flutter

我想自动捕获或读取短信的 OTP。我做了一些像这样的代码测试:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Demo Auto OTP'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  TextEditingController _textController = TextEditingController();
  String _error;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Multi-Factor-Authentication"),
        ),
        body: Form(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            mainAxisSize: MainAxisSize.min,
            children: [
              TextField(
                controller: _textController,
                autofillHints: [ AutofillHints.oneTimeCode ],
                keyboardType: TextInputType.visiblePassword,
                maxLength: 6,
                maxLengthEnforced: true,
                style: TextStyle(fontSize: 32),
              ),

              RaisedButton(
                child: Text("Verify"),
                onPressed: () => Navigator.of(context).pop(_textController.value.text),
              ),
            ],
          ),
        )
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

这是测试短信:12345 is your code to log in.

oneTimeCode 的 Flutter 文档: https://api.flutter.dev/flutter/services/AutofillHints/oneTimeCode-constant.html

颤振自动填充:https://github.com/flutter/flutter/blob/7891006299/packages/flutter/lib/src/services/autofill.dart#L362

iOS: https: //developer.apple.com/documentation/uikit/uitextcontenttype

安卓: https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_SMS_OTP

Md.*_*min 27

新答案(截至 23 年 6 月): 我们将使用此包自动填充 sms otp: https: //pub.dev/packages/sms_autofill。将其添加到您的 pubspec.yaml 中。首先,确保您在 Android 手机中收到的短信应在短信开头包含“<#>”,并在短信末尾包含您的应用程序签名密钥。短信示例应如下所示:

<#> 您的 otp 代码是 543216 app_signature

生成应用程序签名密钥的方法有多种,您还可以使用 sms_autofill 包使用以下代码获取应用程序签名密钥:

await SmsAutoFill().getAppSignature;
Run Code Online (Sandbox Code Playgroud)

它将以字符串格式返回您的应用程序签名,只需将其添加到短信末尾即可。如果您已经拥有应用程序签名,则可以删除上述代码或忽略它。

首先让我们绘制小部件:

PinFieldAutoFill(
                        decoration: BoxLooseDecoration(
                          strokeColorBuilder: PinListenColorBuilder(Colors.black, Colors.black26),
                          bgColorBuilder: const FixedColorBuilder(Colors.white),
                          strokeWidth: 2,
                        ),
                        autoFocus: true,
                        cursor: Cursor(color: Colors.red, enabled: true, width: 1),
                        currentCode: '',
                        onCodeSubmitted: (code) {},
                        codeLength: 6,
                        onCodeChanged: (code) {
                          print(code);
                        },
                      ),
Run Code Online (Sandbox Code Playgroud)

然后在 onInit() 状态下监听短信代码:

await SmsAutoFill().listenForCode();
Run Code Online (Sandbox Code Playgroud)

这将在 5 分钟内监听带有代码的短信,收到后自动填充上述小部件。

在你的 onDispose 方法中不要忘记释放监听器:

SmsAutoFill().unregisterListener();
Run Code Online (Sandbox Code Playgroud)

旧答案: 如果有人想阅读用户的短信,可以使用此答案。此外,如果您使用底部实现,如果您没有提供有关为什么要阅读用户短信的正确解释,PlayStore 可能会拒绝您的应用程序。我希望对于仍在寻找这个问题答案的人们来说还不算太晚。我使用了两个包https://pub.dev/packages/alt_sms_autofillhttps://pub.dev/packages/pin_code_fields。将这两个包添加到您的 pubspec.yaml 文件中。运行“flutter pub get”下载软件包。

在您的 otp 屏幕中导入两个包:

import 'package:alt_sms_autofill/alt_sms_autofill.dart';
import 'package:pin_code_fields/pin_code_fields.dart';
Run Code Online (Sandbox Code Playgroud)

在您的 AppState 扩展 State 后,放置以下函数来抓取传入的短信:

  TextEditingController textEditingController1;

  String _comingSms = 'Unknown';

  Future<void> initSmsListener() async {

    String comingSms;
    try {
      comingSms = await AltSmsAutofill().listenForSms;
    } on PlatformException {
      comingSms = 'Failed to get Sms.';
    }
    if (!mounted) return;
    setState(() {
      _comingSms = comingSms;
      print("====>Message: ${_comingSms}");
      print("${_comingSms[32]}");
      textEditingController1.text = _comingSms[32] + _comingSms[33] + _comingSms[34] + _comingSms[35]
          + _comingSms[36] + _comingSms[37]; //used to set the code in the message to a string and setting it to a textcontroller. message length is 38. so my code is in string index 32-37.
    });
  }
Run Code Online (Sandbox Code Playgroud)

我的传入 OTP 消息格式如下所示: 您的手机验证码是 625742。 在上面的函数中,它正在侦听传入的短信并将其保存到字符串中。收到短信后,我将“625742”代码设置到我的文本编辑控制器,方法是在字符串中提供代码的索引位置,然后将该值设置到我的 PinFields(稍后您将看到)。

在 initState 中调用函数:

  @override
  void initState() {
    super.initState();
    textEditingController1 = TextEditingController();
    initSmsListener();
  }
Run Code Online (Sandbox Code Playgroud)

您应该在 dispose 函数中处置任何不使用的内容:

  @override
  void dispose() {
    textEditingController1.dispose();
    AltSmsAutofill().unregisterListener();
    super.dispose();
  }
Run Code Online (Sandbox Code Playgroud)

然后,您需要将 pinfields 放入构建函数中或像这样的列中:

PinCodeTextField(
          appContext: context,
          pastedTextStyle: TextStyle(
            color: Colors.green.shade600,
            fontWeight: FontWeight.bold,
          ),
          length: 6,
          obscureText: false,
          animationType: AnimationType.fade,
          pinTheme: PinTheme(
            shape: PinCodeFieldShape.box,
            borderRadius: BorderRadius.circular(10),
            fieldHeight: 50,
            fieldWidth: 40,
            inactiveFillColor: Colors.white,
            inactiveColor: ColorUtils.greyBorderColor,
            selectedColor: ColorUtils.greyBorderColor,
            selectedFillColor: Colors.white,
            activeFillColor: Colors.white,
            activeColor: ColorUtils.greyBorderColor
          ),
          cursorColor: Colors.black,
          animationDuration: Duration(milliseconds: 300),
          enableActiveFill: true,
          controller: textEditingController1,
          keyboardType: TextInputType.number,
          boxShadows: [
            BoxShadow(
              offset: Offset(0, 1),
              color: Colors.black12,
              blurRadius: 10,
            )
          ],
          onCompleted: (v) {
            //do something or move to next screen when code complete
          },
          onChanged: (value) {
            print(value);
            setState(() {
              print('$value');
            });
          },
        ),
Run Code Online (Sandbox Code Playgroud)

确保将控制器设置为 pinfield 小部件,并在收到短信后使用字符串索引将代码设置为文本字段。例如,请参见下图。 在此输入图像描述


AVE*_*imi 5

您可以使用此包: https: //pub.dev/packages/sms_autofill

但请考虑以下限制:

Android SMS 约束 对于要接收的代码,需要遵循此处描述的一些规则: https: //developers.google.com/identity/sms-retriever/verify

不超过 140 个字节 以前缀 <#> 开头 包含客户端发送回服务器以完成验证流程的一次性代码 以标识您的应用程序的 11 个字符的哈希字符串结尾 SMS 的一个示例是:

<#> 示例应用程序:您的代码是 123456 FA+9qCX9VSu