๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“ฑ| Android/๐Ÿ“˜ | ๊ธฐ๋ก

[Android, Kotlin] Zxing ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ QR์ฝ”๋“œ ์Šค์บ”ํ•˜๊ธฐ

by immgga 2023. 3. 11.

์˜ค๋žœ๋งŒ์— ํฌ์ŠคํŒ…์„ ํ•ด๋ณธ๋‹ค.

์š”์ฆ˜ ์ข€ ๋ฐ”๋น ์„œ ใ…Žใ…Ž(์‚ฌ์‹ค ๊ท€์ฐฎ๊ธฐ๋„ ํ–ˆ๊ณ  ๊นŒ๋จน์—ˆ์–ด์„œ ๋ชป ์˜ฌ๋ ธ๋‹ค ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค.)

 

์•„๋ฌดํŠผ ์ด๋ฒˆ์— ์‚ฌ์šฉํ•ด ๋ณธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” zxing ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ๋ฐ, ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์— QR์ฝ”๋“œ ์Šค์บ” ๊ธฐ๋Šฅ์ด ๋“ค์–ด๊ฐˆ ์˜ˆ์ •์ด๋ผ ๊ฒ€์ƒ‰์„ ํ•ด๋ดค๋”๋‹ˆ, Zxing ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ๊ธธ๋ž˜ ๋ฐ”๋กœ ์‚ฌ์šฉํ•ด ๋ณด์•˜๋‹ค(ํ—คํ—ค)

 

๊ฐœ์†Œ๋ฆฌ๋Š” ์—ฌ๊ธฐ๊นŒ์ง€ ํ•˜๊ณ  ๋ฐ”๋กœ Zxing์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž


 

 

1. dependency ์ถ”๊ฐ€,์„ธํŒ…

build.gradle(app)build.gradle(app)

// zxing
implementation 'com.journeyapps:zxing-android-embedded:4.2.0'

// circle imageview(์˜ˆ์ œ์—์„œ ์‚ฌ์šฉ)
implementation 'de.hdodenhof:circleimageview:3.1.0'

Zxing์— ์‚ฌ์šฉํ•  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•ด ์ค€๋‹ค.

 

AndroidManifest.xml

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

์นด๋ฉ”๋ผ ํผ๋ฏธ์…˜๋„ ์ถ”๊ฐ€ํ•ด ์ค€๋‹ค(QR์Šค์บ”ํ•˜๋‹ˆ๊นŒ ๋‹น์—ฐํ•˜์ง€)

 

2. xml

์ฒซ ํ™”๋ฉด์—์„œ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด QR์ฝ”๋“œ ์Šค์บ”ํ™”๋ฉด์ด ๋‚˜์˜ค๋„๋ก UI๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค.

 

activity_scan.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=".example4.Scan4Activity">

    <Button
        android:id="@+id/scan_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="start to scan code"
        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_result.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=".example4.ResultActivity">

    <com.journeyapps.barcodescanner.DecoratedBarcodeView
        android:id="@+id/decorated_bar_code_view"
        android:layout_width="300dp"
        android:layout_height="300dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/flash_image"
        android:layout_width="60dp"
        android:layout_height="60dp"
        app:civ_circle_background_color="#e5f5f5"
        android:src="@drawable/flashlight"
        app:layout_constraintEnd_toEndOf="@+id/decorated_bar_code_view"
        app:layout_constraintStart_toStartOf="@+id/decorated_bar_code_view"
        app:layout_constraintTop_toBottomOf="@+id/decorated_bar_code_view" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

3. activtiy ์ž‘์„ฑ

ScanActivity.kt

package com.example.qrpractice.example4

import android.app.Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import com.example.qrpractice.R
import com.example.qrpractice.databinding.ActivityScan4Binding
import com.google.zxing.integration.android.IntentIntegrator

class Scan4Activity : AppCompatActivity() {
    private lateinit var binding: ActivityScan4Binding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityScan4Binding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.scanBtn.setOnClickListener {
            val integrator = IntentIntegrator(this)
            with(integrator) {
                setBeepEnabled(false)
                captureActivity = ResultActivity::class.java
                initiateScan()
            }
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (resultCode == Activity.RESULT_OK) {
            val scanRes = IntentIntegrator.parseActivityResult(requestCode, resultCode, data)
            val content = scanRes.contents

            Toast.makeText(this, content, Toast.LENGTH_SHORT).show()
        } else Toast.makeText(this, "์ธ์‹ ์‹คํŒจ", Toast.LENGTH_SHORT).show()
    }
}

scan activity์—์„œ๋Š” ์Šค์บ” ํ™”๋ฉด์œผ๋กœ ๊ฐ€๊ธฐ ์œ„ํ•œ ์„ธํŒ…๊ณผ ์Šค์บ”ํ•˜๊ณ  ๋‚˜์„œ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

 

setonclicklistener์—์„œ๋Š” ์Šค์บ” ํ™”๋ฉด์œผ๋กœ ๊ฐ€๊ธฐ ์œ„ํ•œ ์„ธํŒ…์„ ํ•œ๋‹ค.

  • setBeepEnabled(boolean): ๋ฐ”์ฝ”๋“œ ์ธ์‹ ์‹œ "์‚" ์†Œ๋ฆฌ๋ฅผ ๋‚˜๊ฒŒ ํ•œ๋‹ค.
  • captureActivity: ์Šค์บ” ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•  activity๋ฅผ ์„ค์ •ํ•œ๋‹ค.
  • initiateScan: ์ดˆ๊ธฐํ™”

 

onActivityResult์—์„œ๋Š” ๋ฐ”์ฝ”๋“œ๋ฅผ ์ธ์‹ํ•˜๊ณ  ๋‚œ ํ›„์˜ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

  • content: ์ธ์‹ํ•œ URL์„ ๊ฐ€์ ธ์˜จ๋‹ค.

 

๊ฒฐ๊ณผ

 

์ •๋ฆฌ

๋ฐฐ์šฐ๋ฉด์„œ ์ฝ”๋“œ๋กœ ๋ฐ”์ฝ”๋“œ ์Šค์บ”์„ ๋งŒ๋“œ๋Š” ๊ฒƒ๊ณผ DecoratedBarCodeView๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋งŒ๋“œ๋Š” ๊ฒƒ๊ณผ ํ—ท๊ฐˆ๋ ค์„œ ํ—ค๋งธ๋˜ ๊ธฐ์–ต์ด ์žˆ๋‹ค(์ง€๊ธˆ ์ƒ๊ฐํ•˜๋ฉด ํ˜„ํƒ€๊ฐ€ ์˜ค์ง€๋งŒ).

 

์•ž์œผ๋กœ ํฌ์ŠคํŒ… ์ž์ฃผ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค(์ž์ฃผ ํ• ์ง„ ๋ชจ๋ฅด๊ฒ ๋‹ค).

728x90

๋Œ“๊ธ€