일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Android
- 센토스
- MachineLearning
- qunit
- picker
- androidstudio
- xcode
- ReactNative
- 네트워크
- node
- 맥
- avds
- 리눅스
- react
- build
- unittest
- IOS
- MAC
- webpack
- PYTHON
- vsCode
- jest
- Chrome
- linux
- TensorFlow
- centos
- 개발
- localserver
- VirtualBox
- Today
- Total
로메오의 블로그
Flutter Firebase login 본문
화면디자인
main.dart
import 'package:flutter/material.dart';
import 'firebase_login_screen.dart';
import 'firebase_signup_screen.dart';
import 'firebase_success_screen.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
'/login': (context) => const FirebaseLoginScreen(),
'/signup': (context) => const FirebaseSignupScreen(),
'/success': (context) => const FirebaseSuccessScreen(),
},
title: 'Navigation Example',
home: const HomeScreen(),
);
}
}
firebase_login_screen.dart
import 'package:flutter/material.dart';
class FirebaseLoginScreen extends StatefulWidget {
const FirebaseLoginScreen({super.key});
@override
// ignore: library_private_types_in_public_api
_FirebaseLoginPageState createState() => _FirebaseLoginPageState();
}
class _FirebaseLoginPageState extends State<FirebaseLoginScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Firebase Login'),
),
// body
body: Padding(
padding: const EdgeInsets.all(15),
child: Column(
children: [
const TextField(
decoration: InputDecoration(labelText: 'Email'),
),
const TextField(
decoration: InputDecoration(labelText: 'Password'),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/success');
},
child: const Text('로그인')),
TextButton(
onPressed: () {
Navigator.pushNamed(context, '/signup');
},
child: const Text('회원가입 '))
],
),
));
}
}
firebase_signup_screen.dart
import 'package:flutter/material.dart';
class FirebaseSignupScreen extends StatefulWidget {
const FirebaseSignupScreen({super.key});
@override
// ignore: library_private_types_in_public_api
_FirebaseSignupPageState createState() => _FirebaseSignupPageState();
}
class _FirebaseSignupPageState extends State<FirebaseSignupScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Firebase Login'),
),
// body
body: Padding(
padding: const EdgeInsets.all(15),
child: Column(
children: [
const TextField(
decoration: InputDecoration(labelText: 'Email'),
),
const TextField(
decoration: InputDecoration(labelText: 'Password'),
),
const TextField(
decoration: InputDecoration(labelText: 'Confirm Password'),
),
const SizedBox(height: 20),
TextButton(
onPressed: () {
Navigator.pushNamed(context, '/signup');
},
child: const Text('회원가입 '))
],
),
));
}
}
firebase_success_screen.dart
import 'package:flutter/material.dart';
class FirebaseSuccessScreen extends StatefulWidget {
const FirebaseSuccessScreen({super.key});
@override
// ignore: library_private_types_in_public_api
_FirebaseSuccessPageState createState() => _FirebaseSuccessPageState();
}
class _FirebaseSuccessPageState extends State<FirebaseSuccessScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Firebase Login'),
),
// body
body: Padding(
padding: const EdgeInsets.all(15),
child: Column(
children: [
const Text(
"로그인 성공",
style: TextStyle(fontSize: 20),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/login');
},
child: const Text('로그아웃'))
],
),
));
}
}
Firebase tools
## firebase tools 설치
$ npm install -g firebase-tools
$ firebase --version
13.16.0
## firebase 로그인
$ firebase login
## flutterfire_cli 설치
$ flutter pub global activate flutterfire_cli
Warning: Pub installs executables into $HOME/.pub-cache/bin, which is not on your path.
You can fix that by adding this to your shell's config file (.zshrc, .bashrc, .bash_profile, etc.):
export PATH="$PATH":"$HOME/.pub-cache/bin"
Activated flutterfire_cli 1.0.0.
zshell에 환경변수를 추가하는 warning이 뜹니다.
vim을 이용해서 .zshrc에
export PATH="$PATH":"$HOME/.pub-cache/bin"
을 추가해줍니다.
$ vim ~/.zshrc
## vim 명령
## i 수정
## esc 수정 종료
## :wq 저장 종료
$ source ~/.zshrc
## 다시 설치 합니다.
$ flutter pub global activate flutterfire_cli
Installed executable flutterfire.
Activated flutterfire_cli 1.0.0.
flutterfire_cli 프로젝트 구성
$ cd MYPROJEC/FOLDER
$ firebase projects:list
$ flutterfire configure -p <Project ID>
i Found 8 Firebase projects. Selecting project xxxx-27a82.
? Which platforms should your configuration support (use arrow keys & space to select)? ›
✔ android
✔ ios
macos
web
windows
사용할 플랫폼을 스페이스바를 이용해서 선택합니다.
설정을 하면
/lib/firebase_options.dart
/ios/Runner/GoogleService-info.plist
/android/app/google-services.json
파일이 생성됩니다.
flutter plugin 설치
https://firebase.google.com/docs/auth/flutter/start?hl=ko
firebase api 사이트를 참조합니다.
$ flutter pub add firebase_auth
$ flutter pub add firebase_core
pubspec.yaml에 dependencies에 추가되었습니다.
dependencies:
flutter:
sdk: flutter
firebase_auth: ^4.16.0
firebase_core: ^2.24.2
firebase 초기화
main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
...
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
...
}
회원가입
firebase_signup_screen.dart
// ignore_for_file: avoid_print
import 'dart:convert';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class FirebaseSignupScreen extends StatefulWidget {
const FirebaseSignupScreen({super.key});
@override
// ignore: library_private_types_in_public_api
_FirebaseSignupPageState createState() => _FirebaseSignupPageState();
}
class _FirebaseSignupPageState extends State<FirebaseSignupScreen> {
final _formKey = GlobalKey<FormState>();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final TextEditingController _confirmPasswordController =
TextEditingController();
Future<void> signup() async {
if (_formKey.currentState!.validate()) {
if (_passwordController.text != _confirmPasswordController.text) {
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text('비밀번호가 다릅니다.')));
}
}
try {
final credential =
await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text,
);
Navigator.pushNamed(context, '/success');
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
}
} catch (e) {
print(e);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Firebase Login'),
),
// body
body: Padding(
padding: const EdgeInsets.all(15),
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
controller: _emailController,
decoration: const InputDecoration(labelText: 'Email'),
validator: (value) {
if (value!.isEmpty) {
return '이메일을 입력하세요.';
}
return null;
},
),
TextFormField(
controller: _passwordController,
decoration: const InputDecoration(labelText: 'Password'),
obscureText: true,
validator: (value) {
if (value!.isEmpty) {
return '패스워드를 입력하세요.';
}
return null;
},
),
TextFormField(
controller: _confirmPasswordController,
decoration:
const InputDecoration(labelText: 'Confirm Password'),
obscureText: true,
validator: (value) {
if (value!.isEmpty) {
return '패스워드를 다시 입력하세요.';
}
return null;
},
),
const SizedBox(height: 20),
TextButton(onPressed: signup, child: const Text('회원가입 '))
],
),
)));
}
}
Cloud Firestore 설정
Firestore Database를 추가합니다.
$ flutter pub add cloud_firestore
cloud_firestore를 추가합니다.
firebase_signup_screen.dart
...
import 'package:cloud_firestore/cloud_firestore.dart';
class FirebaseSignupScreen extends StatefulWidget {
...
}
class _FirebaseSignupPageState extends State<FirebaseSignupScreen> {
final _formKey = GlobalKey<FormState>();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _nameController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final TextEditingController _confirmPasswordController =
TextEditingController();
Future<void> signup() async {
if (_formKey.currentState!.validate()) {
if (_passwordController.text != _confirmPasswordController.text) {
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text('비밀번호가 다릅니다.')));
}
}
try {
final credential =
await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text,
);
var db = FirebaseFirestore.instance;
final user = <String, String>{
"name": _nameController.text,
"email": _emailController.text,
};
db
.collection("users")
.doc(credential.user!.uid)
.set(user)
.onError((e, _) => print("Error writing document: $e"));
Navigator.pushNamed(context, '/success');
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
}
} catch (e) {
print(e);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Firebase Login'),
),
// body
body: Padding(
padding: const EdgeInsets.all(15),
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
controller: _emailController,
decoration: const InputDecoration(labelText: 'Email'),
validator: (value) {
if (value!.isEmpty) {
return '이메일을 입력하세요.';
}
return null;
},
),
TextFormField(
controller: _nameController,
decoration: const InputDecoration(labelText: 'Name'),
validator: (value) {
if (value!.isEmpty) {
return '이름을 입력하세요.';
}
return null;
},
),
TextFormField(
controller: _passwordController,
decoration: const InputDecoration(labelText: 'Password'),
obscureText: true,
validator: (value) {
if (value!.isEmpty) {
return '패스워드를 입력하세요.';
}
return null;
},
),
TextFormField(
controller: _confirmPasswordController,
decoration:
const InputDecoration(labelText: 'Confirm Password'),
obscureText: true,
validator: (value) {
if (value!.isEmpty) {
return '패스워드를 다시 입력하세요.';
}
return null;
},
),
const SizedBox(height: 20),
TextButton(onPressed: signup, child: const Text('회원가입 '))
],
),
)));
}
}
회원가입시 이메일 인증
firebase_signup_screen.dart
...
class _FirebaseSignupPageState extends State<FirebaseSignupScreen> {
...
Future<void> signup() async {
...
try {
final credential =
await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text,
);
var db = FirebaseFirestore.instance;
final user = <String, String>{
"name": _nameController.text,
"email": _emailController.text,
};
credential.user!.sendEmailVerification();
db
.collection("users")
.doc(credential.user!.uid)
.set(user)
.onError((e, _) => print("Error writing document: $e"));
Navigator.pushNamed(context, '/login');
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
}
} catch (e) {
print(e);
}
}
...
로그인
firebase_login_screen.dart
// ignore_for_file: avoid_print
import 'dart:convert';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class FirebaseLoginScreen extends StatefulWidget {
const FirebaseLoginScreen({super.key});
@override
// ignore: library_private_types_in_public_api
_FirebaseLoginPageState createState() => _FirebaseLoginPageState();
}
class _FirebaseLoginPageState extends State<FirebaseLoginScreen> {
final _formKey = GlobalKey<FormState>();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
Future<void> _login() async {
try {
final credential = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text,
);
if (credential.user!.emailVerified) {
Navigator.pushNamed(context, '/success');
} else {
credential.user!.sendEmailVerification();
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text("이메일을 확인하세요.")));
}
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided for that user.');
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Firebase Login'),
),
// body
body: Padding(
padding: const EdgeInsets.all(15),
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: const InputDecoration(labelText: 'Email'),
controller: _emailController,
validator: (value) {
if (value!.isEmpty) {
return '이메일을 입력하세요.';
}
return null;
},
),
TextFormField(
decoration: const InputDecoration(labelText: 'Password'),
controller: _passwordController,
validator: (value) {
if (value!.isEmpty) {
return '비밀번호를 입력하세요.';
}
return null;
},
),
const SizedBox(height: 20),
ElevatedButton(onPressed: _login, child: const Text('로그인')),
TextButton(
onPressed: () {
Navigator.pushNamed(context, '/signup');
},
child: const Text('회원가입 '))
],
),
)));
}
}
데이터 전달 (argument)
firebase_login_screen.dart
...
class _FirebaseLoginPageState extends State<FirebaseLoginScreen> {
...
Future<void> _login() async {
try {
final credential = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text,
);
Navigator.pushNamed(context, '/success', arguments: credential.user);
/*if (credential.user!.emailVerified) {
Navigator.pushNamed(context, '/success');
} else {
credential.user!.sendEmailVerification();
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text("이메일을 확인하세요.")));
}*/
} on FirebaseAuthException catch (e) {
...
}
}
...
firebase_success_screen.dart
...
import 'package:firebase_auth/firebase_auth.dart';
....
class _FirebaseSuccessPageState extends State<FirebaseSuccessScreen> {
@override
Widget build(BuildContext context) {
final user = ModalRoute.of(context)?.settings.arguments as User;
return Scaffold(
...
body: Padding(
padding: const EdgeInsets.all(15),
child: Column(
children: [
Text(
"로그인 성공 ${user.email}",
style: const TextStyle(fontSize: 20),
),
...
],
),
));
}
}
provider
$ flutter pub add provider
/lib/provider/login_provider.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class LoginProvider with ChangeNotifier {
User? _user;
User? get user => _user;
Future<void> signInWithEmailAndPassword(String email, String password) async {
try {
final credential = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: email,
password: password,
);
_user = credential.user;
notifyListeners();
} catch (e) {
throw Exception(e);
}
}
Future<void> signOut() async {
await FirebaseAuth.instance.signOut();
_user = null;
notifyListeners();
}
}
main.dart
...
import 'package:provider/provider.dart';
import 'provider/login_provider.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(ChangeNotifierProvider(
create: (_) => LoginProvider(),
child: const MyApp(),
));
}
...
firebase_login_screen.dart
...
import 'package:provider/provider.dart';
import 'provider/login_provider.dart';
...
class _FirebaseLoginPageState extends State<FirebaseLoginScreen> {
final _formKey = GlobalKey<FormState>();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
Future<void> _login() async {
try {
await Provider.of<LoginProvider>(context, listen: false)
.signInWithEmailAndPassword(
_emailController.text, _passwordController.text);
Navigator.pushNamed(context, '/success');
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided for that user.');
}
}
}
...
firebase_success_screen.dart
// ignore_for_file: avoid_print
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'provider/login_provider.dart';
class FirebaseSuccessScreen extends StatefulWidget {
const FirebaseSuccessScreen({super.key});
@override
// ignore: library_private_types_in_public_api
_FirebaseSuccessPageState createState() => _FirebaseSuccessPageState();
}
class _FirebaseSuccessPageState extends State<FirebaseSuccessScreen> {
@override
Widget build(BuildContext context) {
final user = Provider.of<LoginProvider>(context).user;
return Scaffold(
appBar: AppBar(
title: const Text('Firebase Login'),
),
// body
body: Padding(
padding: const EdgeInsets.all(15),
child: Column(
//mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"로그인 성공 ${user?.email}",
style: const TextStyle(fontSize: 20),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
await Provider.of<LoginProvider>(context, listen: false)
.signOut();
Navigator.pushNamed(context, '/login');
},
child: const Text('로그아웃'))
],
),
));
}
}
Splash 화면
/lib/splash_screen.dart
import 'package:flutter/material.dart';
class SplashScreen extends StatefulWidget {
const SplashScreen({super.key});
@override
State<SplashScreen> createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: FlutterLogo(size: 100),
));
}
}
main.dart
....
import 'package:whereisthis/splash_screen.dart';
...
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
...
initialRoute: '/splash',
routes: {
'/splash': (context) => const SplashScreen(),
'/login': (context) => const FirebaseLoginScreen(),
'/signup': (context) => const FirebaseSignupScreen(),
'/success': (context) => const FirebaseSuccessScreen(),
},
);
}
}
splash에서 로그인 정보 확인
login_provider.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class LoginProvider with ChangeNotifier {
User? _user;
User? get user => _user;
Future<void> signInWithEmailAndPassword(String email, String password) async {
try {
final credential = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: email,
password: password,
);
_user = credential.user;
notifyListeners();
} catch (e) {
throw Exception(e);
}
}
Future<void> signOut() async {
await FirebaseAuth.instance.signOut();
_user = null;
notifyListeners();
}
void currentUser() {
_user = FirebaseAuth.instance.currentUser;
notifyListeners();
}
}
splash_screen.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:provider/provider.dart';
import 'provider/login_provider.dart';
class SplashScreen extends StatefulWidget {
const SplashScreen({super.key});
@override
State<SplashScreen> createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
@override
void initState() {
// TODO: implement initState
super.initState();
SchedulerBinding.instance.addPostFrameCallback((_) {
_initialize();
});
}
Future<void> _initialize() async {
await Future.delayed(const Duration(seconds: 2));
//Provider.of<LoginProvider>(context).currentUser;
context.read<LoginProvider>().currentUser();
User? user = context.read<LoginProvider>().user;
if (user != null) {
Navigator.pushReplacementNamed(context, '/success');
} else {
Navigator.pushReplacementNamed(context, '/login');
}
}
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: FlutterLogo(size: 100),
));
}
}
Google 로그인
$ flutter pub add google_sign_in
$ flutter pub add font_awesome_flutter
https://developers.google.com/android/guides/client-auth?hl=ko
$ keytool -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore
password
## password는 android 입력
keystore 생성
생성된 keystore를 디지털 지문 추가해서 SHA-1과 SHA-256을 추가합니다.
import 'dart:convert';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:provider/provider.dart';
import 'provider/login_provider.dart';
class FirebaseLoginScreen extends StatefulWidget {
const FirebaseLoginScreen({super.key});
@override
// ignore: library_private_types_in_public_api
_FirebaseLoginPageState createState() => _FirebaseLoginPageState();
}
class _FirebaseLoginPageState extends State<FirebaseLoginScreen> {
final _formKey = GlobalKey<FormState>();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
Future<void> _login() async {
try {
await Provider.of<LoginProvider>(context, listen: false)
.signInWithEmailAndPassword(
_emailController.text, _passwordController.text);
Navigator.pushNamed(context, '/success');
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided for that user.');
}
}
}
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);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Firebase Login'),
),
// body
body: Padding(
padding: const EdgeInsets.all(15),
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: const InputDecoration(labelText: 'Email'),
controller: _emailController,
validator: (value) {
if (value!.isEmpty) {
return '이메일을 입력하세요.';
}
return null;
},
),
TextFormField(
decoration: const InputDecoration(labelText: 'Password'),
controller: _passwordController,
validator: (value) {
if (value!.isEmpty) {
return '비밀번호를 입력하세요.';
}
return null;
},
),
const SizedBox(height: 20),
ElevatedButton(onPressed: _login, child: const Text('로그인')),
Center(
child: ElevatedButton.icon(
onPressed: signInWithGoogle,
icon: const FaIcon(FontAwesomeIcons.google),
label: const Text('Google')),
),
TextButton(
onPressed: () {
Navigator.pushNamed(context, '/signup');
},
child: const Text('회원가입 '))
],
),
)));
}
}
https://firebase.google.com/docs/auth/flutter/federated-auth?hl=ko
ios simulator에서는 구글 로그인 테스트 불가
Kakao 로그인
https://developers.kakao.com/console/app
keyhash 생성
https://developers.kakao.com/docs/latest/ko/android/getting-started
$ keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -storepass android -keypass android | openssl sha1 -binary | openssl base64
플랫폼 생성및 키 해시 입력
카카오 로그인 활성화 설정
프로젝트 설정
https://developers.kakao.com/docs/latest/ko/flutter/getting-started
$ flutter pub add kakao_flutter_sdk_user
https://developers.kakao.com/docs/latest/ko/kakaologin/flutter
// ignore_for_file: avoid_print
import 'dart:convert';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart';
import 'package:provider/provider.dart';
import 'provider/login_provider.dart';
class FirebaseLoginScreen extends StatefulWidget {
const FirebaseLoginScreen({super.key});
@override
// ignore: library_private_types_in_public_api
_FirebaseLoginPageState createState() => _FirebaseLoginPageState();
}
class _FirebaseLoginPageState extends State<FirebaseLoginScreen> {
final _formKey = GlobalKey<FormState>();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
Future<void> _login() async {
try {
await Provider.of<LoginProvider>(context, listen: false)
.signInWithEmailAndPassword(
_emailController.text, _passwordController.text);
Navigator.pushNamed(context, '/success');
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided for that user.');
}
}
}
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);
}
Future<void> kakaoTalkLogin() async {
if (await isKakaoTalkInstalled()) {
try {
await UserApi.instance.loginWithKakaoTalk();
print('카카오톡으로 로그인 성공');
} catch (error) {
print('카카오톡으로 로그인 실패 $error');
}
} else {
try {
await UserApi.instance.loginWithKakaoAccount();
print('카카오계정으로 로그인 성공');
} catch (error) {
print('카카오계정으로 로그인 실패 $error');
}
}
}
Future<void> kakaoTalkLogout() async {
try {
await UserApi.instance.unlink();
print('카카오톡으로 로그아웃 성공');
} catch (error) {}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Firebase Login'),
),
// body
body: Padding(
padding: const EdgeInsets.all(15),
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: const InputDecoration(labelText: 'Email'),
controller: _emailController,
validator: (value) {
if (value!.isEmpty) {
return '이메일을 입력하세요.';
}
return null;
},
),
TextFormField(
decoration: const InputDecoration(labelText: 'Password'),
controller: _passwordController,
validator: (value) {
if (value!.isEmpty) {
return '비밀번호를 입력하세요.';
}
return null;
},
),
const SizedBox(height: 20),
ElevatedButton(onPressed: _login, child: const Text('로그인')),
const SizedBox(height: 20),
Center(
child: ElevatedButton.icon(
onPressed: signInWithGoogle,
icon: const FaIcon(FontAwesomeIcons.google),
label: const Text('Google')),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: kakaoTalkLogin, child: const Text('카카오 로그인')),
const SizedBox(height: 20),
ElevatedButton(
onPressed: kakaoTalkLogout,
child: const Text('카카오 로그아웃')),
const SizedBox(height: 20),
TextButton(
onPressed: () {
Navigator.pushNamed(context, '/signup');
},
child: const Text('회원가입 '))
],
),
)));
}
}
main.dart
...
import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
KakaoSdk.init(nativeAppKey: 'e20945d788dXXXXXXX615f625e49');
runApp(ChangeNotifierProvider(
create: (_) => LoginProvider(),
child: const MyApp(),
));
}
class MyApp extends StatelessWidget {
...
}
'App & OS > Hybrid' 카테고리의 다른 글
Flutter (0) | 2024.08.18 |
---|---|
Flutter hello world (0) | 2024.08.15 |
[React Native] Postman에서 Push 보내기 (0) | 2019.08.04 |
[React Native] Firebase Push Notification 추가 [Android] (0) | 2019.07.29 |
[React Native] Firebase 연동하기 (2019년 기준) (1) | 2019.07.29 |