Flutter Google Sign-In v7.1.1 + Firebase Auth 安裝與設定完整指南(Android/iOS)
software-development
目錄
- 概述
- 技術棧
- 前置需求
- 步驟 1:安裝相依套件
- 步驟 2:Firebase Console 配置
- 2.1 啟用 Google Sign-In
- 2.2 配置 Android 應用
- 2.3 配置 iOS 應用
- 步驟 3:Android 平台設定
- 3.1 檢查 google-services.json
- 3.2 build.gradle 啟用 Google Services 插件
- 步驟 4:iOS 平台設定
- 4.1 更新 Info.plist(URL Scheme)
- 4.2 檢查 GoogleService-Info.plist OAuth 欄位
- 步驟 5:實作 AuthRepository
- 步驟 6:UI 介面實作
- 步驟 7:測試與驗證
- 7.1 執行測試
- 7.2 常見問題排除(FAQ)
- 7.3 最佳實踐
- 完整專案結構範例
- 結論
- 參考與延伸閱讀(官方技術文件)
- Firebase 與 Flutter
- 套件(pub.dev)
- Android 設定
- iOS 設定
Flutter Google Sign-In 完整安裝配置指南
本文基於實際開發經驗,詳細介紹如何在 Flutter 應用中正確配置 Google Sign-In 功能,包含 Android 和 iOS 平台的完整設定流程。
概述
Google Sign-In 是現代移動應用中最常用的第三方登入方式之一。本文將詳細介紹如何在 Flutter 應用中整合 Google Sign-In v7.1.1 版本與 Firebase Authentication,確保在 Android 和 iOS 平台上都能正常運作。
技術棧
- Flutter: 3.9.0+
- Firebase Auth: 5.3.2+
- Google Sign-In: 7.1.1
- Riverpod: 2.5.1(狀態管理)
前置需求
- Flutter 開發環境已設定完成
- Firebase 專案已建立
- Android 和 iOS 應用已在 Firebase Console 中註冊
步驟 1:安裝相依套件
在 pubspec.yaml 中添加必要的相依套件:
dependencies:
firebase_auth: ^5.3.2
google_sign_in: ^7.1.1
flutter_riverpod: ^2.5.1
dev_dependencies:
mockito: ^5.4.4 # 用於單元測試
執行安裝:
flutter pub get
步驟 2:Firebase Console 配置
2.1 啟用 Google Sign-In
- 前往 https://console.firebase.google.com 進入 Firebase Console
- 選擇你的專案
- 導航至 Authentication → Sign-in method
- 點擊 Google 並啟用
- 設定專案的公開名稱和支援電子郵件
2.2 配置 Android 應用
- 進入 Project Settings → General → Android App
- 添加 SHA 指紋證書
取得 SHA 指紋:
# Debug 金鑰
keytool -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore -storepass android -keypass android
# Release 金鑰(路徑與密碼請替換為你的設定)
keytool -list -v -keystore /path/to/your/upload-keystore.jks -alias upload -storepass YOUR_STORE_PASSWORD -keypass YOUR_KEY_PASSWORD
將取得的 SHA1 與 SHA-256 指紋添加到 Firebase Console:
- Debug SHA1:
3D:35:44:E4:24:52:E9:90:71:4C:6D:B3:0E:17:11:E8:32:BE:C3:6B - Debug SHA-256:
AC:FF:91:CB:CF:12:74:A0:B9:61:01:D5:6D:AE:D4:8B:06:02:12:6B:7D:06:3B:6B:00:F0:E9:E6:24:B8:00:22 - Release SHA1:
A3:6E:5B:2B:0D:D5:EA:26:33:F8:0B:36:F8:E8:FB:D8:04:9F:C3:68 - Release SHA-256:
34:22:C4:C6:8C:97:DA:FB:A7:F7:32:FD:A6:6F:8E:82:E3:E9:27:6A:D6:E5:E3:62:61:16:89:FE:B6:F5:E4:4B
- 下載更新後的
google-services.json - 放置於
android/app/google-services.json
2.3 配置 iOS 應用
- 在 Firebase Console 找到你的 iOS 應用
- 下載
GoogleService-Info.plist - 將檔案加入 Xcode 專案
ios/Runner/目錄
步驟 3:Android 平台設定
3.1 檢查 google-services.json
確認包含 OAuth client 配置:
{
"project_info": { "project_id": "your-project-id" },
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:123456789:android:abcdef",
"android_client_info": { "package_name": "com.yourcompany.yourapp" }
},
"oauth_client": [
{
"client_id": "123456789-abcdef.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.yourcompany.yourapp",
"certificate_hash": "your_sha1_fingerprint"
}
}
]
}
]
}
3.2 build.gradle 啟用 Google Services 插件
在 android/app/build.gradle:
apply plugin: 'com.google.gms.google-services'
步驟 4:iOS 平台設定
4.1 更新 Info.plist(URL Scheme)
在 ios/Runner/Info.plist 中加入:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<!-- REVERSED_CLIENT_ID from GoogleService-Info.plist -->
<string>com.googleusercontent.apps.123456789-abcdef</string>
</array>
</dict>
</array>
4.2 檢查 GoogleService-Info.plist OAuth 欄位
<key>CLIENT_ID</key>
<string>123456789-abcdef.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.123456789-abcdef</string>
步驟 5:實作 AuthRepository
建立 lib/features/auth/data/repositories/auth_repository.dart:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_sign_in/google_sign_in.dart';
// Custom exception for auth errors
class AuthException implements Exception {
final String message;
AuthException(this.message);
@override
String toString() => message;
}
// Provider for AuthRepository
final authRepositoryProvider = Provider<AuthRepository>((ref) {
return AuthRepository(
FirebaseAuth.instance,
googleSignIn: GoogleSignIn.instance,
);
});
// Repository for handling authentication operations
class AuthRepository {
final FirebaseAuth _firebaseAuth;
final GoogleSignIn? googleSignIn;
AuthRepository(
this._firebaseAuth, {
this.googleSignIn,
});
// Get current user
User? get currentUser => _firebaseAuth.currentUser;
// Stream of authentication state changes
Stream<User?> get authStateChanges => _firebaseAuth.authStateChanges();
// Sign in with Google - 使用 v7.1.1 API
Future<User?> signInWithGoogle() async {
if (googleSignIn == null) {
throw AuthException('Google Sign-In not configured');
}
try {
// Initialize GoogleSignIn if needed
await googleSignIn!.initialize();
// Check if platform supports authentication
if (!googleSignIn!.supportsAuthenticate()) {
throw AuthException('Google Sign-In not supported on this platform');
}
// Trigger the authentication flow
final googleUser = await googleSignIn!.authenticate();
// Obtain the auth details from the request
final GoogleSignInAuthentication googleAuth = googleUser.authentication;
// Create a new credential using the ID token
final credential = GoogleAuthProvider.credential(
idToken: googleAuth.idToken,
);
// Sign in to Firebase with the Google credential
final userCredential = await _firebaseAuth.signInWithCredential(credential);
return userCredential.user;
} on GoogleSignInException catch (e) {
if (e.code == GoogleSignInExceptionCode.canceled) {
throw AuthException('Sign in cancelled by user');
}
throw AuthException('Google sign-in failed: ${e.code}');
} catch (e) {
if (e is AuthException) rethrow;
if (e is FirebaseAuthException) rethrow;
throw AuthException('Google sign-in failed: ${e.toString()}');
}
}
// Sign out
Future<void> signOut() async {
// Sign out from Google if signed in
if (googleSignIn != null) {
await googleSignIn!.signOut();
}
// Sign out from Firebase
await _firebaseAuth.signOut();
}
// Get auth error message in Traditional Chinese
String getAuthErrorMessage(dynamic e) {
if (e is FirebaseAuthException) {
switch (e.code) {
case 'account-exists-with-different-credential':
return '此電子郵件已使用其他登入方式註冊';
case 'invalid-credential':
return '登入憑證無效或已過期';
case 'sign_in_failed':
return 'Google 登入失敗,請稍後再試';
default:
return '發生錯誤:${e.message ?? e.code}';
}
} else if (e is AuthException) {
return e.message;
}
return '發生未知錯誤';
}
}
步驟 6:UI 介面實作
建立 lib/features/auth/presentation/pages/auth_page.dart:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../auth/data/repositories/auth_repository.dart';
class AuthPage extends ConsumerWidget {
const AuthPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(title: const Text('登入')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Google Sign-In button
ElevatedButton.icon(
onPressed: () => _signInWithGoogle(context, ref),
icon: const Icon(Icons.login),
label: const Text('使用 Google 登入'),
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 12,
),
),
),
],
),
),
);
}
Future<void> _signInWithGoogle(BuildContext context, WidgetRef ref) async {
final authRepository = ref.read(authRepositoryProvider);
try {
final user = await authRepository.signInWithGoogle();
if (context.mounted && user != null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('歡迎,${user.displayName}!'),
backgroundColor: Colors.green,
),
);
}
} catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(authRepository.getAuthErrorMessage(e)),
backgroundColor: Colors.red,
),
);
}
}
}
}
步驟 7:測試與驗證
7.1 執行測試
# 執行單元測試
flutter test
# 執行應用程式
flutter run
7.2 常見問題排除(FAQ)
問題 1:Sign in failed 錯誤
解法:
- 檢查 SHA 指紋是否正確添加到 Firebase Console
- 確認 package name 與 bundle ID 一致
- 重新下載並替換配置檔案
問題 2:iOS 無法開啟 Google 登入頁面
解法:
- 檢查
Info.plist中的 URL Scheme 是否正確 - 確認
GoogleService-Info.plist包含REVERSED_CLIENT_ID
問題 3:Google Sign-In API 版本差異
解法(v7.1.1 變更重點):
- 使用
authenticate()取代signIn() - 使用
attemptLightweightAuthentication()取代signInSilently() - 僅使用
idToken,不使用accessToken
7.3 最佳實踐
- 錯誤處理:為各種錯誤提供清楚使用者提示
- 狀態管理:使用 Riverpod 維護認證狀態
- 測試:撰寫單元與整合測試
- 安全性:避免在程式碼中硬編碼敏感資訊
完整專案結構範例
lib/
├── features/
│ └── auth/
│ ├── data/
│ │ └── repositories/
│ │ └── auth_repository.dart
│ └── presentation/
│ └── pages/
│ └── auth_page.dart
└── main.dart
android/
└── app/
└── google-services.json
ios/
└── Runner/
├── GoogleService-Info.plist
└── Info.plist
結論
透過本文的詳細指南,你應該能夠在 Flutter 應用中成功配置 Google Sign-In 功能。關鍵要點:
- 正確配置 Firebase Console(加入正確的 SHA 指紋與平台設定)
- 平台特定設定(Android/iOS 皆需對應配置檔)
- 使用最新 API(Google Sign-In v7.1.1 的 API 與舊版不同)
- 完整錯誤處理(提供良好的使用者體驗)
提醒:Google Sign-In 與 Firebase 的設定可能隨版本調整而變動,建議定期查閱官方文件以取得最新資訊。
參考與延伸閱讀(官方技術文件)
Firebase 與 Flutter
- Firebase Auth(Flutter)快速開始:https://firebase.google.com/docs/auth/flutter/start?hl=zh-tw
- 使用 Google 登入(Flutter):https://firebase.google.com/docs/auth/flutter/google-signin?hl=zh-tw
- 將 Firebase 加入 iOS 專案:https://firebase.google.com/docs/ios/setup?hl=zh-tw
- 將 Firebase 加入 Android 專案:https://firebase.google.com/docs/android/setup?hl=zh-tw
套件(pub.dev)
- google_sign_in 套件頁:https://pub.dev/packages/google_sign_in
- firebase_auth 套件頁:https://pub.dev/packages/firebase_auth
Android 設定
- Google Services Gradle 外掛文件(
com.google.gms.google-services):https://developers.google.com/android/guides/google-services-plugin?hl=zh-tw - 取得 SHA-1 指紋(Android 客戶端驗證):https://developers.google.com/android/guides/client-auth?hl=zh-tw
iOS 設定
- Firebase(iOS)Google 登入設定指南:https://firebase.google.com/docs/auth/ios/google-signin?hl=zh-tw
- Apple 官方:定義自訂 URL Scheme(Info.plist 設定):https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app
—
本文基於實際開發專案的實作經驗,適用於 Flutter 3.9+ 版本。


