如何使用 Firebase - 操作 Authentication - 註冊與登入帳戶

如何使用 Firebase - 操作 Authentication - 註冊與登入帳戶

情境

Firebase 提供一套非常簡單操作的第三方帳號認證登入模式
從 Firebase 的控制台可以看到我們的登入方式有以下幾種方式

  • Email
  • Google
  • Facebook
  • Twitter
  • GitHub
  • Anonymous

完整程式碼

你可以到 GitHub 上面觀看或下載完整的程式碼

程式碼說明

導入 library

在前面如何使用 Firebase - 用 Android Studio 建立帳戶篇
介紹過如何透過 Android Studio 來跟 Firebase 建立好連結在選項當中我可以選擇使用 Authentication 的部分來進行連接
當連結完畢後會發現 Project 多了 google-services.json 這個檔案
以及 Gradle 內多了以下 library 的導入

compile 'com.google.firebase:firebase-auth:10.0.1'

開啟網路權限

由於會用到網路

<uses-permission android:name="android.permission.INTERNET" />

程式頁面解說

由於此次要解說的功能比較龐大
因此會分成四個頁面

  • HomeActivity

程式第一次進入的畫面
會分成登入跟註冊
如果之前登入過則不會進入到此頁面

  • SignUpActivity

註冊頁面
如果沒有帳號
則使用者會點選這個頁面進行註冊

  • LoginActivity

登入頁面
基本上這個頁面跟註冊頁面大同小異
只是操作 Firebase 的方法不同而已
不過真實情境由程式設計師自行去變化

  • MainActivity

主要頁面
也就是當使用者通過了認證就可以進入 App 的畫面

首頁選擇登入或註冊 (HomeActivity)

在一開始的頁面只有兩個按鈕,一個是登入一個是註冊。

public class HomeActivity extends AppCompatActivity {
    private Button login;
    private Button signUp;
    private FirebaseAuth mAuth;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mAuth = FirebaseAuth.getInstance();
        FirebaseUser user = mAuth.getCurrentUser();
        if(user == null){
            setContentView(R.layout.activity_home);
            login = (Button) findViewById(R.id.login);
            signUp = (Button) findViewById(R.id.sign_up);

            login.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent();
                    intent.setClass(HomeActivity.this, LoginActivity.class);
                    startActivity(intent);

                }
            });
            signUp.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent();
                    intent.setClass(HomeActivity.this, SignUpActivity.class);
                    startActivity(intent);
                }
            });
        } else{
            Intent intent = new Intent();
            intent.setClass(HomeActivity.this, MainActivity.class);
            startActivity(intent);
        }

    }
}

當按下登入則導到 LoginActivity.java
當按下註冊則導到 SignUpActivity.java


一開始我們沒有帳號 你可以試著點選登入 然後隨便亂打帳號密碼 會出現這樣的訊息

顯示這個帳號不存在 所以我們先點選註冊

後台帳號建立

在前面的介紹使用 Firebase 登入必須要有帳號
Firebase 有提供多種登入方式
在登入之前我們先採用註冊的路徑來完成這次的登入
所以必須到後台將 電子郵件/密碼 這個選項啟用
如下圖


我們先刻出一個註冊的頁面 這個頁面的範例是參考 [如何使用TextInputLayout](http://givemepass.blogspot.tw/2017/04/textinputlayout.html) 改寫而成 由於會用到 TextInputLayout 因此我們需要導入 library
compile 'com.android.support:design:25.3.0'

可以看到我們的註冊頁面布局會是如下程式碼

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:gravity="center"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.design.widget.TextInputLayout
        android:id="@+id/account_layout"
        android:layout_width="200dp"
        android:layout_height="wrap_content">
        <EditText
            android:id="@+id/account_edit"
            android:hint="@string/account"
            android:textSize="15sp"
            android:textColor="#000000"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:layout_below="@id/account_layout"
        android:id="@+id/password_layout"
        android:layout_width="200dp"
        android:layout_height="wrap_content">
        <EditText
            android:id="@+id/password_edit"
            android:hint="@string/password"
            android:textSize="15sp"
            android:textColor="#000000"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </android.support.design.widget.TextInputLayout>
    <Button
        android:layout_below="@id/password_layout"
        android:text="@string/signup"
        android:id="@+id/login_button"
        android:layout_width="200dp"
        android:layout_height="wrap_content" />
</RelativeLayout>

就可以看到以下布局畫面


接著初始化所有元件。
private void initView() {
 mAuth = FirebaseAuth.getInstance();
    accountEdit = (EditText) findViewById(R.id.account_edit);
    passwordEdit = (EditText) findViewById(R.id.password_edit);
    accoutLayout = (TextInputLayout) findViewById(R.id.account_layout);
    passwordLayout = (TextInputLayout) findViewById(R.id.password_layout);
    passwordLayout.setErrorEnabled(true);
    accoutLayout.setErrorEnabled(true);
    signUpBtn = (Button) findViewById(R.id.signup_button);
 //...
}

如何使用TextInputLayout 中,有介紹怎麼操作怎麼讓 EditText 的 UI 更加的流暢,因此根據此範例改寫成我們的註冊頁面,當使用者按下註冊按鈕的時候,會去檢查帳號密碼是否為空的,如果是則透過 TextInputLayout 的錯誤顯示 UI 來呈現提示訊息。

signUpBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        String account = accountEdit.getText().toString();
        String password = passwordEdit.getText().toString();
        if(TextUtils.isEmpty(account)){
            accoutLayout.setError(getString(R.string.plz_input_accout));
            passwordLayout.setError("");
            return;
        }
        if(TextUtils.isEmpty(password)){
            accoutLayout.setError("");
            passwordLayout.setError(getString(R.string.plz_input_pw));
            return;
        }
        accoutLayout.setError("");
        passwordLayout.setError("");
        //...
    }
}   

帳號如果是空的則會顯示提示訊息


密碼如果是空的則會顯示提示訊息

檢查結束後 將提示訊息記得設回空字串,否則遇到第一次失敗,第二次要輸入的時候失敗字串還會顯示在上面,在上面程式碼中我們有跟 Firebase 取得 auth 的物件。
mAuth = FirebaseAuth.getInstance();

接著使用者按下註冊按鈕時,我們就可以透過 Firebase 提供的 createUserWithEmailAndPassword 方法來新增一個帳號。

mAuth.createUserWithEmailAndPassword(account, password)
.addOnCompleteListener(MainActivity.this, new OnCompleteListener<AuthResult>() {
    @Override
    public void onComplete(@NonNull Task<AuthResult> task) {
        if (task.isSuccessful()) {
            Toast.makeText(MainActivity.this, "success", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(MainActivity.this, task.getException().getMessage(), Toast.LENGTH_SHORT).show();
        }
    }
});

可以看到這個上面有一個 OnCompleteListener callback 方法,這個是用來告訴你當建立成功以後回傳的結果,裡面有一個 Task 的物件,透過它可以得知此次的建立帳號密碼是否成功,回到我們的註冊畫面來操作一次,
帳號密碼亂打。


居然失敗了 跳出 Email 格式不正確

可見得我們不需要自行判斷 Email 的格式,Firebase 有提供 Email 的判斷機制,接著輸入正常的 Email,密碼還是亂打。

竟然跳出密碼太弱的提示訊息。

只好輸入正常的 Email 跟 密碼。

顯示成功。

代表我們已經登入成功了,就導到 MainActivity 頁面並且顯示登入成功,下方還有一個登出的按鈕。

到 Firebase 的後台看可以看到剛剛註冊成功的帳號。

登出

如果進到 MainActivity 的畫面以後,就代表目前是已經登入的狀態,從 FirebaseAuth 的物件可以拿到 User 的資訊,也可以透過 FirebaseAuth 的物件進行登出。

FirebaseAuth.getInstance().signOut();

透過上面的指令就可以直接將帳號登出,此時 Firebase 會將存在手機的使用者資訊全部清除掉,畫面會再一次切到 HomeActivity 這個畫面。


### 登入

既然前面已經註冊過了,Firebase SDK 會直接幫你記住帳號密碼跟一些資訊,並且直接進入登入狀態,所以剛進入 HomeActivity 這個頁面就會先判斷是否有登入過了。

mAuth = FirebaseAuth.getInstance();
FirebaseUser user = mAuth.getCurrentUser();
if(user == null){
 //...
} else{
    Intent intent = new Intent();
    intent.setClass(HomeActivity.this, MainActivity.class);
    startActivity(intent);
    finish();
}

如果登入過則直接導入到 MainActivity 的頁面,反之則先進入 LoginActivity 的頁面。


將我們剛剛註冊成功的帳號密碼輸入。

顯示登入成功。

這樣就是一個簡單的透過 Firebase 登入跟註冊的範例了。