flutter 如何从SMS获取OTP-自动填充

xmakbtuz  于 2023-05-19  发布在  Flutter
关注(0)|答案(5)|浏览(370)

我想捕捉或读取短信的动态口令自动。我做了一些测试,像这样的代码:

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),
              ),
            ],
          ),
        )
    );
  }
}

这是测试短信:12345 is your code to log in.
oneTimeCode的Flutter文档:https://api.flutter.dev/flutter/services/AutofillHints/oneTimeCode-constant.html
Flutter自动填充:https://github.com/flutter/flutter/blob/7891006299/packages/flutter/lib/src/services/autofill.dart#L362
IOS:https://developer.apple.com/documentation/uikit/uitextcontenttype
Android:https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_SMS_OTP

zed5wv10

zed5wv101#

我希望我对那些仍在寻找这个问题答案的人来说还不算太晚。我使用了两个软件包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';

在你的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.
    });
  }

我收到的OTP消息格式如下所示:**您的手机验证码为625742。**在上述功能中,它正在收听传入的短信并将其保存为字符串。收到短信后,我通过在字符串中给出代码的索引位置来将“625742”代码设置到我的textEditing控制器中,然后将值设置到我的PinFields中,稍后您将看到。
调用initState中的函数:

@override
  void initState() {
    super.initState();
    textEditingController1 = TextEditingController();
    initSmsListener();
  }

你应该在dispose函数中处理任何你没有使用的东西:

@override
  void dispose() {
    textEditingController1.dispose();
    AltSmsAutofill().unregisterListener();
    super.dispose();
  }

然后你需要把pinfield放在你的构建函数中或者像这样的列中:

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');
            });
          },
        ),

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

o2g1uqev

o2g1uqev2#

您可以使用此软件包:https://pub.dev/packages/sms_autofill
但请考虑以下限制:
Android SMS约束对于要接收的代码,它需要遵循一些规则,如下所述:https://developers.google.com/identity/sms-retriever/verify
不超过140字节以前缀<#>开始包含客户端发送回服务器以完成验证流的一次性代码以标识您的应用的11个字符的哈希字符串结尾SMS的一个示例是:
<#> ExampleApp:您的代码是123456 FA+9 qCX 9VSu

oxalkeyp

oxalkeyp3#

我已经用这个package接收短信Check it

  • 它所做的是,它通过它的listner监听短信,当短信到达它打印短信。*

这是Code,我写了一段时间前(* 我不知道如果包做了一些更改或更新,因为我还没有使用它一段时间,但它是工作的时间pefectly。

SmsReceiver receiver = new SmsReceiver();
await receiver.onSmsReceived.listen((SmsMessage msg) => checkSMS(msg));
  • 打印SMS主体的方法,*
checkSMS(SmsMessage msg) async {
    print(msg.body);
  }

现在您可以自动填充SMS,并从msg.body中使用一些regex取出OTP,并将其设置为TextFieldController文本以进行自动填充。

注意:它将获取每一条短信,所以要获取你需要的唯一一条,你必须检查关键字或在你身边设置一些Regex,以只显示OTP消息,或消息中的公司名称。

8dtrkrch

8dtrkrch4#

@Kamrul Hasan Jony描述得很好。但有一件事应该记住是谁在实施这一点。在将OTP分配给控制器之前,您应该检查app_Signature或其他验证,以便OTP仅从特定的消息中获取。例如

setState(() {
  _commingSms = commingSms;
  String aStr = _commingSms.replaceAll(new RegExp(r'[^0-9]'),'');
  String otp = aStr.substring(0,4);
  if(_commingSms.contains(AppConstants.appSignature)){
    textEditingController.text = otp;
    //_presenter.validateOtp(widget.apiToken, widget.phone, textEditingController.text, context);
  }
});

此外,对于iOS AltSmsAutofill().listenForSms返回iOS版本(alt_sms_autofill:^1.0.0)。因此,如果您在将otp分配给控制器之前使用某种验证,则会删除所有内容。

pkwftd7m

pkwftd7m5#

我使用https://pub.dev/packages/sms_autofill包读取OTP -代码是Pinput(androidSmsAutofillMethod:AndroidSmsAutofillMethod .smsRetrieverApi,listenForMultipleSmsOnAndroid:真的,...
我在登录页面var appSignatureID = await SmsAutoFill().getAppSignature;我添加了这段代码,并在一个小部件中使用了这个appSignatureID变量来显示UI中的值-并在内部测试中添加了该版本,因此我可以在UI中获得应用程序签名ID,并注意到它。在那之后,我删除了显示在UI中的代码,并将该键发送到SMS模板的后端

相关问题