แนวทางการสร้างระบบ Authentication บน Firebase สำหรับแอพฯ Android เพื่อดึงฐานข้อมูลจาก Firebase มาเข้าระบบ Login อย่างง่าย
ทบทวนบทเรียนการเขียนแอพฯ Android ได้ที่นี่ เขียนแอพ Android
บทเรียนนี้สามารถศึกษาการติดตั้งและทำงานร่วมกับ Firebase มาก่อนศึกษาได้จากบทความนี้
ในบทเรียนนี้เราจะใช้ฐานข้อมูลส่วนของ Authentication ของ Firebase ซึ่งเราจะมีการเปิดใช้งานและใส่ข้อมูลผู้ใช้เข้าไปแล้วที่ DEVELOP -> Authentication
สร้าง Project ใหม่ขึ้นมาบน Android Studio ทำการติดตั้ง Firebase ให้เรียบร้อยตามบทความก่อนหน้านี้ที่ระบุไว้ตามตัวอย่าง เขียนแอพฯ Android เชื่อมต่อ FireBase เป็นฐานข้อมูล
ออกแบบหน้าจอ content_main.xml ดังนี้
<?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" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/content_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.daydev.firebaselogin.MainActivity" tools:showIn="@layout/activity_main"> <TextView android:text="Firebase Authentation" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="32dp" android:id="@+id/textView" android:textAppearance="@style/TextAppearance.AppCompat.Large" android:textSize="30sp" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textEmailAddress" android:ems="10" android:layout_marginTop="28dp" android:id="@+id/txt_email" android:text="Email:" android:layout_below="@+id/textView" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPassword" android:ems="10" android:layout_below="@+id/txt_email" android:layout_centerHorizontal="true" android:layout_marginTop="32dp" android:id="@+id/txt_password" android:text="password" /> <Button android:text="Login" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/txt_password" android:layout_centerHorizontal="true" android:layout_marginTop="14dp" android:id="@+id/login_action" android:textStyle="normal|bold" android:background="@android:color/holo_orange_dark" /> <Button android:text="Forget Password" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/login_action" android:layout_centerHorizontal="true" android:layout_marginTop="51dp" android:id="@+id/forget_pass" android:background="@android:color/background_light" /> <ProgressBar android:id="@+id/progressBar" android:layout_width="30dp" android:layout_height="30dp" android:layout_gravity="center|bottom" android:layout_marginBottom="20dp" android:visibility="gone" /> </RelativeLayout>
แก้ไขไฟล์ strings.xml เพิ่มเติมดังนี้
<resources> <string name="app_name">Firebase Login</string> <string name="action_settings">Settings</string> <string name="minimum_password">Please insert 6 digits</string> <string name="auth_failed">Authentication Fail!</string> <string name="title_activity_authen">AuthenActivity</string> <string name="title_activity_profile">ProfileActivity</string> </resources>
รอบนี้เราจะเตรียม ข้อความสำหรับคำเตือนต่างๆ เช่น รหัสผ่านใช้ 6 หลักก็จะเตือน minimum_password เป็นชุด String ว่า Please insert 6 digits และ auth_failed กรณีที่ Login ไม่ผ่านด้วยครับ เมื่อชุด Strings พร้อมแล้วก็เปิดไฟล์ MainActivity.java มาเขียนโปรแกรมกันดีกว่า
public EditText txt_email, txt_password; public FirebaseAuth auth; public ProgressBar progressBar; public Button login_action, forget_pass;
สร้าง Globa Var ขึ้นมารับค่าทั้ง EditText, Button และ ProgressBar อย่าลืมส่วนของ FirebaseAuth ครับ ดังนั้น Header จะประกอบไปด้วย
import android.content.Intent; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.text.TextUtils; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.Toast; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; import com.google.firebase.auth.AuthResult; import com.google.firebase.auth.FirebaseAuth;
ภายใน Method OnCreate ให้สร้างฟังก์ชันสำหรับ Authentication ดังนี้
txt_email = (EditText) findViewById(R.id.txt_email); txt_password = (EditText) findViewById(R.id.txt_password); progressBar = (ProgressBar) findViewById(R.id.progressBar); login_action = (Button) findViewById(R.id.login_action); forget_pass = (Button) findViewById(R.id.forget_pass); auth = FirebaseAuth.getInstance(); if (auth.getCurrentUser() != null) { Toast.makeText(getApplicationContext(), "OK, you already logged in!", Toast.LENGTH_SHORT).show(); //Intent for check Session finish(); }
เป็นการตรวจสอบการเข้าระบบ Session ผ่านการตรวจ
auth = FirebaseAuth.getInstance(); if (auth.getCurrentUser() != null) { ... }
ถ้ามี Session อยู่จะ finish(); ทันทีโดยมี Toast แจ้งเตือนว่า “Ok, you already logged in!” ดังนั้นให้เราสร้าง setOnClickListener() ของปุ่ม login_action() ดังนี้ครับเพื่อทำการกดเข้าระบบแล้ว Login ทันที
login_action.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String email = txt_email.getText().toString(); final String password = txt_password.getText().toString(); if (TextUtils.isEmpty(email)) { Toast.makeText(getApplicationContext(), "Enter email address!", Toast.LENGTH_SHORT).show(); return; } if (TextUtils.isEmpty(password)) { Toast.makeText(getApplicationContext(), "Enter password!", Toast.LENGTH_SHORT).show(); return; } progressBar.setVisibility(View.VISIBLE); //authenticate user auth.signInWithEmailAndPassword(email, password) .addOnCompleteListener(MainActivity.this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { progressBar.setVisibility(View.GONE); if (!task.isSuccessful()) { if (password.length() < 6) { txt_password.setError(getString(R.string.minimum_password)); } else { Toast.makeText(MainActivity.this, getString(R.string.auth_failed), Toast.LENGTH_LONG).show(); } } else { Toast.makeText(getApplicationContext(), "OK, you already logged in!", Toast.LENGTH_SHORT).show(); finish(); } } }); } });
ทดสอบแอพฯ ของเราโดยการ Run ดูครับ
ทำการเข้าระบบด้วย Email และ Password กดปุ่ม Login เมื่อเรากรอกข้อมูลที่ตรงกับที่เรากำหนดใน Firebase ของเรา
เข้าระบบได้จะมี Toast เตือนแล้วปิดแอพฯ
เราจะตรวจสอบ Session ของแอพฯ เรายังไงดีว่า มีการ Authentication ไปแล้วง่ายๆ ครับให้สร้างตัว Check Session ขึ้นมาแล้วถ้ามี Session อยู่ให้เรา Intent ไปยังหน้าที่บอกว่าเราเข้าระบบแล้วไปเลย
สร้าง New Activity ขึ้นมาเป็น BasicActivity กำหนดชื่อว่า ProfileActivity ครับ
สร้าง Basic Activity แล้วออกแบบหน้าจอตามตัวอย่างโดยมีปุ่ม SignOut ตั้ง ID ว่า logout_action เพื่อออกจากระบบเมื่อกดครับ
ไฟล์ content_profile.xml จะเป็นดังนี้
<?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" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/content_profile" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.daydev.firebaselogin.ProfileActivity" tools:showIn="@layout/activity_profile"> <TextView android:text="เองเข้าระบบแล้ว!" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="65dp" android:id="@+id/textView2" android:textSize="40sp" /> <Button android:text="Sign Out" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="60dp" android:id="@+id/logout_action" /> </RelativeLayout>
ไปที่ไฟล์ MainActivity ใหม่แก้ไขส่วนของบรรทัด
//Intent for check Session
เป็น
Intent intent = new Intent(MainActivity.this, ProfileActivity.class); startActivity(intent);
และเพิ่มส่วนของ //authenticate user แก้ไขเป็นดังนี้
auth.signInWithEmailAndPassword(email, password) .addOnCompleteListener(MainActivity.this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { // If sign in fails, display a message to the user. If sign in succeeds // the auth state listener will be notified and logic to handle the // signed in user can be handled in the listener. progressBar.setVisibility(View.GONE); if (!task.isSuccessful()) { // there was an error if (password.length() < 6) { txt_password.setError(getString(R.string.minimum_password)); } else { Toast.makeText(MainActivity.this, getString(R.string.auth_failed), Toast.LENGTH_LONG).show(); } } else { Intent intent = new Intent(MainActivity.this, ProfileActivity.class); startActivity(intent); //Toast.makeText(getApplicationContext(), "OK, you already logged in!", Toast.LENGTH_SHORT).show(); finish(); } } });
ดังนั้นไฟล์ MainActivity.java จะมีภาพรวม Source Code ดังนี้
package com.daydev.firebaselogin; import android.content.Intent; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.text.TextUtils; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.Toast; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; import com.google.firebase.auth.AuthResult; import com.google.firebase.auth.FirebaseAuth; public class MainActivity extends AppCompatActivity { public EditText txt_email, txt_password; public FirebaseAuth auth; public ProgressBar progressBar; public Button login_action, forget_pass; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); txt_email = (EditText) findViewById(R.id.txt_email); txt_password = (EditText) findViewById(R.id.txt_password); progressBar = (ProgressBar) findViewById(R.id.progressBar); login_action = (Button) findViewById(R.id.login_action); forget_pass = (Button) findViewById(R.id.forget_pass); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } }); auth = FirebaseAuth.getInstance(); if (auth.getCurrentUser() != null) { //Toast.makeText(getApplicationContext(), "OK, you already logged in!", Toast.LENGTH_SHORT).show(); Intent intent = new Intent(MainActivity.this, ProfileActivity.class); startActivity(intent); finish(); } login_action.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String email = txt_email.getText().toString(); final String password = txt_password.getText().toString(); if (TextUtils.isEmpty(email)) { Toast.makeText(getApplicationContext(), "Enter email address!", Toast.LENGTH_SHORT).show(); return; } if (TextUtils.isEmpty(password)) { Toast.makeText(getApplicationContext(), "Enter password!", Toast.LENGTH_SHORT).show(); return; } progressBar.setVisibility(View.VISIBLE); //authenticate user auth.signInWithEmailAndPassword(email, password) .addOnCompleteListener(MainActivity.this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { progressBar.setVisibility(View.GONE); if (!task.isSuccessful()) { // there was an error if (password.length() < 6) { txt_password.setError(getString(R.string.minimum_password)); } else { Toast.makeText(MainActivity.this, getString(R.string.auth_failed), Toast.LENGTH_LONG).show(); } } else { Intent intent = new Intent(MainActivity.this, ProfileActivity.class); startActivity(intent); //Toast.makeText(getApplicationContext(), "OK, you already logged in!", Toast.LENGTH_SHORT).show(); finish(); } } }); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
กลับไปส่วนของหน้า Session อย่าง ProfileActivity.java ให้เราสร้างเมธอด SignOut() ใหม่ขึ้นมาดังนี้
public void signOut() { auth.signOut(); Intent intent = new Intent(ProfileActivity.this, MainActivity.class); startActivity(intent); finish(); }
ส่วนการเรียกใช้ให้อยู่ใน Action ส่วนของ setOnClickListener() ของ logout_action ที่เป็น Button ครับ ภาพรวมของ ProfileActivity.java จะเป็นดังนี้
package com.daydev.firebaselogin; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.Button; import android.widget.ProgressBar; import android.widget.Toast; import com.google.firebase.auth.FirebaseAuth; public class ProfileActivity extends AppCompatActivity { public ProgressBar progressBar; public FirebaseAuth.AuthStateListener authListener; public FirebaseAuth auth; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_profile); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); auth = FirebaseAuth.getInstance(); final Button logout_action = (Button) findViewById(R.id.logout_action); logout_action.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(ProfileActivity.this, "Logged out!", Toast.LENGTH_LONG).show(); signOut(); } }); } //sign out method public void signOut() { auth.signOut(); Intent intent = new Intent(ProfileActivity.this, MainActivity.class); startActivity(intent); finish(); } }
ทดสอบแอพฯ ของเราได้เลยครับ ให้ลองเข้าระบบดูจะเห็นว่าหน้าจอแอพฯ เราจะไปหน้านี้
ถ้ากดปุ่ม Sign Out ก็จะเห็นว่าหน้าจอจะกลับมาหน้าเข้าสู่ระบบ MainActivity.java เช่นเคยพร้อม Toast ว่า “Logged Out”
จบล่ะ นี่ก็จะเป็นเพียงบทเรียนง่ายๆ สำหรับการสร้างระบบ Authentication ด้วย Firebase บน Android สำหรับมือใหม่ครับ