Flutter bloc 和 Firebase 电话身份验证
Posted
技术标签:
【中文标题】Flutter bloc 和 Firebase 电话身份验证【英文标题】:Flutter bloc and Firebase phone auth 【发布时间】:2019-08-05 14:07:43 【问题描述】:enter code here
我正在尝试创建一个使用 Firebase 电话身份验证的 LoginBloc。我为phoneNumber、smsCode 和verificationId 创建了一个StreamController。我想借助 Bloc 模式在 VerificationNumber() 方法中动态添加它们的值。这是 verifyNumber() 中的 LoginBloc:
class LoginBloc extends Object with AuthValidator implements BlocBase
String _phone;
String _sms;
String _verifId;
StreamController<String> _phoneController=StreamController<String>.broadcast();
//Sink<String> get _addPhone=>_phoneController.sink;
Stream<String> get getPhone=>_phoneController.stream.transform(validatePhone);
StreamController<String> _codeController=StreamController<String>.broadcast();
Stream<bool> get registerValid => Observable.combineLatest2(getPhone,getPhone
,(e, p) =>true);
//Sink<String> get _addCode=>_phoneController.sink;
Stream<String> get getCode=>_phoneController.stream.transform(validatePhone);
Function(String) get onPhoneChanged => _phoneController.sink.add;
StreamController<String> _verificationIdController=StreamController<String>.broadcast();
Sink<String> get _addVerification=>_verificationIdController.sink;
Stream<String> get getVerification=>_verificationIdController.stream;
@override
void dispose()
_phoneController.close();
_codeController.close();
_verificationIdController.close();
Future<void> verifyPhone(String phone, String verifId,String sms) async
_phone=phone;
_sms=sms;
_verifId=verifId;
final PhoneCodeAutoRetrievalTimeout autoRetrieve=(String verId)
_verifId=verId;
_addVerification.add(_verifId);
;
final PhoneCodeSent smsCodeSent=(String verId,[int forceCodeRetrieve])
_verifId=verId;
_addVerification.add(_verifId);
;
final PhoneVerificationCompleted phoneVerificationCompleted=(FirebaseUser user)
print("User $user");
;
final PhoneVerificationFailed phoneVerificationFailed=(AuthException exception)
print("Error $exception");
;
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: _phone,
timeout: Duration(minutes: 1),
verificationCompleted: phoneVerificationCompleted,
verificationFailed: phoneVerificationFailed,
codeSent: smsCodeSent,
codeAutoRetrievalTimeout: autoRetrieve);
LoginBloc loginBloc=LoginBloc();
【问题讨论】:
【参考方案1】:我现在有一个工作解决方案: 这是 login_bloc:
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:phone_auth_bloc/services/auth/authentification.dart';
import 'package:rxdart/rxdart.dart';
import 'package:bloc_pattern/bloc_pattern.dart';
class LoginBloc implements BlocBase
final Authentification _authentification = new Authentification();
final _phoneControler = new BehaviorSubject<String>();
Observable<String> get phoneStream => _phoneControler.stream;
Sink<String> get phoneEvent => _phoneControler.sink;
final _smsControler = new BehaviorSubject<String>();
Observable<String> get smsStream => _phoneControler.stream;
Sink<String> get smsEvent => _phoneControler.sink;
var _controllerLoading = new BehaviorSubject<bool>(seedValue: false);
Stream<bool> get outLoading => _controllerLoading.stream;
final BuildContext context;
LoginBloc(this.context);
onClickPhone() async
print(_phoneControler.value);
_controllerLoading.add(!_controllerLoading.value);
await _authentification.verifyPhoneNumber(_phoneControler.value);
_controllerLoading.add(!_controllerLoading.value);
Future<bool> onClickSms() async
print(_phoneControler.value);
_controllerLoading.add(!_controllerLoading.value);
bool isAuth = await _authentification.signWithPhone(
_authentification?.verificationId, _smsControler.value);
_controllerLoading.add(!_controllerLoading.value);
print(isAuth);
return isAuth;
@override
void dispose()
_controllerLoading?.close();
_phoneControler?.close();
_smsControler?.close();
和班级女巫交流:
class Authentification
final _firebaseAuth= FirebaseAuth.instance;
String verificationId;
Future<bool> signWithPhone(String verifiId,String smsCode) async
verificationId=verifiId;
print(verificationId);
final resultLogin=await _firebaseAuth.signInWithPhoneNumber(verificationId: verificationId, smsCode: smsCode);
if(resultLogin?.uid!=null)
return true;
else
return false;
Future verifyPhoneNumber(String phone)async
await _firebaseAuth.verifyPhoneNumber(
phoneNumber: phone,
timeout: Duration(seconds: 30),
verificationCompleted: (FirebaseUser user)
print("User: "+user?.uid);
,
verificationFailed: (AuthException authException)
print("exception: $authException");
,
codeSent: (String verifId,[int forceSent])
print("verificannId: $verifId");
verificationId=verifId;
,
codeAutoRetrievalTimeout: (String timeOut)
print("Time out: "+timeOut);
);
之后,您可以在 Ui 中调用 bloc,这是我的情况:
class AuthForm extends StatefulWidget
@override
_AuthFormState createState() => _AuthFormState();
class _AuthFormState extends State<AuthForm>
@override
Widget build(BuildContext context)
LoginBloc loginBloc = BlocProvider.of<LoginBloc>(context);
navigateTOnext()
loginBloc.onClickPhone().then((v)
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (BuildContext context) =>SmsCode()
),);
// else
// Center(child: CircularProgressIndicator());
//
);
return Scaffold(
appBar: AppBar(
title: Text("formulaire d'authentification"),
),
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
onChanged:loginBloc.phoneEvent.add,
onSubmitted:(String value) =>loginBloc.onClickPhone,
maxLength: 13,
keyboardType: TextInputType.phone,
decoration: InputDecoration(labelText: "Phone number"),
),
RaisedButton(
onPressed: navigateTOnext,
child: Text("verifier"),
),
],
),
),
);
【讨论】:
很好的例子。 ui 中的这一行builder: (BuildContext context) =>SmsCode()
不清楚。你能澄清一下 SmsCode() 方法在做什么吗?
builder: (BuildContext context) =>SmsCode() 它只是一个等待短信发送到电话号码的另一个 UI 屏幕。以上是关于Flutter bloc 和 Firebase 电话身份验证的主要内容,如果未能解决你的问题,请参考以下文章
Stream/Bloc/Repository/Firebase 数据流 Flutter
使用 BLoC 进行 Flutter Firebase 电话身份验证
如何将 Flutter Bloc 与 Firebase 电话身份验证一起使用
Flutter Bloc 与 firebase 查询有多种关系