FirebaseAuth
.instance // 싱글톤 객체 가져오기
.authStateChanges() // 인증이 바뀌는 것을
.listen((User? user) { // 계속 지켜보고 실행하겟
if (user == null) {
print('User if currently signed out!');
} else {
print('User is signed in!');
}
});
Sign-in method > 이메일/비밀번호
사용설정 키고 저장
짜잔
FirebaseAuth
.instance
.createUserWithEmailAndPassword();
FirebaseAuth
.instance
.createUserWithEmailAndPassword(
email: 'test@gmail.com',
password: '12341234'
);
FirebaseAuth.instance.signOut();
FirebaseAuth
.instance
.signInWithEmailAndPassword(
email: 'test@gmail.com',
password: '12341234'
);
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import '../../../../firebase_options.dart';
import 'login_page.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized(); // 메인 함수에 비동기 함수 있으면 추가해줘야함
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
void initState() {
super.initState();
FirebaseAuth.instance.authStateChanges().listen((user) {
print(FirebaseAuth.instance.currentUser);
if (user != null) {
print('회원가입이 됐거나 유저가 들어왔다');
return;
}
print('회원가입이나 로그인이 필요하다');
});
}
Widget build(BuildContext context) {
return MaterialApp(
home: LoginPage(),
);
}
}
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key);
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
_handleLoginButton() async {
var res = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: 'test@gmail.com',
password: '12341234'
);
print(res);
}
_handleSignUpButton() {
print('회원가입 버튼 눌려짐');
FirebaseAuth.instance.createUserWithEmailAndPassword(
email: 'test@gmail.com',
password: '12341234'
);
}
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 40.0),
child: SingleChildScrollView(
physics: NeverScrollableScrollPhysics(),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height: 50),
TextField(
decoration: InputDecoration(
labelText: '아이디',
border: OutlineInputBorder(),
),
),
SizedBox(height: 16.0),
TextField(
decoration: InputDecoration(
labelText: '비밀번호',
border: OutlineInputBorder(),
),
),
SizedBox(height: 16.0),
Container(
width: double.infinity,
child: ElevatedButton(
onPressed: _handleLoginButton,
child: Text('로그인'),
),
),
TextButton(
onPressed: _handleSignUpButton,
child: Text('회원가입')
),
TextButton(
onPressed: () {
FirebaseAuth.instance.signOut();
},
child: Text('로그아웃')
),
],
),
),
),
),
);
}
}
콘솔 > 프로젝트 > Authentication > Sign-in method > 새 제공업체 추가 > Google 추가
사용 설정 키고 프로젝트 지원 이메일 설정한 다음에 저장 클릭
공식 문서 - 구글 로그인 만들기 (https://firebase.google.com/docs/auth/flutter/federated-auth?hl=ko) 들어가서 코드 복붙
Future<UserCredential> signInWithGoogle() async {
// Trigger the authentication flow
final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
// Obtain the auth details from the request
final GoogleSignInAuthentication? googleAuth = await googleUser?.authentication;
// Create a new credential
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth?.accessToken,
idToken: googleAuth?.idToken,
);
// Once signed in, return the UserCredential
return await FirebaseAuth.instance.signInWithCredential(credential);
}
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import '../../../../firebase_options.dart';
import 'login_page.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized(); // 메인 함수에 비동기 함수 있으면 추가해줘야함
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
void initState() {
super.initState();
FirebaseAuth.instance.authStateChanges().listen((user) {
print(FirebaseAuth.instance.currentUser);
if (user != null) {
print('회원가입이 됐거나 유저가 들어왔다');
print(user.displayName);
print(user.uid);
print(user.email);
return;
}
print('회원가입이나 로그인이 필요하다');
});
}
Widget build(BuildContext context) {
return MaterialApp(
home: LoginPage(),
);
}
}
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key);
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
_handleLoginButton() async {
var res = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: 'test@gmail.com',
password: '12341234'
);
print(res);
}
_handleSignUpButton() {
print('회원가입 버튼 눌려짐');
FirebaseAuth.instance.createUserWithEmailAndPassword(
email: 'test@gmail.com',
password: '12341234'
);
}
Future<UserCredential> signInWithGoogle() async {
// Trigger the authentication flow
final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
// Obtain the auth details from the request
final GoogleSignInAuthentication? googleAuth = await googleUser?.authentication;
// Create a new credential
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth?.accessToken,
idToken: googleAuth?.idToken,
);
// Once signed in, return the UserCredential
return await FirebaseAuth.instance.signInWithCredential(credential);
}
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 40.0),
child: SingleChildScrollView(
physics: NeverScrollableScrollPhysics(),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height: 50),
TextField(
decoration: InputDecoration(
labelText: '아이디',
border: OutlineInputBorder(),
),
),
SizedBox(height: 16.0),
TextField(
decoration: InputDecoration(
labelText: '비밀번호',
border: OutlineInputBorder(),
),
),
SizedBox(height: 16.0),
Container(
width: double.infinity,
child: ElevatedButton(
onPressed: _handleLoginButton,
child: Text('로그인'),
),
),
TextButton(
onPressed: _handleSignUpButton,
child: Text('회원가입')
),
TextButton(
onPressed: signInWithGoogle,
child: Text('구글 로그인')
),
TextButton(
onPressed: () {
FirebaseAuth.instance.signOut();
},
child: Text('로그아웃')
),
],
),
),
),
),
);
}
}
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 10: , null, null)
(프로젝트 > app 폴더 하위에 google-service.json 없으면)
안드로이드 스튜디오에서 플러터 프로젝트 열고 > 터미널 열기
cd android
./gradlew signingReport
입력
SHA-1 키 복사
콘솔에서 디지털 지문 추가 > SHA-1 키 붙여넣
uId
: 유저 고유번호email
: 이메일emailVerified
: 이메일 인증여부photoURL
: 프로필사진displayName
: 닉네임Profile컬렉션 > userId 문서ID > 추가정보 저장
저장할 때
불러올 때
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../../firebase_options.dart';
import 'controller/auth_controller.dart';
import 'controller/profile_edit_controller.dart';
import 'page/login_page.dart';
import 'page/main_page.dart';
import 'page/profile_edit_page.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized(); // 메인 함수에 비동기 함수 있으면 추가해줘야함
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return GetMaterialApp(
initialBinding: BindingsBuilder(() {
Get.put(AuthController());
Get.lazyPut(() => ProfileEditController(), fenix: true);
}),
getPages: [
GetPage(name: '/', page: () => const LoginPage()),
GetPage(name: '/main', page: () => const MainPage()),
GetPage(name: '/edit/profile', page: () => const ProfileEditPage()),
],
initialRoute: '/',
);
}
}
model
class Profile {
String mbti;
String job;
String bloodtype;
Profile({
required this.mbti,
required this.job,
required this.bloodtype,
});
}
controller
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:get/get.dart';
import 'package:google_sign_in/google_sign_in.dart';
import '../model/profile.dart';
class AuthController extends GetxController {
final Rxn<User> user = Rxn<User>();
final Rxn<Profile> profile = Rxn<Profile>();
fetchProfile(String uId) async {
var res = await FirebaseFirestore.instance.collection('profile').doc(uId).get();
var data = res.data()!;
profile(Profile(mbti: data['mbti'], job: data['job'], bloodtype: data['bloodtype']));
}
onInit() {
super.onInit();
FirebaseAuth.instance.authStateChanges().listen((value) {
user(value);
if (value != null) {
// 유저가 있는 상태
fetchProfile(value.uid);
Get.toNamed('/main');
} else {
// 유저가 없는 상태
Get.toNamed('/');
}
});
}
login(id, pw) => FirebaseAuth.instance.signInWithEmailAndPassword(
email: id,
password: pw
);
signup(id, pw) => FirebaseAuth.instance.createUserWithEmailAndPassword(
email: id,
password: pw
);
providerGoogle() async {
final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
final GoogleSignInAuthentication? googleAuth = await googleUser?.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth?.accessToken,
idToken: googleAuth?.idToken,
);
return await FirebaseAuth.instance.signInWithCredential(credential);
}
}
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:get/get.dart';
import 'auth_controller.dart';
class ProfileEditController extends GetxController {
final RxnString mbti = RxnString();
final RxnString job = RxnString();
final RxnString bloodtype = RxnString();
updateProfile() {
String uId = Get.find<AuthController>().user.value!.uid;
FirebaseFirestore.instance.collection('profile').doc(uId).update({
'mbti': mbti.value,
'job': job.value,
'bloodtype': bloodtype.value,
});
Get.find<AuthController>().fetchProfile(uId);
}
void onInit() {
super.onInit();
var profile = Get.find<AuthController>().profile.value;
if (profile != null) {
mbti(profile.mbti);
job(profile.job);
bloodtype(profile.bloodtype);
}
}
}
page
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:google_sign_in/google_sign_in.dart';
import '../controller/auth_controller.dart';
class LoginPage extends GetView<AuthController> {
const LoginPage({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 40.0),
child: SingleChildScrollView(
physics: NeverScrollableScrollPhysics(),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height: 50),
TextField(
decoration: InputDecoration(
labelText: '아이디',
border: OutlineInputBorder(),
),
),
SizedBox(height: 16.0),
TextField(
decoration: InputDecoration(
labelText: '비밀번호',
border: OutlineInputBorder(),
),
),
SizedBox(height: 16.0),
Container(
width: double.infinity,
child: ElevatedButton(
onPressed: (){},
child: Text('로그인'),
),
),
TextButton(
onPressed: (){},
child: Text('회원가입')
),
TextButton(
onPressed: controller.providerGoogle,
child: Text('구글 로그인')
),
TextButton(
onPressed: () {
FirebaseAuth.instance.signOut();
},
child: Text('로그아웃')
),
],
),
),
),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controller/auth_controller.dart';
class MainPage extends GetView<AuthController> {
const MainPage({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Obx(() => Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(controller.user.value!.displayName!),
Text(controller.profile.value?.bloodtype ?? 'null'),
Text(controller.profile.value?.job ?? 'null'),
Text(controller.profile.value?.mbti ?? 'null'),
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => Get.toNamed('edit/profile'),
child: Icon(Icons.edit),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controller/profile_edit_controller.dart';
class ProfileEditPage extends GetView<ProfileEditController> {
const ProfileEditPage({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Obx(() => Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('프로필 수정 및 추가'),
DropdownButton(
value: controller.job.value,
items: ['개발자', '디자이너', '기획자', '마케터'].map((e) => DropdownMenuItem(value: e, child: Text(e))).toList(),
onChanged: controller.job,
hint: Text('직업을 선택하세요'),
),
DropdownButton(
value: controller.bloodtype.value,
items: ['A', 'B', 'AB', 'O'].map((e) => DropdownMenuItem(value: e, child: Text(e))).toList(),
onChanged: controller.bloodtype,
hint: Text('혈액형을 선택하세요'),
),
DropdownButton(
value: controller.mbti.value,
items: ['ISTJ', 'ISFJ', 'ISTP', 'INTP'].map((e) => DropdownMenuItem(value: e, child: Text(e))).toList(),
onChanged: controller.mbti,
hint: Text('MBTI를 선택하세요'),
),
TextButton(
onPressed: controller.updateProfile,
child: Text('적용하기'),
),
],
),
),
),
);
}
}