# Firebase + Flutter 簡單實作經驗筆記 Firebase是一個提供存取、帳戶應用、App監控的一個免費平台 >https://console.firebase.google.com/?hl=zh-cn 今天要操作的是使用Flutter實現在**Firebase上達成手機註冊、登入與監聽User**的部分。 * 一些小觀念提點 1. 在firebase當中再實現手機操作會分成是在 "手機端"、"Web" 的部分 ```dart= verifyPhoneNumber + signInWithCredential + PhoneAuthProvider.credential //手機端 signInWithPhoneNumber //Web端 ``` 2. 可以使用監聽的方式進行監控View跟model的部分ex. User是否登入登出。 > 接下來都是以你已經成功連接Flutter + firebase後的實例 > UI構成部分,就只要有簡單幾個輸入框跟按鈕即可 ### 1.創建一個能夠呼叫firebase函式庫的語法 ```dart= final _auth = FirebaseAuth.instance; //.instance為單例模式(此生命週期舊只會有這一次的new實例,其餘的創建都會是應用於這個實例 ``` ### 2.註冊帳號 1. 使用email + password 可以在controller的部分寫上註冊方法,並且創建AuthRepository實例呼叫當中的自訂方法createUserWithEnailAndPassword。 ``` dart= void registerUser(String email, String password) { AuthRepository authRepository = AuthRepository(); authRepository.createUserWithEnailAndPassword(email, password); } class AuthRepository extends ChangeNotifier{ ... Future<void> createUserWithEnailAndPassword( String email, String password, ) async { try { await _auth.createUserWithEmailAndPassword( email: email, password: password); } on FirebaseAuthException catch (e) { debugPrint(e.code); } catch (_) {} } } ``` 假如成功完成的話就會在你連結的firebase上出現帳戶 ![image](https://hackmd.io/_uploads/rykQCCk0T.png) 2. 手機註冊 >重點提醒! 不管註冊還是登入都會是走verifyPhoneNumber + signInWithCredential( PhoneAuthProvider.credential)的流程喔。 >假如執行到signInWithCredential(PhoneAuthProvider.credential)時沒有帳戶的話就會直接新增一個上去,有的話就會進入登入動作 1. verifyPhoneNumber先驗證手機正確性 **在完成呼叫verifyPhoneNumber之後他會傳OTP碼到你設定的phoneNumber當中** 所以可以再codesent的部分回傳一些東西或是使用Provider去監聽去改變頁面到輸入OTP碼的頁面。 >verificationId將會是接下來登入的ID要先存起來 ``` dart= void registerUserByPhone(String phoneNumber, BuildContext context) { AuthRepository authRepository = AuthRepository(); authRepository.phoneAuthentication(phoneNumber, context); } class AuthRepository with ChangeNotifier { final _auth = FirebaseAuth.instance; User? user = FirebaseAuth.instance.currentUser; String? verificationId; void updateVerificationId(var value) { verificationId = value; notifyListeners(); } ... ///手機號碼註冊帳號的方式 ///1. 先用verifyPhoneNumber先驗證手機正確性 ///2. 獲取到verificationId後再 ///3. 創建PhoneAuthCredential使用signInWithCredential進行登入或註冊 Future<void> phoneAuthentication( String phoneNumber, BuildContext context, ) async { final authVerify = Provider.of<AuthRepository>(context, listen: false); _auth.verifyPhoneNumber( phoneNumber: phoneNumber, verificationCompleted: (credential) async { debugPrint("我進入到了verificationCompleted"); await _auth.signInWithCredential(credential); }, verificationFailed: (exception) { debugPrint("firebase手機登入驗證,號碼失敗,$exception"); }, codeSent: (String verificationId, int? resendToken) async { debugPrint("firebase手機登入驗證,verificationId: $verificationId"); authVerify.updateVerificationId(verificationId); }, codeAutoRetrievalTimeout: (String verificationId) {}, ); } } ``` 2. 驗證OTP碼 + 登入(註冊) 將剛剛的verificationId與otp碼同時輸入給signInWithCredential(PhoneAuthProvider.credential())就完成登入(註冊)了。 ``` dart= void verifyOTP( String verificationId, String otp, BuildContext context, ) { AuthRepository authRepository = AuthRepository(); authRepository .verifyOTP( verificationId, otp, context, ) .then((value) { value ? debugPrint("OTP成功") : debugPrint("OTP失敗"); }); } class AuthRepository with ChangeNotifier { ... Future<bool> verifyOTP( String verificationId, String otp, BuildContext context, ) async { var credentials = await _auth.signInWithCredential( PhoneAuthProvider.credential( verificationId: verificationId, smsCode: otp), ); return credentials.user != null ? true : false; } } ``` ### 3.監聽的部分 因為不管是登入還是登出Firebase都會有一段小延遲時間,因此為了避免會有問題,就可以使用到監聽手段在UI更新頁面而去觸發其他的更新資料之類的。 >記得有使用到監聽就要去清除。 ``` dart= StreamSubscription<User?>? _authSubScription; @override void initState() { super.initState(); _authSubScription = FirebaseAuth.instance.authStateChanges().listen((User? user) { final userData = Provider.of<UserData>(context, listen: false); if (user == null) { userData.updateUserUuid(user?.uid); } else { userData.updateUserUuid(user.uid); } }); } @override void dispose() { _authSubScription!.cancel(); super.dispose(); } ``` 完整程式碼 https://drive.google.com/drive/folders/1n-iTPyvRCK3SEXicGSGg5ed6Tg1TsIqR?usp=sharing --- 參考資料 firebase文檔 https://firebase.google.com/docs/flutter/setup?hl=zh-cn&platform=android https://firebase.google.com/docs/auth/flutter/phone-auth?hl=zh-cn https://firebase.google.com/docs/auth/flutter/password-auth?hl=zh-cn youtube影片(內含GetX語法、但我自己是使用Provider) https://youtu.be/dGwr66EkJKk?si=EiJ9kVnAgsdW6IkK