Flutter/Social Login

[Flutter] Google Login ② - 구현

찌김이 2022. 8. 21. 06:00
728x90
반응형

 

 

[Flutter] Google Login ① - 준비

소셜 로그인 구현 두번째는 구글 로그인 입니다. 파이어베이스를 사용하면 훨씬 간단하지만 파이어베이스 없이 구현해보겠습니다. 먼저 프로젝트를 만들기 위해 Google Cloud Platform 에서 계정의

dalgoodori.tistory.com

 

이전 포스팅에서 구글 로그인을 위한 모든 셋팅을 완료하였습니다.

이번 포스팅에서는 구글 로그인을 구현하고 유저의 이메일, 이름을 가져오는 것 까지 구현해보겠습니다.

 

pubspec.yaml

 

google_sign_in | Flutter Package

Flutter plugin for Google Sign-In, a secure authentication system for signing in with a Google account on Android and iOS.

pub.dev

dependencies:
  google_sign_in: ^5.4.1

 

login_platform.dart

  • 로그인을 구현할 플랫폼들을 enum 으로 한개 만들어 둡니다.

 

enum LoginPlatform {
  facebook,
  google,
  kakao,
  naver,
  apple,
  none, // logout
}

 

sample_screen.dart

  • 로고 버튼을 눌러 로그인을 실행하고 로그아웃 버튼으로 로그아웃을 처리하는 화면입니다.
  • StatefulWidget 으로 만들고 현재 로그인한 플랫폼을 저장할 변수를 선언합니다.

 

LoginPlatform _loginPlatform = LoginPlatform.none;

 

 

로그인 처리 

  • 모든 셋팅을 정상적으로 완료하였다면 아래의 코드로 로그인이 진행됩니다.

 

final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();

 

 

  • 로그인이 성공하면 GoogleSignInAccount 을 받을 수 있고 별도의 통신 없이 유저 정보를 받아올 수 있습니다. 

 

GoogleSignInAccount._(this._googleSignIn, GoogleSignInUserData data)
    : displayName = data.displayName,
      email = data.email,
      id = data.id,
      photoUrl = data.photoUrl,
      serverAuthCode = data.serverAuthCode,
      _idToken = data.idToken {
  assert(id != null);
}

 

  • 로그인을 처리하는 함수입니다.
  • 로그인 성공하면 loginPlatform 을 google 로 갱신시켜줍니다.
void signInWithGoogle() async {
  final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();

  if (googleUser != null) {
    print('name = ${googleUser.displayName}');
    print('email = ${googleUser.email}');
    print('id = ${googleUser.id}');

    setState(() {
      _loginPlatform = LoginPlatform.google;
    });
  }
}

 

 

로그아웃 처리

  • GoogleSignIn().signOut() 으로 로그아웃 처리 후 현재 로그인 플랫폼을 none 으로 갱신 시킵니다. 

 

void signOut() async {
  switch (_loginPlatform) {
    case LoginPlatform.facebook:
      // await FacebookAuth.instance.logOut();
      break;
    case LoginPlatform.google:
      // 추가
      await GoogleSignIn().signOut();
      break;
    case LoginPlatform.kakao:
      break;
    case LoginPlatform.naver:
      break;
    case LoginPlatform.apple:
      break;
    case LoginPlatform.none:
      break;
  }

  setState(() {
    _loginPlatform = LoginPlatform.none;
  });
}

 

 

로그인 버튼

  • onPressed 나 onTap 이 있는 아무 위젯이나 사용해도 되지만 그렇게하면 기분이 나지 않으니 버튼을 구현해봅시다.
  • 로고는 아래 링크에서 다운받으시면 됩니다.

 

 

Brand Resource Center | Brand terms

Azerty le Numerique Avec des Mots

about.google

 

 

  • 프로젝트에서 asset 폴더와 그 안에 image 폴더를 만들고 다운받은 로고를 넣어줍니다.

 

  • pubspec.yaml 에 assets 를 추가해주세요.
flutter:
  assets:
    - asset/image/

 

 

  • 버튼에 그림자 효과를 주기위해 Card 위젯을 사용했습니다.
  • 버튼에 ripple 효과를 주기위해 Card 위젯 자식으로 Ink 위젯을 사용했습니다.
  • 그리고 onTap 사용을 위해 InkWell 위젯을 사용했습니다.
  • 이미지 경로는 path 부분을 빼고 모두 공통으로 처리할 것이기 때문에 이미지의 이름만 path 로 받습니다.
  • VoidCallback 을 통해 로그인 처리를 하는 함수를 받습니다.

 

  Widget _loginButton(String path, VoidCallback onTap) {
    return Card(
      elevation: 18.0,
      shape: const CircleBorder(),
      clipBehavior: Clip.antiAlias,
      child: Ink.image(
        image: AssetImage('asset/image/$path.png'),
        width: 60,
        height: 60,
        child: InkWell(
          borderRadius: const BorderRadius.all(
            Radius.circular(35.0),
          ),
          onTap: onTap,
        ),
      ),
    );
  }

 

 

로그아웃 버튼

  Widget _logoutButton() {
    return ElevatedButton(
      onPressed: signOut,
      style: ButtonStyle(
        backgroundColor: MaterialStateProperty.all(
          const Color(0xff0165E1),
        ),
      ),
      child: const Text('로그아웃'),
    );
  }

 

 

전체 코드

sample_screen.dart

import 'dart:convert';

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:http/http.dart' as http;
import 'package:social_login_app/login_platform.dart';

class SampleScreen extends StatefulWidget {
  const SampleScreen({Key? key}) : super(key: key);

  @override
  State<SampleScreen> createState() => _SampleScreenState();
}

class _SampleScreenState extends State<SampleScreen> {
  LoginPlatform _loginPlatform = LoginPlatform.none;

  void signInWithGoogle() async {
    final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();

    if (googleUser != null) {
      print('name = ${googleUser.displayName}');
      print('email = ${googleUser.email}');
      print('id = ${googleUser.id}');

      setState(() {
        _loginPlatform = LoginPlatform.google;
      });
    }
  }

  void signOut() async {
    switch (_loginPlatform) {
      case LoginPlatform.facebook:
        break;
      case LoginPlatform.google:
        await GoogleSignIn().signOut();
        break;
      case LoginPlatform.kakao:
        break;
      case LoginPlatform.naver:
        break;
      case LoginPlatform.apple:
        break;
      case LoginPlatform.none:
        break;
    }

    setState(() {
      _loginPlatform = LoginPlatform.none;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
          child: _loginPlatform != LoginPlatform.none
              ? _logoutButton()
              : Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    _loginButton(
                      'google_logo',
                      signInWithGoogle,
                    )
                  ],
                )),
    );
  }

  Widget _loginButton(String path, VoidCallback onTap) {
    return Card(
      elevation: 5.0,
      shape: const CircleBorder(),
      clipBehavior: Clip.antiAlias,
      child: Ink.image(
        image: AssetImage('asset/image/$path.png'),
        width: 60,
        height: 60,
        child: InkWell(
          borderRadius: const BorderRadius.all(
            Radius.circular(35.0),
          ),
          onTap: onTap,
        ),
      ),
    );
  }

  Widget _logoutButton() {
    return ElevatedButton(
      onPressed: signOut,
      style: ButtonStyle(
        backgroundColor: MaterialStateProperty.all(
          const Color(0xff0165E1),
        ),
      ),
      child: const Text('로그아웃'),
    );
  }
}

 

login_platform.dart

enum LoginPlatform {
  facebook,
  google,
  kakao,
  naver,
  apple,
  none,
}
 

 

 

구글 로그인 뿐만 아니라 다른 소셜 로그인 구현도 포스팅 해놓았습니다!! 

 

코딩전사의 기록

 

dalgoodori.tistory.com

 

728x90
반응형