Flutter一次性密码自动填充插件otp_autofill_plus的使用
Flutter一次性密码自动填充插件otp_autofill_plus的使用
otp_autofill_plus
是一个用于在Flutter应用中实现一次性密码(OTP)自动填充的插件。它利用了Android的SMS User Consent API和SMS Retriever API以及iOS内置的文本字段自动填充功能。
描述
该插件允许你通过监听短信来自动填充一次性密码,支持自定义策略以从其他输入源获取验证码(例如推送通知)。
iOS
在iOS上,OTP自动填充是内置于TextField
中的。短信内容必须包含单词“code”或其翻译,并且短信中只能有一个数字序列。
iOS测试
iOS可以从任何其他号码接收验证码。
Android
在Android上,插件提供了多种方法来启动监听验证码的功能:
OTPInteractor.hint
:显示系统对话框以选择保存的电话号码。OTPInteractor.getAppSignature
:创建应用程序的哈希码,用于SMS Retriever API。OTPInteractor.startListenUserConsent
和OTPInteractor.startListenRetriever
:开始监听来自Google服务的验证码,持续5分钟。OTPInteractor.stopListenForCode
:在dispose时使用。
安装
在pubspec.yaml
文件中添加依赖:
dependencies:
otp_autofill_plus: ^当前版本号
确保Android项目的minSdkVersion
至少为21:
android {
...
defaultConfig {
...
minSdkVersion 21
...
}
...
}
使用示例
创建简单策略
class SampleStrategy extends OTPStrategy {
@override
Future<String> listenForCode() {
return Future.delayed(
const Duration(seconds: 4),
() => 'Your code is 54321',
);
}
}
初始化监听器并设置
import 'package:flutter/material.dart';
import 'package:otp_autofill_plus/otp_autofill_plus.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
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();
print('Your app signature: $appSignature');
}
@override
void dispose() {
controller.stopListen();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Plugin example app'),
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(40),
child: TextField(
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
controller: controller,
),
),
),
),
);
}
}
发送新代码
当超时异常发生时,可以重新启动监听以获取新的验证码:
controller = OTPTextEditController(
codeLength: 5,
onCodeReceive: (code) => print('Your Application receive code - $code'),
otpInteractor: _otpInteractor,
onTimeOutException: () {
controller.startListenUserConsent(
(code) {
final exp = RegExp(r'(\d{5})');
return exp.stringMatch(code ?? '') ?? '';
},
strategies: [
SampleStrategy(),
],
);
},
)..startListenUserConsent(
(code) {
final exp = RegExp(r'(\d{5})');
return exp.stringMatch(code ?? '') ?? '';
},
strategies: [
SampleStrategy(),
],
);
以上是一个完整的示例demo,展示了如何在Flutter应用中使用otp_autofill_plus
插件来实现一次性密码的自动填充功能。
更多关于Flutter一次性密码自动填充插件otp_autofill_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter一次性密码自动填充插件otp_autofill_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于otp_autofill_plus
插件在Flutter中的使用,以下是一个简单的代码示例,展示了如何集成和使用这个插件来实现一次性密码(OTP)的自动填充功能。
首先,确保你已经在pubspec.yaml
文件中添加了otp_autofill_plus
依赖:
dependencies:
flutter:
sdk: flutter
otp_autofill_plus: ^x.y.z # 请替换为最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,是一个完整的Flutter应用示例,展示了如何使用otp_autofill_plus
:
import 'package:flutter/material.dart';
import 'package:otp_autofill_plus/otp_autofill_plus.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'OTP Autofill Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: OtpScreen(),
);
}
}
class OtpScreen extends StatefulWidget {
@override
_OtpScreenState createState() => _OtpScreenState();
}
class _OtpScreenState extends State<OtpScreen> {
final TextEditingController _controller1 = TextEditingController();
final TextEditingController _controller2 = TextEditingController();
final TextEditingController _controller3 = TextEditingController();
final TextEditingController _controller4 = TextEditingController();
final TextEditingController _controller5 = TextEditingController();
final TextEditingController _controller6 = TextEditingController();
@override
void dispose() {
_controller1.dispose();
_controller2.dispose();
_controller3.dispose();
_controller4.dispose();
_controller5.dispose();
_controller6.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('OTP Autofill Demo'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextField(
controller: _controller1,
keyboardType: TextInputType.number,
maxLength: 1,
decoration: InputDecoration(
labelText: '1',
border: OutlineInputBorder(),
),
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
onSubmitted: (value) {
FocusScope.of(context).requestFocus(_controller2.focusNode);
},
),
TextField(
controller: _controller2,
keyboardType: TextInputType.number,
maxLength: 1,
decoration: InputDecoration(
labelText: '2',
border: OutlineInputBorder(),
),
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
onSubmitted: (value) {
FocusScope.of(context).requestFocus(_controller3.focusNode);
},
),
TextField(
controller: _controller3,
keyboardType: TextInputType.number,
maxLength: 1,
decoration: InputDecoration(
labelText: '3',
border: OutlineInputBorder(),
),
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
onSubmitted: (value) {
FocusScope.of(context).requestFocus(_controller4.focusNode);
},
),
TextField(
controller: _controller4,
keyboardType: TextInputType.number,
maxLength: 1,
decoration: InputDecoration(
labelText: '4',
border: OutlineInputBorder(),
),
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
onSubmitted: (value) {
FocusScope.of(context).requestFocus(_controller5.focusNode);
},
),
TextField(
controller: _controller5,
keyboardType: TextInputType.number,
maxLength: 1,
decoration: InputDecoration(
labelText: '5',
border: OutlineInputBorder(),
),
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
onSubmitted: (value) {
FocusScope.of(context).requestFocus(_controller6.focusNode);
},
),
TextField(
controller: _controller6,
keyboardType: TextInputType.number,
maxLength: 1,
decoration: InputDecoration(
labelText: '6',
border: OutlineInputBorder(),
),
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
onEditingComplete: () {
// OTP entered completely, perform action
String otp = _controller1.text +
_controller2.text +
_controller3.text +
_controller4.text +
_controller5.text +
_controller6.text;
print('OTP: $otp');
},
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
// Simulate fetching OTP
// Here you would typically request an OTP from your server
// and display it to the user via SMS/Email/etc.
// For demo purposes, we'll just simulate filling the OTP
await OtpAutofill.fillOtp(
context,
code: '123456',
message: 'Your OTP is 123456',
);
},
child: Text('Simulate OTP'),
),
],
),
),
);
}
}
在这个示例中,我们创建了六个TextField
来分别接收OTP的每一位数字。每个TextField
都设置了maxLength
为1,并且只接受数字输入。当用户输入完一个数字后,焦点会自动跳转到下一个TextField
。当最后一个TextField
完成编辑时,会拼接所有的数字并打印出来。
此外,我们还添加了一个按钮来模拟OTP的填充。在实际应用中,这个按钮可能会触发向用户发送OTP的操作(如通过SMS)。在这个示例中,我们直接调用OtpAutofill.fillOtp
方法来模拟填充OTP。
请注意,为了使OtpAutofill.fillOtp
方法正常工作,你的应用需要满足一些条件,比如正确的Android和iOS配置,以及正确的SMS检索权限等。这些配置通常涉及到操作系统的特定设置和权限请求,具体细节可以参考otp_autofill_plus
的官方文档。