Firebase로 로그인 처리하기

2021. 12. 1. 08:53Android Development

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/firebaseauthbtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="FCM auth"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

activity_main.xml

package com.example.fcmtest;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;


public class MainActivity extends AppCompatActivity implements View.OnClickListener { 
    // mainActivity자체에 클릭 이벤트 설정.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button firebaseauthbtn = findViewById(R.id.firebaseauthbtn);
        firebaseauthbtn.setOnClickListener(this);
        // 기존에는 익명 내부 클래스로 클릭 이벤트를 처리했지만,
        // 이번에는 메인택티비티에 해당 이벤트를 처리하도록 변경.
    }


    //View.OnClickListener 의 강제 구현 메소드.
    @Override
    public void onClick(View v) {
        Intent i = null;
        i = new Intent(this, AuthActivity.class);
        startActivity(i);
        // 기존 액티비티에서 AuthActivity 호출.
    }
}

MainActivity.java

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".AuthActivity">

    <ImageView
        android:id="@+id/topimg"
        android:layout_width="120dp"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_launcher_foreground" />

    <TextView
        android:id="@+id/titletxt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="FCM auth"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/topimg" />

    <Button
        android:id="@+id/firebaseui"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="삽입형 인증 솔루션"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/titletxt" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/firebaseui" />
</androidx.constraintlayout.widget.ConstraintLayout>

Auth_Activity.xml

package com.example.fcmtest;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class AuthActivity extends AppCompatActivity implements View.OnClickListener{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_auth);

        Button firebaseauthbtn = findViewById(R.id.firebaseui);
        firebaseauthbtn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        Intent i = null;
        i = new Intent(this, FirebaseUIActivity.class);
        startActivity(i);

    }
}

AuthActivity.java

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".FirebaseUIActivity">

    <ImageView
        android:id="@+id/topimg"
        android:layout_width="120dp"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_launcher_foreground" />

    <TextView
        android:id="@+id/titletxt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="FCM auth"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/topimg" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="인증"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/titletxt" />

    <CheckBox
        android:id="@+id/checkBox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="google"
        android:checked="true"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button2" />
</androidx.constraintlayout.widget.ConstraintLayout>

activity_firebaseui_activity.xml

package com.example.fcmtest;

import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.GoogleAuthProvider;

public class FirebaseUIActivity extends AppCompatActivity implements
        View.OnClickListener {
    // 파이어 베이스에 (로그인 인증) 정보를 요청하고 결과를 리턴 받음.
    private static final String TAG = "GoogleActivity";// 디버그용 태그
    private FirebaseAuth mAuth;// 파이어 베이스 인증 객체
    private GoogleSignInClient mGoogleSignInClient;// 구글인증 객체
    ActivityResultLauncher<Intent> someActivityResultLauncher = null;
    // 양방향 액티비티에서 응답 처리 콜백 객체.
    Button firebaseauthbtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_firebase_uiactivity);
        GoogleSignInOptions gso
                = new
                GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken(getString(R.string.default_web_client_id))
                .requestEmail()
                .build();
        // 액티비티를 준비하면서 구글 인증 객체 준비.(토큰과 이메일을 요청)
        mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
        // 구글 인증 객체 초기화.(로그인 시도 구글 계정의 정보를 담을 객체)
        mAuth = FirebaseAuth.getInstance();// 파이어 베이스 인증 객체 초기화.
        // 싱글톤, 파이어베이스에서 인증정보 가져오기.
        // 패키지 정보, 이메일 정보 확인.
        firebaseauthbtn = findViewById(R.id.button2);
        firebaseauthbtn.setOnClickListener(this);
        someActivityResultLauncher
                = registerForActivityResult(
                new ActivityResultContracts.StartActivityForResult(),
                new ActivityResultCallback<ActivityResult>() {
                    @Override
                    public void onActivityResult(ActivityResult result) {
                        if (result.getResultCode() == Activity.RESULT_OK) {
                            // There are no request codes
                            Intent data = result.getData();
                            Task<GoogleSignInAccount> task
                                    =
                                    GoogleSignIn.getSignedInAccountFromIntent(data);
                            // 인텐트로 부터 구글 로그인 정보를 가져옴.
                            try {
                                // Google Sign In was successful, authenticatewith Firebase
                                GoogleSignInAccount account
                                        = task.getResult(ApiException.class);
                                Log.d(TAG, "firebaseAuthWithGoogle:" +
                                        account.getId());
                                //ok
                                firebaseAuthWithGoogle(account.getIdToken(),
                                        data);
                            } catch (ApiException e) {
                                // Google Sign In failed, update UIappropriately
                                Log.w(TAG, "Google sign in failed", e);
                            }
                        } else {
                            Log.d(TAG, "no_k");
                        }
                    }
                });
    }

    private void firebaseAuthWithGoogle(String idToken, Intent data) {
        AuthCredential credential
                = GoogleAuthProvider.getCredential(idToken, null);
        // 인증 토큰을 이용하여 자격 증명을 인증
        // 파이어베이스에 구글 인증을 전달하여 인증 처리하고,
        mAuth.signInWithCredential(credential).addOnCompleteListener(this
                , new OnCompleteListener<AuthResult>() {
                    // 구글 로그인 정보를 이용하여 파이어베이스 인증이 완료 됐다면,
                    @Override
                    public void onComplete(@NonNull Task task) {
                        if (task.isSuccessful()) {
                            Log.d(TAG, "signInWithCredential:success");//ok
                            FirebaseUser user = mAuth.getCurrentUser();
                            // 파이어베이스 인증 유저명 확인.
                            Log.d(TAG, "user : " + user);
                            // 접속 유저 갱신.
                            // 처리후 결과 표시. 내부 클래스.
                            go(data);
                        } else {
                            Log.w(TAG, "signInWithCredential:failure"
                                    , task.getException());
                            updateUI(null);
                        }
                    }
                });
    }

    private void go(Intent data) {
        Log.d(TAG, "go");
        Intent i = new Intent(this, SignedInActivity.class);// intent 생성불가.
                i.putExtras(data);
        startActivity(i);
    }

    private void updateUI(FirebaseUser user) {
        Log.d(TAG, "user : " + user);
    }

    @Override
    public void onClick(View v) {
        Log.d(TAG, "signin");
        Intent signInIntent = mGoogleSignInClient.getSignInIntent();
        //startActivityForResult(signInIntent, RC_SIGN_IN);// deprecated이지만 현재 동작함.
                // 구글 인증으로 정보를 보내고, 인증을 기다림.
                        someActivityResultLauncher.launch(signInIntent);
    }
}

FirebasUIActivity.java

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SignedInActivity">

    <ImageView
        android:id="@+id/topimg"
        android:layout_width="120dp"
        android:layout_height="120dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_launcher_foreground" />

    <TextView
        android:id="@+id/toptxt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="signed in"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/topimg" />

    <LinearLayout
        android:id="@+id/ll"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="horizontal"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/toptxt"
        app:layout_constraintVertical_bias="0.027">

        <Button
            android:id="@+id/sign_out"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="sign out" />

        <Button
            android:id="@+id/delete_account"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="del account" />
    </LinearLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/profilelayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/ll"
        tools:layout_editor_absoluteX="1dp">

        <ImageView
            android:id="@+id/user_profile_picture"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@drawable/ic_launcher_foreground" />

        <TextView
            android:id="@+id/user_email"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView"
            app:layout_constraintStart_toEndOf="@+id/user_profile_picture"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/user_display_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="24dp"
            android:text="TextView"
            app:layout_constraintBottom_toTopOf="@+id/user_enabled_providers"
            app:layout_constraintStart_toEndOf="@+id/user_profile_picture"
            app:layout_constraintTop_toBottomOf="@+id/user_email" />

        <TextView
            android:id="@+id/user_enabled_providers"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toEndOf="@+id/user_profile_picture" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/idp_token_layout"
        android:layout_width="409dp"
        android:layout_height="420dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/profilelayout">

        <TextView
            android:id="@+id/idtokentxt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="token"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/idp_token"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="n/a"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/idtokentxt" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

activity_signed_in.xml

package com.example.fcmtest;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.content.DialogInterface;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.firebase.ui.auth.AuthUI;
import com.firebase.ui.auth.IdpResponse;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.GetTokenResult;
import com.google.firebase.auth.GoogleAuthProvider;
import com.google.firebase.auth.UserInfo;

public class SignedInActivity extends AppCompatActivity implements
        View.OnClickListener {
    // Identi provider response : 식별 공급자 응답.
    private IdpResponse mIdpResponse;// 파이어베이스 인증처리 결과 식별값 저장.
    private static final String TAG = "SignedInActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FirebaseUser currentUser =
                FirebaseAuth.getInstance().getCurrentUser();
        // 현재 사용자를 얻어내고,
        if (currentUser == null) {
            finish();// 사용자가 없다면 결과 액티비티 종료.
            //return;
        }
        mIdpResponse = IdpResponse.fromResultIntent(getIntent());
        // 앞의 인증에서 보내준 데이터를 읽어와서.
        Log.d(TAG, "onCreate_token :" + mIdpResponse);// null
        setContentView(R.layout.activity_signed_in);
        populateProfile();
        populateIdpToken();
        Button signoutbtn = findViewById(R.id.sign_out);
        signoutbtn.setOnClickListener(this);
        Button deleteuser = findViewById(R.id.delete_account);
        deleteuser.setOnClickListener(this);
    }

    private void populateIdpToken() {
        Log.d(TAG, "token :" + mIdpResponse);// null
        FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
        mUser.getIdToken(true)
                .addOnCompleteListener(new
                                               OnCompleteListener<GetTokenResult>() {
                                                   @Override
                                                   public void onComplete(@NonNull Task<GetTokenResult> task) {
                                                       if (task.isSuccessful()) {
                                                           String idToken = task.getResult().getToken();
                                                           if (idToken == null) {// 토큰이 널이라면 숨김.

                                                               findViewById(R.id.idp_token_layout).setVisibility(View.GONE);
                                                           } else {
                                                               ((TextView)
                                                                       findViewById(R.id.idp_token)).setText(idToken);
                                                               // 파이어베이스 인증을 통해서 찾아온 토큰값을 텍스트뷰에 표시.
                                                               Log.d(TAG, "token :" + idToken);
                                                           }
                                                       } else {
                                                           // Handle error -> task.getException();
                                                       }
                                                   }
                                               });
    }

    private void populateProfile() {
        FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
        // 파이어베이스를 통해서 접속한 사용자 정보를 가져와서
        TextView emailtxt = findViewById(R.id.user_email);
        emailtxt.setText(
                TextUtils.isEmpty(user.getEmail()) ? "No email" :
                        user.getEmail());
        // 사용자의 이메일 정보 표시
        TextView usernametxt = findViewById(R.id.user_display_name);
        usernametxt.setText(
                TextUtils.isEmpty(user.getDisplayName()) ? "No display name"
                        : user.getDisplayName());
        // 사용자의 이름 표시
        StringBuilder providerList = new StringBuilder(100);
        providerList.append("Providers used: ");// 인증 주체 표시
        if (user.getProviderData() == null ||
                user.getProviderData().isEmpty()) {
            providerList.append("none");
        } else {
            for (UserInfo profile : user.getProviderData()) {
                String providerId = profile.getProviderId();
                if (GoogleAuthProvider.PROVIDER_ID.equals(providerId)) {
                    providerList.append("Google");
                } else {
                    providerList.append(providerId);
                }
            }
        }
        TextView userenabled = findViewById(R.id.user_enabled_providers);
        userenabled.setText(providerList);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.sign_out:
                signOut();
                break;
            case R.id.delete_account:
                deleteAccountClicked();
                break;
            default:
                break;
        }
    }

    private void deleteAccountClicked() {
        AlertDialog dialog = new AlertDialog.Builder(this)
                .setMessage("Are you sure you want to delete this account?")
                .setPositiveButton("Yes, nuke it!"
                        , new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int
                                    i) {
                                deleteAccount();
                            }
                        })
                .setNegativeButton("No", null)
                .create();
        dialog.show();
        Log.d(TAG, "deleteAccountClicked()");
    }

    private void deleteAccount() {
        // 파이어베이스에 딜리트 메소드 호출,
        // 삭제 처리가 완료되면 현재 액티비티는 종료.
        AuthUI.getInstance()
                .delete(this)
                .addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        if (task.isSuccessful()) {
                            finish();
                        } else {
                        }
                    }
                });
    }

    private void signOut() {
        // 파이어베이스에 사인아웃 처리 요청함.
        AuthUI.getInstance()
                .signOut(this)
                .addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        if (task.isSuccessful()) {
                            finish();
                        } else {
                        }
                    }
                });
        Log
                .
                        d
                                (TAG, "signOut()");

    }
}

SignedInActivity.java

'Android Development' 카테고리의 다른 글

Friebase 사용해서 push message 보내기  (0) 2021.12.02
Firebase_RealtimeDatabase 사용 해보기.  (0) 2021.12.01
Google Firebase 환경설정.  (0) 2021.11.29
Android semiProject  (0) 2021.11.24
Android Studio 13일차  (0) 2021.11.17