Thêm Firebase vào Flutter và login với Google (Update 9/2020)

Firebase là gì?

Firebase là một nền tảng lập trình di động và web application được phát triển bởi Firebase, Inc năm 2011. Vào năm 2014, Firebase được Google mua lại, và đây chính là sự bùng nổ của Firebase khi được một ông lớn công nghệ như Google đứng sau. Tính đến thời điểm tháng 10 năm 2018, Firebase có 18 sản phẩm, chúng được sử dụng bởi 1.5 triệu ứng dụng.

Rất nhanh chóng, sau khi Flutter ra mắt, các plugin hỗ trợ Flutter kết nối với Firebase cũng đã được Google phát triển, họ gọi các plugin đó là FlutterFire. Tuy nhiên, do còn mới các FlutterFire này vẫn chưa chạm đến phiên bản 1.0, đây chính là nguyên nhân gây ra rất nhiều lỗi trong quá trình tích hợp Firebase vào Flutter. Hôm nay mình sẽ hướng dẫn các bạn cách tích hợp Firebase vào Flutter và login với Google. Hãy cùng bắt đầu ngay bây giờ!

Tạo project Flutter

Chọn nơi bạn muốn lưu project Flutter của mình, nhấn chuột phải mở git bash, chạy câu lệnh “flutter create <your_project_name>”, mình sẽ đặt tên App là firebase_login. Mình muốn là trên màn hình có hai nút Login, Logout và một dòng chữ thông báo user đã login hay chưa, code của mình như sau:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String _message = 'You are not sign in';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Firebase Login'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(_message),
            OutlineButton(
              onPressed: () {},
              child: Text('Login'),
            ),
            OutlineButton(
              onPressed: () {},
              child: Text('Logout'),
            ),
          ],
        ),
      ),
    );
  }
}

Sau khi xong phần flutter project, chúng ta sẽ chuyển sang phần Firebase project.

Tạo project Firebase và kết nối với Flutter

Đầu tiên, bạn truy cập Firebase Console, nhấn vào nút Add project. Sau đó đặt tên project, phần Project Id các bạn để mặc định. Ở đây mình đặt project tên là Flutter Firebase, sau đó nhấn Continue để tiếp tục.

Đặt tên Firebase Project
Đặt tên Firebase Project

Tiếp theo, ở phần Google Analytics for your Firebase project, bạn bỏ tích Enable Google Analytics for this project và nhấn Create project, sau khi tạo xong bạn nhấn Continue để tiếp tục.

Không sử dụng Google Analytics và nhấn Create Project
Không sử dụng Google Analytics và nhấn Create Project

Ở trang chủ, bạn nhấn vào biểu tượng Android để thêm ứng dụng Android vào project, ở đây chúng ta sẽ phải nhập applicationId. Bạn mở lại project flutter, vào thư mục “android/app”, mở file “build.gradle”, bạn tìm đến dòng “applicationId”, bạn sửa lại dòng này thành id bạn muốn (lưu ý định dạng com.example.app), copy nó và dán vào phần Android package name trong Firebase.

Chọn thêm Android App vào Project
Chọn thêm Android App vào Project
Lấy applicationId
Lấy applicationId

Tiếp đến phần Debug signing certificate SHA-1, nếu app của bạn không dùng Google Sign in hoặc Dynamic link thì không cần (mình vẫn khuyên bạn nên thêm vào cho chắc). Để lấy được mã SHA-1, bạn mở thư mục cài Android Studio và tìm đến thư mục “jre/bin”, máy của mình sẽ là thư mục “C:\Program Files\Android\Android Studio\jre\bin”. Trong thư mục bin, bạn mở git bash và chạy lệnh “keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android”, sau khi chạy lệnh này, bạn sẽ thấy trên cửa sổ git có một mục là Certificate fingerprints, bên trong đó có mục SHA1, bạn copy toàn bộ phần mã đó dán vào mục SHA-1 bên Firebase.

Lấy SHA1 Fingerprint
Lấy SHA1 Fingerprint

Nếu như lệnh keytool bị lỗi, các bạn hãy thay đường dẫn thành “keytool -list -v -keystore C:/Users/<Tên user trên máy của bạn>/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android”. Tiếp tục copy mã SHA1 và bỏ vào trong firebase.

Thêm SHA1 Key vào Project
Thêm SHA1 Key vào Project

Bạn nhấn Next để tiếp tục, ở bước tiếp theo, bạn nhấn vào Download google-services.json, sau đó để nó vào trong thư mục android/app của project.

Tải file config về
Tải file config về

Tiếp theo, bạn copy dòng “classpath ‘com.google.gms:google-services:4.3.3′”, mở project flutter, tìm đến folder android, mở file build.gradle, bạn tìm đến phần dependencies và dán đoạn code vừa copy vào.

Lấy các thông tin cần thiết
Lấy các thông tin cần thiết
Setup gradle file

Tiếp tục bạn quay lại Firebase, copy đoạn code “apply plugin: ‘com.google.gms.google-services'”, thêm vào cuối file build.gradle trong folder “android/app” và lưu lại. Quay về Firebase và nhấn Continue to console.

Thêm Google Service plugin vào file app/build.gradle
Thêm các thông tin cần thiết vào file Gradle
Hoàn tất thiết lập
Hoàn tất thiết lập

Tiếp theo, bạn copy file google-services.json đã tải ở trên vào thư mục “android/app”. Vậy là chúng ta đã hoàn thành phần config Firebase trong flutter rồi. Sang phần tiếp theo là code flutter để đăng nhập và đăng xuất.

Thêm plugin và code phần đăng nhập

Đầu tiên, mình cần thêm các plugin sau vào file pubspec.yaml:

dependencies:
  firebase_core: "0.5.0"
  firebase_auth: "^0.18.0+1"
  google_sign_in: ^4.5.3
  // ...

Trở lại với file main.dart của chúng ta, trong phiên bản rework mới của Google, chúng ta bắt buộc thêm đoạn code sau trước khi chạy bất kỳ dịch vụ nào của Google. Nhớ là phải gọi mọi dịch vụ của Google sau khi initializeApp hoàn tất, nếu không sẽ bị lỗi.

await Firebase.initializeApp();

Vì lý do này, chúng ta cần phải thêm FutureBuilder vào Widget tree để đảm bảo việc initial firebase được thực hiện xong trước khi bất kỳ chức năng nào khác được thực hiên.

// Thêm thư viện firebase_core
import 'package:firebase_core/firebase_core.dart';

class _MyHomePageState extends State<MyHomePage> {
// Thêm dòng này
final Future<FirebaseApp> _initialization = Firebase.initializeApp();

// Trong body của Scaffold
// Bọc Widget Center bằng FutureBuilder
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Firebase Login'),
      ),
      body: FutureBuilder(
          future: _initialization,
          builder: (context, snapshot) {
            // Kiểm tra xem có bị lỗi khi initialize không
            if (snapshot.hasError) {
              return Text('Something went wrong');
            }

            // Nếu thành công thì hiển thị như lúc đầu chúng ta đã tạo
            if (snapshot.connectionState == ConnectionState.done) {
              return Center(
                // Code goes here
              );
            }
            // Đang load
            return CircularProgressIndicator();
          }
}

Sau khi xong các bạn có thể run app để check thử xem có bị lỗi không. Nếu không có thì chúng ta tiếp tục thêm tính năng login.

import 'package:flutter/material.dart';
// import thêm hai thư viện này
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';

// ...

class _MyHomePageState extends State<MyHomePage> {
  String _message = 'You are not sign in';

  // Thêm các đoạn code sau
  FirebaseAuth _auth;
  GoogleSignIn _googleSignIn;

  Future<User> _handleSignIn() async {
    final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
    final GoogleSignInAuthentication googleAuth =
        await googleUser.authentication;

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

    final User user = (await _auth.signInWithCredential(credential)).user;
    print("signed in " + user.displayName);
    setState(() {
      // User đã login thì hiển thị đã login
      _message = "You are signed in";
    });
    return user;
  }

  Future _handleSignOut() async {
    await _auth.signOut();
    await _googleSignIn.signOut();
    setState(() {
      // Hiển thị thông báo đã log out
      _message = "You are not sign out";
    });
  }

  Future _checkLogin() async {
    // Khi mở app lên thì check xem user đã login chưa
    final User user = _auth.currentUser;
    if (user != null) {
      setState(() {
        _message = "You are signed in";
      });
    }
  }

  // ...
            if (snapshot.connectionState == ConnectionState.done) {
              // Chỉ có thể thực hiện các dịch vụ Google sau khi initializeApp hoàn tất
              _auth = FirebaseAuth.instance;
              _googleSignIn = GoogleSignIn();
              _checkLogin();
                    // Code goes here
                    OutlineButton(
                      onPressed: () {
                        _handleSignIn();
                      },
                      child: Text('Login'),
                    ),
                    OutlineButton(
                      onPressed: () {
                        _handleSignOut();
                      },
                      child: Text('Logout'),
                    ),
                    // Code goes here
            }
// ...

Code của mình đơn giản chỉ có vậy. Nhưng hiện giờ bạn chưa thể login được đâu, bạn cần bật phương thức đăng nhập bằng Google Account trong Firebase Console. Cách thực hiện như sau: bạn mở tab Authentication, nhấn vào button Set up a sign-in method.

Thiết lập phương thức đăng nhập
Thiết lập phương thức đăng nhập

Tiếp theo, bạn nhấn vào dòng Provider là Google, chọn Enable. Sau đó, ở phần Project public-facing name bạn đặt tên gì cũng được, nó sẽ là tên hiển thị trong phần hỏi user khi login. Phần project support email, bạn chọn email của bạn và nhấn Save.

Thiết lập đăng nhập với Google
Thiết lập đăng nhập với Google

Vậy là chúng đã xong rồi, giờ là lúc chúng ta run app và test thử. Một lưu ý nhỏ cho các bạn là các bạn dùng Login với Google thì phải run trên máy ảo có Google Play, hoặc chạy trên máy thật cho nó chắc, nếu không app sẽ bị lỗi. Và đây là kết quả!

Chọn tài khoản Google để đăng nhập
Chọn tài khoản Google để đăng nhập
Đăng nhập thành công
Đăng nhập thành công

Nếu như bạn nào gặp phải lỗi build app, bạn nên xem lại các cái version của dependencies, classpath, đã chỉnh sửa lại như trong bài viết chưa (mình sẽ có gắng update bài liên tục), nếu vẫn chưa được, bạn hãy migrate sang android X, chỉnh minSdkVersion (trong file “android/app/build.gradle”) từ 16 sang ít nhất là 21. Nếu vẫn chưa giải quyết được bạn có thể comment phía bên dưới mình sẽ giúp đỡ bạn.

Tổng kết

Vậy là trong bài này, mình đã hướng dẫn các bạn tích hợp Firebase vào Flutter và đăng nhập với Google Sign In. Nếu các bạn có thắc mắc dì có thể để lại comment phía bên dưới, mình sẽ giúp nếu có thể. Nếu Firebase có update, các plugin có thay đổi hoặc flutter có thay đổi, bài viết này không còn áp dụng được nữa, bạn có thể vào trang Liên hệ để thông báo với mình, mình sẽ update lại bài viết này nha.

Bài viết này sẽ được mình cập nhật khi có thay đổi lớn diễn ra. Nếu các bạn gặp vấn đề với các method bị Deprecated thì có thể comment bên dưới, mình sẽ cố gắng cập nhật bài viết sớm nhất có thể nha. Trong bài này mình chỉ hướng dẫn các bạn cách có thể thêm firebase và login bằng Google thôi, code chưa được tổ chức hợp lý nên các bạn có thể tổ chức lại cho dễ quản lý hơn nha.

Các bạn có thể xem code tại GitHub của mình. Hy vọng bài viết này hưu ích đối với các bạn, nếu bạn thấy bài viết hay, hãy share bài viết để mọi người cùng biết nha ^^. Cảm ơn các bạn đã đọc bài viết của mình!

Bài viết liên quan
Tạo website với Firebase Hosting
Tao-website-voi-firebase-hosting

Hướng dẫn các bạn tạo project Firebase và deploy một static website lên Firebase Hosting

Code game rắn săn mồi trên console bằng C++
code-game-ran-san-moi-tren-console-bang-cpp

Code game rắn săn mồi trên console bằng C++

Chat app đơn giản với Flutter
Chat app đơn giản với Flutter

Chia sẻ project Chat app đơn giản với Flutter, sử dụng Firebase Authentication và Firestore

Seminar môn Cấu trúc dữ liệu và giải thuật
Seminar-mon-Cau-truc-du-lieu-va-giai-thuat

Chia sẻ về Seminar môn cấu trúc dữ liệu và giải thuật

guest
2 Comments
Inline Feedbacks
View all comments
Tạ Hạnh

Em bị lỗi:
‘FirebaseUser’ is deprecated and shouldn’t be used. 
No Firebase App ‘[DEFAULT]’ has been created – call Firebase.initializeApp()