개발하는 정대리 님의 Android 강의영상 목록을 보던 중, 개발하는 정대리님 - 안드로이드 QR 인식 강의 영상 있었고, 생각해보니 필자는 안드로이드 프로젝트를 지금까지 진행해오면서 기능 구현 중 QR코드를 다뤄본 경험이 없어 영상에 흥미가 생겨 시청하게 되면서 이번 기회에 공부해보고자 한다.
현재 코로나(COVID-19)사태에 비교적 최근까지 시설 출입자의 실명정보
와 백신접종정보
를 인증하는 방역패스를 통해 많이 사용되어왔다.
디지털 결제
진행
웹 사이트 주소
로 이동
QR은 Quick-Response
의 약자로 빠른 응답을 위해 빠르게 요청을 할 수 있게 정보를 담고있는 코드라고 생각한다.
정식 명칭은 Quick-Response
를 사용하지 않고 QR 코드
로 사용한다고 한다.
위 활용사례로 유추해본 결과, 여러 사용자들의 실명 정보
, 웹 사이트 URL
, 결제 등 개인정보
를 담은 QR 코드들이 많이 사용된다.
실제로 숫자는 최대 7,089자, 아스키 문자는 최대 4,296자, 한자는 최대 1,817자를 저장하는 것이 가능하다. 한글도 한자와 비슷한 분량인 1,700자 정도까지 저장 가능하다.
[출처] - QR코드 - 나무위키
다음 링크(QR Code Generator)로 이동하여 웹
에서 쉽게 QR 코드를 생성할 수도 있다.
실생활에서의 QR코드는 결제 또는 사용자 인증 정보를 제공할 때, 생성되고, 그 정보들이 스캔이 된다.
이러한 실생활에서 사용되는 QR 코드의 생성과 스캔을 예제로 구현해보려 한다.
Android 에서 QR코드를 다루려면 Zxing 라이브러리를 사용하여야 한다.
Android를 위한 Barcode Scanning Library, Zxing 을 사용하여 Barcode를 해석(decode)할 수 있다.
Intent
를 통해 사용된다. ( 조금의 코드의 작성이 필요하다 )UI
및로직
의 고급 사용자 정의를 위해 Acitivity에 내장할 수 있습니다.- 스캔은 가로 또는 세로 모드로 수행할 수 있다.
- Camera 가 시작 시간을 단축하기 위해 백그라운드에서 관리된다.
Minimum SDK
가 24이어야 한다는 것을 의미한다.// Config for SDK 24+
repositories {
mavenCentral()
}
dependencies {
implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
}
minSdk
값을 24
로 설정해주었고, Zxing
라이브러리를 dependencies
에 추가해주었다.
Zxing
의 경우, TextureView
를 사용하므로 하드웨어 가속을 사용하여야 한다.
android:hardwareAccelerated="true"
QR 코드 스캔
작업을 할 때, Android Camera
권한이 필요하다.
<uses-permission android:name="android.permission.CAMERA"/>
메인 화면의 레이아웃 파일이다.
<?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이 있다.
메인 화면의 동작부가 구현된 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 생성 화면의 레이아웃 파일이다.
<?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 코드가 보일 ImageView
를 RelativeLayout
을 사용하여 정중앙에 배치한다.
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 코드 스캔 화면의 레이아웃 파일이다.
<?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
가 있다.
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
에 출력되는 것을 확인할 수 있다.