# 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上出現帳戶

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