颤振:如何倾听FirebaseUser的电子邮件?
我的想法: 我想在flatter中使用Firebase Auth插件来注册用户。 但在他们可以访问应用程序之前,他们必须验证自己的电子邮件地址。 因此,我将注册后的Firebase用户推送到验证屏幕。这只是一个加载屏幕,告诉用户他必须验证他的电子邮件 但是现在:如果用户的电子邮件经过验证与否,我如何持续收听,并将其发送到主屏幕(如果是真的) 我是个新手,不知道是否需要使用Streams、Observables、while循环、setState()或其他方法来进行布尔检查。我也不知道如何设置解决方案 这是我注册用户的基本代码:颤振:如何倾听FirebaseUser的电子邮件?,firebase,flutter,dart,firebase-authentication,state-management,Firebase,Flutter,Dart,Firebase Authentication,State Management,我的想法: 我想在flatter中使用Firebase Auth插件来注册用户。 但在他们可以访问应用程序之前,他们必须验证自己的电子邮件地址。 因此,我将注册后的Firebase用户推送到验证屏幕。这只是一个加载屏幕,告诉用户他必须验证他的电子邮件 但是现在:如果用户的电子邮件经过验证与否,我如何持续收听,并将其发送到主屏幕(如果是真的) 我是个新手,不知道是否需要使用Streams、Observables、while循环、setState()或其他方法来进行布尔检查。我也不知道如何设置解决方
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:async';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
final Firestore _db = Firestore.instance;
Future<FirebaseUser> get getUser => _auth.currentUser();
Stream<FirebaseUser> get user => _auth.onAuthStateChanged;
Future<FirebaseUser> edubslogin(String email, String password) async {
try {
final FirebaseUser user = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
await user.sendEmailVerification();
//email verification somewhere here
updateUserData(user);
return user;
} catch (error) {
print(error);
return null;
}
}
但是我没有从isEmailVerified
中得到布尔值true
我该怎么办?此验证并不像您希望的那样简单。首先,存在识别用户已验证其电子邮件的问题。第二个问题是,没有任何类型的通知可以自动触发应用程序中的更改 检查此线程以获取有关emailVerified的信息: 我只能在以下情况下验证用户:1)创建了他们的帐户,2)让他们登录,3)然后检查以确保他们验证了他们的电子邮件
final FirebaseAuth _auth = FirebaseAuth.instance;
var _authenticatedUser = await _auth.signInWithEmailAndPassword(email: _email, password: _password);
//where _email and _password were simply what the user typed in the textfields.
if (_authenticatedUser.isEmailVerified) {
//Verified
} else {
//Not verified
}
第2部分:如何让应用程序识别用户已确认其电子邮件?找到一种方法来触发检查确认的函数。一个按钮就足够容易了。如果您想让它显示“自动”,那么我想您可以创建一个计时器,每隔10秒左右检查电子邮件验证。我找到了一种方法,更新firebase用户配置文件并在
init()中调用它,如下面的函数所示
void _checkEmailVerification() async {
await widget.auth.getCurrentUser().then((user) {
UserUpdateInfo userUpdateInfo = new UserUpdateInfo();
userUpdateInfo.displayName = user.displayName;
user.updateProfile(userUpdateInfo).then((onValue) {
setState(() {
_isEmailVerified = user.isEmailVerified;
});
});
});
}
我只是在我的应用程序中遇到了同样的情况。我的解决方案是在策略路由的initState方法中创建一个周期计时器,在验证电子邮件之前保持应用程序。它没有使用监听器那么优雅,但效果很好
bool _isUserEmailVerified;
Timer _timer;
@override
void initState() {
super.initState();
// ... any code here ...
Future(() async {
_timer = Timer.periodic(Duration(seconds: 5), (timer) async {
await FirebaseAuth.instance.currentUser()..reload();
var user = await FirebaseAuth.instance.currentUser();
if (user.isEmailVerified) {
setState((){
_isUserEmailVerified = user.isEmailVerified;
});
timer.cancel();
}
});
});
}
@override
void dispose() {
super.dispose();
if (_timer != null) {
_timer.cancel();
}
}
我创建了一个流来处理这个问题。不是很优雅,但很管用。使用StreamProvider.value()来处理事件
Stream<userVerificationStatus> checkUserVerified() async* {
bool verified = false;
yield userVerificationStatus(status: Status.LOADING);
while (!verified) {
await Future.delayed(Duration(seconds: 5));
FirebaseUser user = await _auth.currentUser();
if(user!=null)await user.reload();
if (user == null) {
yield userVerificationStatus(status: Status.NULL);
} else {
print("isemailverified ${user.isEmailVerified}");
await user.reload();
verified = user.isEmailVerified;
if(verified)
yield userVerificationStatus(status: Status.VERIFIED);
else
yield userVerificationStatus(status: Status.NOT_VERIFIED);
}
}
}
流checkUserVerified()异步*{
bool-verified=false;
产生userVerificationStatus(状态:status.LOADING);
而(!已验证){
等待未来。延迟(持续时间(秒:5));
FirebaseUser=等待_auth.currentUser();
如果(user!=null)等待user.reload();
if(user==null){
产生userVerificationStatus(状态:status.NULL);
}否则{
打印(“isemailverified${user.isemailverified}”);
等待user.reload();
已验证=user.isEmailVerified;
如果(已验证)
生成userVerificationStatus(状态:status.VERIFIED);
其他的
生成userVerificationStatus(状态:status.NOT\u VERIFIED);
}
}
}
由于authOnChanged
只侦听登录和注销操作,因此在您的登录方法中,首先注销,然后尝试登录
await _firebaseAuth.signOut();
authResult = await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
return authResult.user;
在onAuthChanged
中,当您控制用户.isEmailVerified时,它将在您注销后工作,即使您尚未登录,它也会更新用户,因为即使您尚未登录,注销也会触发您的onAuthChanged
这就像作弊,但我发现的唯一没有超时的方法是这样。为了让应用程序识别用户是否验证了他们的电子邮件,你可以通过一个简单的用户来实现。重新加载 为了亲自测试,请使用按下的代码执行一个按钮:
FlatButton(
child: Text("check"),
textColor: Colors.white,
onPressed: () async {
try {
FirebaseUser user = await _firebaseAuth.currentUser();
await user.reload();
user = await _firebaseAuth.currentUser();
print( user.isEmailVerified);
} catch (e) {
return e.message;
}
}),
身份验证状态更改侦听器对我无效。即使用户验证了他的电子邮件,字段
isEmailVerified
仍然保持false
我的解决方法:
假设用户离开应用程序以验证其电子邮件(这意味着应用程序已暂停),并在验证后返回应用程序(应用程序恢复)
我所做的是将一个WidgetsBinding
附加到一个相关的有状态小部件上,在那里我想显示电子邮件是否经过验证(但可以在其他地方完成)。这包括两个步骤
第一步是附加绑定:
@覆盖
void initState(){
WidgetsBinding.instance.addObserver(这个);
super.initState();
}
@凌驾
无效处置(){
WidgetsBinding.instance.removeObserver(此);
super.dispose();
}
第二步是重写didChangeAppLifecycleState
以重新加载用户。我创建了一个函数来重新加载并设置一个新的firebaseUser对象
void didchangeappifecyclestate(AppLifecycleState状态){
if(state==AppLifecycleState.resume&&!firebaseUser.isEmailVerified)
refreshFirebaseUser()。然后((值)=>setState((){}));
super.didChangeAppLifecycleState(州);
}
Future refreshFirebaseUser()异步{
等待firebaseUser.reload();
firebaseUser=FirebaseAuth.instance.currentUser;
}
因此,这基本上是在用户每次返回应用程序时重新加载firebase用户对象,而其电子邮件未经验证。我选择了这个解决方案,而不是设置和取消计时器,因为它避免了通过计时器设置重复操作,这对于这个特定的问题来说可能是过度的。正确。如果用户验证其电子邮件,FirebaseAuth
idTokenChanges()
、authStateChanges()
或userChanges()
都不会向您发送事件。我正在使用多种方法在我的应用程序中获得电子邮件验证更新,它似乎运行良好
首先,我在initState()方法中检查状态,如果电子邮件未被验证,则启动计时器
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
//Get Authenticated user
user = context.read<AuthenticationService>().currentUser();
_isEmailVerified = user.emailVerified;
if (!_isEmailVerified) _startEmailVerificationTimer();
}
这是_startEmailVerificationTimer()方法
我的Firebase用户方法,以防任何人感兴趣:
User currentUser() {
return _firebaseAuth.currentUser;
}
User reloadCurrentUser() {
User oldUser = _firebaseAuth.currentUser;
oldUser.reload();
User newUser = _firebaseAuth.currentUser;
return newUser;
}
我对firebase auth的最新版本也有同样的问题 但是我发现
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
user = context.read<AuthenticationService>().reloadCurrentUser();
if (user.emailVerified) {
setState(() {
_isEmailVerified = user.emailVerified;
});
timer?.cancel();
} else {
if (!timer.isActive) _startEmailVerificationTimer();
}
}
}
_startEmailVerificationTimer() {
timer = Timer.periodic(Duration(seconds: 5), (Timer _) {
user = context.read<AuthenticationService>().reloadCurrentUser();
if (user.emailVerified) {
setState(() {
_isEmailVerified = user.emailVerified;
});
timer.cancel();
}
});
}
@override
void dispose() {
timer?.cancel();
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
User currentUser() {
return _firebaseAuth.currentUser;
}
User reloadCurrentUser() {
User oldUser = _firebaseAuth.currentUser;
oldUser.reload();
User newUser = _firebaseAuth.currentUser;
return newUser;
}