🙋‍♀️ Android

[Android] firebase SMS 인증 기능, qr코드 생성

수댕ʕت̫͡ʔ 2023. 5. 8. 18:53

졸업프로젝트를 위하여 로그인 서비스를 구현중이다.

오늘의 프로세스는 다음과 같다. 

그리고 결과동영상을 먼저 아래에 첨부한다. - 테스트 번호로 테스트해 본 모습

 

 

일단 firebase에 연동을 하였다. 

아래에서 포스팅한것을 참고하자!

https://sojinlee1004.tistory.com/12

 

[Android] 안드로이드와 firebase 연동하기

졸업프로젝트 QR_generator를 만들기 위해서 firebase와 android를 연동해야했다. 전화번호 인증을 구현할 것인데 그것은 mysql보다 firebase가 가장 편한 방법이라고 생각해서 firebase와 안드로이드를 연동

sojinlee1004.tistory.com

그리고 테스트 번호를 설정해서 테스트 번호를 이용하여 sms인증 기능을 테스트하였다.

전화번호가 유효하지 않으면

android:enabled="false"

로 하여 접근할 수 없게 하였다.

 

자세하게 기능과 코드를 살펴보면 다음과 같다.

 

1. 테스트 번호 설정

 

2. build.gradle (app)

implementation platform('com.google.firebase:firebase-bom:31.4.0')
implementation 'com.google.firebase:firebase-auth'

 

3. activity_main.xml , activity_main2.xml

 

<activity_main.xml>

<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">


    <EditText
        android:id="@+id/phone_editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:hint="전화번호 입력"
        android:padding="12dp" />


    <Button
        android:id="@+id/phone_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="20dp"
        android:text="인증요청" />

    <EditText
        android:id="@+id/qrcode_editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:hint="인증번호 입력"
        android:padding="12dp"
        android:enabled="false" />

    <Button
        android:id="@+id/qrcode_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="20dp"
        android:text="인증번호 확인"
        android:enabled="false" />


</LinearLayout>

<activity_main2.xml>

<?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=".MainActivity2">

    <ImageView
        android:id="@+id/qrcode_imageView"
        android:layout_width="400dp"
        android:layout_height="400dp"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.454" />

</androidx.constraintlayout.widget.ConstraintLayout>

4. MainActivity.java , MainActivity2.java

 

<MainActivity.java>

package com.example.qr_login;

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

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.FirebaseException;
import com.google.firebase.FirebaseTooManyRequestsException;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException;
import com.google.firebase.auth.PhoneAuthCredential;
import com.google.firebase.auth.PhoneAuthOptions;
import com.google.firebase.auth.PhoneAuthProvider;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.journeyapps.barcodescanner.BarcodeEncoder;

import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {
    private EditText phoneEditText, verificationCodeEditText;
    private Button sendVerificationButton, verifyCodeButton;

    private FirebaseAuth mAuth;
    private PhoneAuthProvider.ForceResendingToken mResendToken;

    String mVerificationId;

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

        phoneEditText = findViewById(R.id.phone_editText);
        verificationCodeEditText = findViewById(R.id.qrcode_editText);
        sendVerificationButton = findViewById(R.id.phone_btn);
        verifyCodeButton = findViewById(R.id.qrcode_btn);

        mAuth = FirebaseAuth.getInstance();

        sendVerificationButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String phoneNumber = "+1" + phoneEditText.getText().toString();
                PhoneAuthProvider.getInstance().verifyPhoneNumber(
                phoneNumber,
                        60,
                        TimeUnit.SECONDS,
                        MainActivity.this,
                        new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
                            @Override
                            public void onVerificationCompleted(@NonNull PhoneAuthCredential phoneAuthCredential) {
                                signInWithPhoneAuthCredential(phoneAuthCredential);
                            }

                            @Override
                            public void onVerificationFailed(@NonNull FirebaseException e) {
                                if (e instanceof FirebaseAuthInvalidCredentialsException) {
                                    Toast.makeText(MainActivity.this, "Invalid phone number", Toast.LENGTH_SHORT).show();
                                } else if (e instanceof FirebaseTooManyRequestsException) {
                                    Toast.makeText(MainActivity.this, "SMS quota exceeded", Toast.LENGTH_SHORT).show();
                                }
                            }

                            @Override
                            public void onCodeSent(@NonNull String verificationId, @NonNull PhoneAuthProvider.ForceResendingToken token) {
                                mVerificationId = verificationId;
                                mResendToken = token;
                                Toast.makeText(MainActivity.this, "Verification code sent", Toast.LENGTH_SHORT).show();
                                verificationCodeEditText.setEnabled(true); // enabled 를 true로 바꿔준다,
                                verifyCodeButton.setEnabled(true);
                            }
                        });
            }
        });

        verifyCodeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String verificationCode = verificationCodeEditText.getText().toString();
                PhoneAuthCredential credential = PhoneAuthProvider.getCredential(mVerificationId, verificationCode);
                signInWithPhoneAuthCredential(credential);
            }
        });
    }

    private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
        mAuth.signInWithCredential(credential)
                .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) { // 인증번호를 성공적으로 전송하면
                            String inputText = phoneEditText.getText().toString();
                            String userNumber = "{\"userNumber\":\"" + inputText + "\"}";
                            Intent intent = new Intent(MainActivity.this, MainActivity2.class);
                            intent.putExtra("userNumber", userNumber);
                            startActivity(intent);
                            Toast.makeText(MainActivity.this, "Verification successful", Toast.LENGTH_SHORT).show();
                        } else {
                            if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                                Toast.makeText(MainActivity.this, "Invalid verification code", Toast.LENGTH_SHORT).show();
                            }
                        }
                    }
                });
    }
}

<MainActivity2.java>

package com.example.qr_login;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.ImageView;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;

public class MainActivity2 extends AppCompatActivity {
    private ImageView imageView;

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

        imageView = findViewById(R.id.qrcode_imageView);

        String userNumber = getIntent().getStringExtra("userNumber");
        Bitmap bitmap = generateQRCode(userNumber);

        imageView.setImageBitmap(bitmap);
    }

    private Bitmap generateQRCode(String userNumber) {

        try {
            BitMatrix bitMatrix = new MultiFormatWriter().encode(userNumber, BarcodeFormat.QR_CODE, 500, 500);
            int width = bitMatrix.getWidth();
            int height = bitMatrix.getHeight();
            Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);

            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    bitmap.setPixel(x, y, bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE);
                }
            }

            return bitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}