[Android] Android에서 QR코드 다뤄보기 1 - Zxing (생성, 스캔)

Delight Yoon·2022년 9월 6일
0

Android

목록 보기
3/17
post-thumbnail
post-custom-banner

📌 QR 코드

개요

개발하는 정대리 님의 Android 강의영상 목록을 보던 중, 개발하는 정대리님 - 안드로이드 QR 인식 강의 영상 있었고, 생각해보니 필자는 안드로이드 프로젝트를 지금까지 진행해오면서 기능 구현 중 QR코드를 다뤄본 경험이 없어 영상에 흥미가 생겨 시청하게 되면서 이번 기회에 공부해보고자 한다.

QR 코드의 활용사례로는...

  1. 현재 코로나(COVID-19)사태에 비교적 최근까지 시설 출입자의 실명정보백신접종정보를 인증하는 방역패스를 통해 많이 사용되어왔다.

  2. 디지털 결제 진행

  3. 웹 사이트 주소로 이동

등등이 있는 것 같다.

QR 코드란 ?

QR은 Quick-Response 의 약자로 빠른 응답을 위해 빠르게 요청을 할 수 있게 정보를 담고있는 코드라고 생각한다.
정식 명칭은 Quick-Response를 사용하지 않고 QR 코드로 사용한다고 한다.

위 활용사례로 유추해본 결과, 여러 사용자들의 실명 정보, 웹 사이트 URL, 결제 등 개인정보 를 담은 QR 코드들이 많이 사용된다.

실제로 숫자는 최대 7,089자, 아스키 문자는 최대 4,296자, 한자는 최대 1,817자를 저장하는 것이 가능하다. 한글도 한자와 비슷한 분량인 1,700자 정도까지 저장 가능하다.

[출처] - QR코드 - 나무위키

QR 코드 생성

다음 링크(QR Code Generator)로 이동하여 에서 쉽게 QR 코드를 생성할 수도 있다.

📌 Android QR 코드 예제

실생활에서의 QR코드는 결제 또는 사용자 인증 정보를 제공할 때, 생성되고, 그 정보들이 스캔이 된다.
이러한 실생활에서 사용되는 QR 코드의 생성과 스캔을 예제로 구현해보려 한다.

Android에서 QR 코드를 생성, 스캔하려면 어떻게 해야할까?

Android 에서 QR코드를 다루려면 Zxing 라이브러리를 사용하여야 한다.

Zxing ?

Android를 위한 Barcode Scanning Library, Zxing 을 사용하여 Barcode를 해석(decode)할 수 있다.

  1. Intent를 통해 사용된다. ( 조금의 코드의 작성이 필요하다 )
  2. UI로직의 고급 사용자 정의를 위해 Acitivity에 내장할 수 있습니다.
  3. 스캔은 가로 또는 세로 모드로 수행할 수 있다.
  4. Camera 가 시작 시간을 단축하기 위해 백그라운드에서 관리된다.

여기서 중요한 부분은 "Android SDK 24+ is required" 가 의미하는 바로는 Minimum SDK가 24이어야 한다는 것을 의미한다.

** 다음과 같이 gradle을 설정해주어야 한다.

// Config for SDK 24+

repositories {
    mavenCentral()
}

dependencies {
    implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
}

build.gradle(module:app)

minSdk 값을 24로 설정해주었고, Zxing 라이브러리를 dependencies에 추가해주었다.

AndroidManifest.xml

Zxing의 경우, TextureView를 사용하므로 하드웨어 가속을 사용하여야 한다.

android:hardwareAccelerated="true"

QR 코드 스캔 작업을 할 때, Android Camera 권한이 필요하다.

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

메인 화면

activity_main(.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=".MainActivity">

    <Button
        android:id="@+id/btnCreate"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:text="QR 생성"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:layout_marginTop="10dp"
        android:id="@+id/btnScan"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:text="QR 인식"
        app:layout_constraintTop_toBottomOf="@+id/btnCreate"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />
    
</androidx.constraintlayout.widget.ConstraintLayout>

QR 코드 생성QR 코드 스캔 기능을 보여주는 Activity로 이동하기 위한 두 Button이 있다.

MainActivity(.kt)

메인 화면의 동작부가 구현된 Activity 이다.

package com.example.qrcode_example

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button

class MainActivity : AppCompatActivity() {

    private lateinit var btnCreate : Button
    private lateinit var btnScan : Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        btnCreate = findViewById(R.id.btnCreate)
        btnScan = findViewById(R.id.btnScan)

        btnCreate.setOnClickListener {
            val intent = Intent( this, CreateQRActivity::class.java )
            startActivity(intent)
        }

        btnScan.setOnClickListener {
            val intent = Intent( this, ScanQRActivity::class.java )
            startActivity(intent)
        }
    }
}

각자의 화면으로 Intent를 사용해 넘어가주는 단순한 코드이다.

QR 생성 화면

activity_create_qr(.xml)

QR 생성 화면의 레이아웃 파일이다.

<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".CreateQRActivity">

    <ImageView
        android:id="@+id/imageViewQrCode"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"/>

</RelativeLayout>

QR 코드가 보일 ImageViewRelativeLayout을 사용하여 정중앙에 배치한다.

CreateQRActivity(.kt)

QR 코드를 생성하는 기능이 동작하는 Activity이다.

어떻게 구현해야 할까 ? 🤔

Zxing의 QR 코드를 생성하는 Example 코드이다.

try {
  BarcodeEncoder barcodeEncoder = new BarcodeEncoder();
  Bitmap bitmap = barcodeEncoder.encodeBitmap("content", BarcodeFormat.QR_CODE, 400, 400);
  ImageView imageViewQrCode = (ImageView) findViewById(R.id.qrCode);
  imageViewQrCode.setImageBitmap(bitmap);
} catch(Exception e) {

}

BarcodeEncoder를 이용해 QR코드를 만들어 이미지 뷰의 비트맵이미지를 적용하는 코드이다.

BarcodeEncoder().encodeBitmap(contents, BarcodeForamt, width, height)

contents - 포함될 내용.
BarcodeFormat - 바코드 유형
width - 너비
height - 높이

Parameter에 다음과 같이 내용을 삽입해주면 된다.

이를 참조하여 작성하였다.

package com.example.qrcode_example

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

import com.google.zxing.BarcodeFormat

import android.view.View
import android.widget.ImageView

import com.journeyapps.barcodescanner.BarcodeEncoder
import java.lang.Exception

class CreateQRActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_create_qr)

        try {
            val barcodeEncoder = BarcodeEncoder()
            val bitmap = barcodeEncoder.encodeBitmap("https://www.naver.com/", BarcodeFormat.QR_CODE, 400, 400)
            val imageViewQrCode: ImageView = findViewById<View>(R.id.imageViewQrCode) as ImageView
            imageViewQrCode.setImageBitmap(bitmap)
        } catch (e: Exception) {
        }

    }
}

contents - 네이버 웹 사이트 URL
BarcodeFormat - BarcodeFormat.QR_CODE
width - 400
height - 400

다음과 같이 QR코드가 생성되었다.

QR 스캔 화면

activity_scan_qr(.xml)

QR 코드 스캔 화면의 레이아웃 파일이다.

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


    <Button
        android:text="SCAN"
        android:id="@+id/btnScan"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        />

    <TextView
        android:padding="10dp"
        android:text="결과 텍스트"
        android:background="#eaeaea"
        android:id="@+id/txtResult"
        android:textSize="15sp"
        android:textColor="@color/black"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/btnScan"
        android:textAlignment="center"
        android:layout_margin="10dp"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

QR Code 스캔을 시작하는 Button과 스캔 결과 값을 담는 TextView가 있다.

ScanQRActivity(.kt)

QR 코드를 Scan하는 기능이 동작하는 Activity이다.

어떻게 구현해야 할까 ? 🤔

Zxing의 바코드를 스캔하는 Example 코드이다.

// Register the launcher and result handler
private final ActivityResultLauncher<ScanOptions> barcodeLauncher = registerForActivityResult(new ScanContract(),
        result -> {
            if(result.getContents() == null) {
                Toast.makeText(MyActivity.this, "Cancelled", Toast.LENGTH_LONG).show();
            } else {
                Toast.makeText(MyActivity.this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
            }
        });

// Launch
public void onButtonClick(View view) {
    barcodeLauncher.launch(new ScanOptions());
}

이를 참조하여 작성해보았다.

package com.example.qrcode_example

import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanIntentResult
import com.journeyapps.barcodescanner.ScanOptions


class ScanQRActivity : AppCompatActivity() {

    private lateinit var txtResult : TextView

    // 스캐너 설정
    private val barcodeLauncher = registerForActivityResult(
        ScanContract()
    ) { result: ScanIntentResult ->
        // result : 스캔된 결과
        
        // 내용이 없다면
        if (result.contents == null) { 
            Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show()
        }
        else { // 내용이 있다면
            
            // 1. Toast 메시지 출력.
            Toast.makeText(
                this,
                "Scanned: " + result.contents,
                Toast.LENGTH_LONG
            ).show()

            // 2. 결과 값 TextView에 출력.
            txtResult.text = result.contents.toString()
        }
    }

    fun onScanButtonClicked() {
        // Launch ( SCAN 실행 )
        barcodeLauncher.launch(ScanOptions())
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_scan_qr)

        val btnScan : Button = findViewById(R.id.btnScan)
        txtResult = findViewById(R.id.txtResult)

        // SCAN 버튼 클릭
        btnScan.setOnClickListener {
            onScanButtonClicked()
        }
    }
}

위에서 생성한 네이버 홈페이지 주소를 contents 로 포함하는 QR 코드를 barcodeLauncher로 SCAN 하는 과정이다.

네이버 홈페이지 주소(https://www.naver.com/)값이 성공적으로 Toast 메시지와 TextView에 출력되는 것을 확인할 수 있다.

다음 글 "Android에서 QR코드 다뤄보기 2" 에서는 세로로 스캔, QR 스캔화면 텍스트, 이미지 커스터마이징, QR 스캔을 통한 또 다른 예제에 대해 글을 작성해보도록 하겠다.

📌 참조

profile
Yoon's Dev Blog
post-custom-banner

0개의 댓글