본문 바로가기

Flutter/01 SNS login

[Flutter] SNS login (3) - 코딩

1. 화면 구성 및 로그인 성공화면

 

초기화면                                                                구글로그인 성공화면

 

페이스북 로그인 성공화면                                                  이메일 로그인 성공화면
SNS 별 User UID 화면

 

 

2. 파일 구성

 

 

3. 소스 코드

상세 설정 참고 사이트 ==> https://firebase.flutter.dev/docs/overview

main.dart

 

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:get/get.dart';
import 'dart:async';
import 'package:sns_login/src/app.dart';

Future<void> main() async {

  // 비동기 메소드 사용시 추가(Firebase 초기화 함수가 비동기 방식임)
  WidgetsFlutterBinding.ensureInitialized();
  // Firebase 초기화 
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    // Getx는 차후에 필요하여 미리 추가함
    return GetMaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: App(),
    );
  }
}

 

app.dart

 

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:sns_login/src/pages/login_page.dart';

class App extends StatelessWidget {
  final GoogleSignIn _googleSignIn = GoogleSignIn();

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Center(child: CircularProgressIndicator());
        } else {
          if (snapshot.hasData) {
            return Scaffold(
              appBar: AppBar(
                title: Text('Login'),
                centerTitle: true,
                actions: <Widget>[
                  IconButton(
                      icon: Icon(Icons.exit_to_app, color: Colors.white,),
                      onPressed: () {
                        FirebaseAuth.instance.signOut();
                        _googleSignIn.signOut();
                        FacebookAuth.instance.logOut();
                      })
                ],
              ),
              body: Center(
                  child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text('provider ID: ' + snapshot.data.providerData[0].providerId,
                    style: TextStyle(fontSize: 20),),
                  SizedBox( height: 20, ),
                  Text('User UID: ' + snapshot.data.uid,
                    style: TextStyle(fontSize: 18),),
                ],
              )),
            );
          }
          return LoginPage();
        }
      },
    );
  }
}

 

login_page.dart

 

import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
import 'package:flutter_signin_button/flutter_signin_button.dart';
import 'package:get/get.dart';
import 'package:google_sign_in/google_sign_in.dart';


class LoginPage extends StatelessWidget {
  final GoogleSignIn _googleSignIn = GoogleSignIn();
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final FacebookAuth _facebookSignIn = FacebookAuth.instance;

  @override
  Widget build(BuildContext context) {

    // 차후에 웹버전을 위한 flag
    var _mobile = false;
    var _isIOS = Theme.of(context).platform == TargetPlatform.iOS;
    var _isAOS = Theme.of(context).platform == TargetPlatform.android;
    if(_isAOS || _isIOS) {
      _mobile = true;
    }

    return Scaffold(
      body: Center(
        child: SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    'Easy',
                    style: TextStyle(
                        fontSize: 40,
                        color: Color.fromRGBO(38, 100, 100, 1.0),
                        fontWeight: FontWeight.bold),
                  ),
                  Container(
                    child: Icon(
                      Icons.star,
                      size: 50,
                      color: Colors.orangeAccent,
                    ),
                  ),
                  Text(
                    'Funny',
                    style: TextStyle(
                        fontSize: 40,
                        color: Color.fromRGBO(38, 100, 100, 1.0),
                        fontWeight: FontWeight.bold),
                  ),
                ],
              ),
              Padding(
                padding: EdgeInsets.all(10.0),
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    'Play',
                    style:
                        TextStyle(fontSize: 20, color: Colors.black38, fontWeight: FontWeight.bold),
                  ),
                  Container(
                    child: Icon(
                      Icons.local_library,
                      size: 25,
                      color: Colors.black87,
                    ),
                  ),
                  Text(
                    'Study',
                    style:
                        TextStyle(fontSize: 20, color: Colors.black38, fontWeight: FontWeight.bold),
                  ),
                ],
              ),
              Padding(
                padding: EdgeInsets.all(40.0),
              ),
// 구글 로그인              
              SignInButton(
                Buttons.GoogleDark,
                onPressed: () {
                  _mobile // 모바일 함수와 웹 함수가 다름
                  ? _handleSignIn().then((user) {
                    print('Google(AOS): login');
                  })
                  : signInWithGoogleWeb().then((user) {
                  print('Google(Web): login');
                  });
                },
              ),
              SizedBox(
                height: 10,
              ),
// Facebook 로그인              
              SignInButton(
                Buttons.Facebook,
                onPressed: () {
                  signInWithFacebook().then((user) { //signInWithFacebookWeb / signInWithFacebook
                    print('Facebook: login');
                  });
                },
              ),
              SizedBox(
                height: 10,
              ),
// Email 로그인
              SignInButton(
                Buttons.Email,
                onPressed: () async {
                  print('------- Email authorization');
                  await Get.to(() => Email()); //widget.user
                },
              ),
            ],
          ),
        ),
      ),
    );
  }

  Future _handleSignIn() async {

    final googleUser = await _googleSignIn.signIn();
    final googleAuth = await googleUser!.authentication;

    final AuthCredential credential = GoogleAuthProvider.credential(
      accessToken: googleAuth.accessToken,
      idToken: googleAuth.idToken,
    );

    final authResult = await _auth.signInWithCredential(credential);
    final user = authResult.user;
    print(user);

    return user;
  }

  Future signInWithGoogleWeb() async {
    // Create a new provider
    var googleProvider = GoogleAuthProvider();

    googleProvider.addScope('https://www.googleapis.com/auth/contacts.readonly');
    googleProvider.setCustomParameters({
      'login_hint': 'user@example.com'
    });

    final authResult = await FirebaseAuth.instance.signInWithPopup(googleProvider);
    final user = authResult.user;

    return user;
  }

  Future signInWithFacebook() async {
    final result = await _facebookSignIn.login();

    // Create a credential from the access token
    final facebookAuthCredential = FacebookAuthProvider.credential(result.accessToken!.token);

    // Once signed in, return the UserCredential
    final authResult = await FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);
    final user = authResult.user;

    return user;
  }

  Future signInWithFacebookWeb() async {
    // Create a new provider
    var facebookProvider = FacebookAuthProvider();

    facebookProvider.addScope('email');
    facebookProvider.setCustomParameters({
      'display': 'popup',
    });

    final authResult = await FirebaseAuth.instance.signInWithPopup(facebookProvider);
    final user = authResult.user;

    return user;
  }

}

// 이메일 로그인 및 가입화면
class Email extends StatefulWidget {
  @override
  _EmailState createState() => _EmailState();
}

class _EmailState extends State<Email> {
  final _email = TextEditingController();
  final _passWd = TextEditingController();

  @override
  void dispose() {
    _email.dispose();
    _passWd.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          centerTitle: true,
          backgroundColor: Color.fromRGBO(38, 100, 100, 1.0),
          iconTheme: IconThemeData(
            color: Colors.white,
          ),
          title: Text('Sign in with Email',
              style: TextStyle(color: Colors.white)
              ),
        ),
        body: Padding(
          padding: const EdgeInsets.all(32.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Flexible(
                child: TextField(
                  decoration: InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: 'Email',
                  ),
                  controller: _email,
                ),
              ),
              Padding(padding: EdgeInsets.all(16.0)),
              Flexible(
                child: TextField(
                  decoration: InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: 'Password',
                  ),
                  controller: _passWd,
                  obscureText: true,
                ),
              ),
              Padding(padding: EdgeInsets.all(16.0)),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: [
                  SizedBox(
                    width: 120,
                    height: 40,
                    child: ElevatedButton.icon(
                      onPressed: () {
                        print('Log in --------------');
                        _login(email: _email.text.trim(), passWord: _passWd.text.trim());
                      },
                      label: Text("Log in"),
                      icon: Icon(Icons.login),
                    ),
                  ),
                  SizedBox(
                    width: 120,
                    height: 40,
                    child: ElevatedButton.icon(
                      onPressed: () {
                        print('Sign up --------------');
                        _signUp(email: _email.text.trim(), passWord: _passWd.text.trim());
                      },
                      label: Text("Sign up"),
                      icon: Icon(Icons.edit),
                    ),
                  )
                ],
              ),
            ],
          ),
        ));
  }

  void myDialog({required String msg}) {
    Get.defaultDialog(
      title: "Notice",
      middleText: msg,
      backgroundColor: Colors.blue,
      titleStyle: TextStyle(color: Colors.white),
      middleTextStyle: TextStyle(color: Colors.white),
    );
  }

  void _signUp({required String email, required String passWord}) async {
    try {
      await FirebaseAuth.instance
          .createUserWithEmailAndPassword(email: email, password: passWord)
          .then((value) => Get.back(result: value));
    } on FirebaseAuthException catch (e) {
      if (e.code == 'weak-password') {
        print('The password provided is too weak');
        myDialog(msg: 'The password provided is too weak');
      } else if (e.code == 'email-already-in-use') {
        print('The account already exists for that email');
        myDialog(msg: 'The account already exists for that email');
      }
    } catch (e) {
      print('기타오류' + e.toString());
      myDialog(msg: e.toString());
    }
//
  }

  void _login({required String email, required String passWord}) async {
    try {
      await FirebaseAuth.instance
          .signInWithEmailAndPassword(email: email, password: passWord)
          .then((value) => Get.back(result: value));
    } on FirebaseAuthException catch (e) {
      if (e.code == 'user-not-found' || e.code == 'wrong-password') {
        print(e.code.toString());
        myDialog(msg: "Wrong email or Wrong password");
      }
    }
  }
}

 

이메일 로그인 화면(로그인 및 가입)