Flutter电话号码快速登录插件easy_phone_sign_in的使用
Flutter电话号码快速登录插件easy_phone_sign_in的使用
此Flutter包旨在简化Google电话登录功能在应用中的集成,使其过程无缝且高效。
特性
- 与Google登录轻松集成
- 支持Android和iOS平台
- 提供简洁的UI用于手机号码输入和验证
安装
要使用此包,请在pubspec.yaml
文件中添加phone_sign_in
依赖:
dependencies:
phone_sign_in: ^x.x.x
并根据Firebase电话认证设置进行设置。
调试
如果在PhoneSignIn
小部件中将debug
设置为true
,该小部件将在控制台中显示调试消息。这对于调试非常有用。
手机号输入
如果用户的手机号以+
开头,则用户输入的手机号将被视为国际格式。在这种情况下,应用会忽略选定的国家信息,并使用用户输入的手机号进行登录。
例如,如果用户选择国家为“菲律宾”,然后输入类似+1 1111 1111 11
的美国手机号码,则尽管国家选择设置为“菲律宾”,它会忽略这一点,并尝试使用用户输入的手机号码+1 1111 1111 11
进行Firebase登录。
如果手机号以0
开头,则会被移除。因此,在检查手机号码时,不要让它以0
开头。
国家选择选项
-
countryPickerOptions
:允许用户选择国家。 -
如果省略此选项,则小部件不会在屏幕上显示国家选择。
- 如果不需要国家选择?
- 可能因为你只需要在应用中使用一个国家代码。
- 或者,用户可以与手机号一起输入国家代码,如
+82
。
- 如果不需要国家选择?
-
moveAlongWithKeyboard
:默认情况下,搜索结果可能会被键盘隐藏。将其设置为true
,则结果不会被键盘遮挡。
固定国家代码
启用此选项后,将隐藏选择国家代码的按钮,并将国家代码固定为一个固定的值。因此,用户无法更改国家选择。
Firebase认证语言代码
firebaseAuthLanguageCode
是Firebase电话登录使用的默认语言。这与Firebase Auth中使用的选项相同。
完整手机号码回调
PhoneSignIn
小部件会自动将用户输入的手机号格式化为国际号码,基于所选国家。
但是,如果你希望自定义国际手机号码,可以利用onCompletePhoneNumber
回调。当小部件需要国际格式的手机号码时,会调用此函数。它只会传递用户输入的手机号码,不包括国家代码。因此,如果你想使用用户选择的国家代码,应避免设置此回调函数,让小部件自动构建国际手机号码。
你可能希望通过自动添加国家代码来简化用户流程。例如,在韩国,手机号码总是以010
开头,在菲律宾,它们总是以09
开头。因此,如果用户输入他们的手机号码为01012345678
,你可以通过程序将其更新为+821012345678
转换为国际格式。同样,如果用户输入他们的手机号码为091212345678
,你可以将其更新为+6391212345678
。
此函数主要用于当未指定countryPickerOptions
和countryCode
时。在这种情况下,由于用户无法在屏幕上选择国家代码,因此用于通过程序添加国家代码。
注意,如果用户输入的手机号以+
开头,onCompletePhoneNumber
函数不会被调用。换句话说,小部件识别用户的输入为完整的国际手机号码,不会调用onCompletePhoneNumber
函数将其转换为国际格式。
因此,如果未指定countryPickerOptions
和countryCode
,并且用户未输入以+
开头的手机号,onCompletePhoneNumber
将被调用并返回国际格式的手机号。
onCompletePhoneNumber
函数接收用户输入的手机号,去除不必要的特殊字符。如果手机号以0
开头,它将被移除。例如,如果用户输入010-1111-2222
,则1011112222
作为参数传递。
当前用户链接
如果linkCurrentUser
设置为true
,它将尝试将当前用户帐户链接到提供的电话登录凭据。如果提供的电话登录账户已存在,则只执行正常登录现有账户。如果用户尚未登录,则仅执行正常登录。
请注意,当用户以电话号码登录时,他不能与另一个电话号码凭证链接。更多详情请参阅Firebase Auth文档。
是否手机号码已注册
当linkCurrentUser
设置为true
时,必须设置此回调函数,并返回true
表示手机号码已注册。
显示手机号码回调
onDisplayPhoneNumber
是一个回调函数,返回要在屏幕上显示的手机号码。onCompletePhoneNumber
函数返回的值用于Firebase电话登录,但此函数返回的手机号码只是以用户友好的格式显示在屏幕上。
例如,如果只有韩国人注册,你可以通过countryCode
选项将国家代码固定为+82
。在这种情况下,显示为010-1234-5678
而不是+821012345678
更符合用户习惯。这就是这个函数的作用。
特别是在输入手机号码并发送短信验证码之后,你需要在屏幕上显示手机号码。你可以使用此函数以用户友好的格式显示手机号码。
onDisplayPhoneNumber
函数接收国际手机号码。更准确地说,它接收onCompletePhoneNumber
函数返回的值。
无国家代码选择器
如果应用未设置countryCode
和countryPickerOption
,则小部件无法生成国际手机号码。而且,用户无法选择国家。但是,用户可以通过手动输入国际手机号码来实现。
错误处理
如果发生错误,onSignInFailed
回调函数将被调用,并将FirebaseAuthException
作为参数传递。你可以使用此错误参数适当地通知用户错误消息。
PhoneSignIn(
onSignInFailed: (FirebaseAuthException e) {
if (e.code == 'web-context-cancelled') {
print('The interaction was cancelled by the user.');
} else if (e.code == 'missing-client-identifier') {
print("We couldn't verify your phone number at the moment. Please ensure you entered a valid phone number and try again.");
} else if (e.code == 'too-many-requests') {
print('We have blocked all requests from this device due to unsual activity. Please try again later');
} else if (e.code == 'invalid-verification-code') {
print('Oops! Incorrect code, Please double-check the code sent to your phone and try again.');
} else {
print('FirebaseAuthException : $e');
throw e;
}
}
)
示例
以下是包含国家选择的完整示例代码。您可以自由复制、粘贴并根据您的应用需求进行调整。
Padding(
padding: const EdgeInsets.symmetric(horizontal: sm),
child: PhoneSignIn(
labelCountryPicker: Padding(
padding: const EdgeInsets.only(bottom: xxs),
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 24, 0, 8),
child: Text(
'1. 选择国家',
style: context.titleLarge,
),
),
),
labelCountryPickerSelected: Padding(
padding: const EdgeInsets.only(bottom: xxs),
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 24, 0, 8),
child: Text(
'1. 选择国家',
),
),
),
labelEmptyCountry: Container(
decoration: BoxDecoration(
border: Border.all(
color: context.colorScheme.onSurface,
width: 1.8,
),
borderRadius: BorderRadius.circular(16),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text('选择国家描述'),
),
),
labelChangeCountry: Padding(
padding: const EdgeInsets.fromLTRB(0, 8, 0, 8),
child: Text('更改国家'),
),
labelPhoneNumber: Padding(
padding: const EdgeInsets.fromLTRB(0.0, 48, 0, 8.0),
child: Text(
'2. 输入您的手机号码',
style: context.titleLarge,
),
),
labelPhoneNumberSelected: Padding(
padding: const EdgeInsets.only(top: 48),
child: Text('2. 电话号码'),
),
hintTextPhoneNumberTextField: '电话号码',
labelOnSmsCodeTextField: Padding(
padding: const EdgeInsets.fromLTRB(0, 48, 0, 8),
child: Text(
'3. 输入短信验证码',
style: context.titleLarge,
),
),
hintTextSmsCodeTextField: '短信验证码',
labelVerifyPhoneNumberButton: Text('验证电话号码'),
labelVerifySmsCodeButton: Text('验证短信验证码'),
labelRetry: Text('重试'),
linkCurrentUser: true,
onSignInSuccess: afterSignIn,
onSignInFailed: onSignInFailed,
countryPickerOptions: const CountryPickerOptions(
favorite: ['US', 'KR'],
),
specialAccounts: const SpecialAccounts(
reviewEmail: 'review@email.com',
reviewPassword: '12345zB,*c',
reviewPhoneNumber: '+11234567890',
reviewSmsCode: '123456',
emailLogin: true,
),
),
)
/// 清理之前匿名用户,登录到现有账户。
///
afterSignIn() async {
if (context.mounted) {
context.pop();
}
}
onSignInFailed(FirebaseAuthException e) {
print('onSignInFailed() -> FirebaseAuthException : $e');
if (e.code == 'web-context-cancelled') {
// 交互被用户取消
error(
context: context,
message: Text('登录被取消'),
);
} else if (e.code == 'missing-client-identifier') {
error(
context: context,
message: Text('您的电话号码无法验证。请确保您输入了正确的电话号码并重试。'),
);
} else if (e.code == 'too-many-requests') {
error(
context: context,
message: Text('由于多次尝试,所有来自此设备的请求都被阻止。请稍后再试。'),
);
} else if (e.code == 'invalid-verification-code') {
error(
context: context,
message: Text('哦!验证码错误。请检查发送到您手机上的验证码并重试。'),
);
} else if (e.code == 'invalid-phone-number') {
error(
context: context,
message: const Text('无效的电话号码'),
);
} else {
print('FirebaseAuthException : $e');
throw e;
}
}
异常
当用户输入无效手机号码时,会抛出以下异常:
Exception: [@phone_sign_in](/user/phone_sign_in)/malformed-phone-number Phone number is empty or malformed.
更多关于Flutter电话号码快速登录插件easy_phone_sign_in的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter电话号码快速登录插件easy_phone_sign_in的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用easy_phone_sign_in
插件实现电话号码快速登录的示例代码。easy_phone_sign_in
插件使得集成电话号码登录变得简单,通常用于Firebase身份验证服务。
首先,确保你已经在pubspec.yaml
文件中添加了easy_phone_sign_in
依赖:
dependencies:
flutter:
sdk: flutter
easy_phone_sign_in: ^最新版本号 # 请替换为实际最新版本号
然后运行flutter pub get
来获取依赖。
接下来,你需要配置Firebase项目以支持电话号码身份验证。这通常涉及在Firebase控制台中启用电话号码身份验证功能,并可能需要进行一些验证步骤(例如,通过短信验证)。
以下是一个基本的Flutter应用程序示例,展示了如何使用easy_phone_sign_in
插件进行电话号码登录:
import 'package:flutter/material.dart';
import 'package:easy_phone_sign_in/easy_phone_sign_in.dart';
import 'package:firebase_auth/firebase_auth.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Phone Sign In Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: PhoneSignInScreen(),
);
}
}
class PhoneSignInScreen extends StatefulWidget {
@override
_PhoneSignInScreenState createState() => _PhoneSignInScreenState();
}
class _PhoneSignInScreenState extends State<PhoneSignInScreen> {
final EasyPhoneSignIn _easyPhoneSignIn = EasyPhoneSignIn();
String _verificationId;
String _smsCode;
String _phoneNumber = '+1'; // 默认国家代码,可以根据需要更改
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Phone Sign In'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
decoration: InputDecoration(
labelText: 'Phone Number',
prefixText: _phoneNumber,
border: OutlineInputBorder(),
),
keyboardType: TextInputType.phone,
onChanged: (value) {
setState(() {
_phoneNumber = _phoneNumber + value;
});
},
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
if (_phoneNumber.length <= 3) { // 简单验证,确保输入了至少一些数字
return;
}
// 发送验证码
await _easyPhoneSignIn.verifyPhoneNumber(
phoneNumber: _phoneNumber,
verificationCompleted: (AuthCredential credential) async {
// 自动验证完成(即时验证)
FirebaseAuth.instance.signInWithCredential(credential);
// 处理登录成功逻辑
},
verificationFailed: (FirebaseAuthException e) {
// 处理验证失败
print('Verification failed: ${e.message}');
},
codeSent: (String id, [String token]) {
// 保存验证码ID
setState(() {
_verificationId = id;
});
// 提示用户输入验证码
},
codeAutoRetrievalTimeout: (String id) {
// 自动检索验证码超时
setState(() {
_verificationId = id;
});
},
);
},
child: Text('Send Code'),
),
SizedBox(height: 20),
TextField(
decoration: InputDecoration(
labelText: 'SMS Code',
border: OutlineInputBorder(),
),
keyboardType: TextInputType.number,
onChanged: (value) {
setState(() {
_smsCode = value;
});
},
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
if (_verificationId == null || _smsCode.isEmpty) {
return;
}
// 使用验证码登录
AuthCredential credential = PhoneAuthProvider.credential(
verificationId: _verificationId,
smsCode: _smsCode,
);
await FirebaseAuth.instance.signInWithCredential(credential);
// 处理登录成功逻辑
print('Sign in successful');
},
child: Text('Sign In'),
),
],
),
),
);
}
}
在这个示例中,我们创建了一个简单的UI,允许用户输入他们的电话号码并发送验证码。用户收到验证码后,可以输入验证码并完成登录过程。这个示例代码涵盖了主要的步骤:发送验证码、处理验证码发送结果、以及使用验证码进行登录。
请确保在实际项目中处理更多的错误情况和边界情况,并根据需要调整UI和用户体验。