728x90
안녕하세요 지난 시간에는 QR 코드 생성하는 기능을 구현해보았는데요
오늘은 카메라로 QR 코드를 한 뒤 해당 링크로 연결(웹 페이지 열기 등) 해보도록 하겠습니다.
이를 위해 구글에서 제공하는 머신러닝 기반의 QR 코드 및 바코드 인식 라이브러리인 ML Kit (Machine Learning Kit) 를 사용할 예정입니다.
QR 코드에 포함되어 있는 텍스트 URL을 인식해서 자동으로 웹 페이지 이동 가능합니다.
아래는 전체 코드입니다.
1. QRCodeScannerActivity.kt
class QRCodeScannerActivity : AppCompatActivity() { // implementation 'androidx.appcompat:appcompat:1.7.0' // 최신 버전 24.5월 업뎃함. 현재 25.3
private lateinit var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>
private lateinit var previewView: PreviewView // 카메라 프리뷰
private val barcodeScanner = BarcodeScanning.getClient() // ML Kit 바코드 스캐너
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_qr_code_scanner)
requestCameraPermission() // ✅ 권한 요청 추가
// ✅ 카메라 시작
startCamera()
previewView = findViewById(R.id.previewView)
cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
val cameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder().build().also {
it.setSurfaceProvider(previewView.surfaceProvider)
}
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA // 후면 카메라 사용
val imageAnalysis = ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
imageAnalysis.setAnalyzer(Executors.newSingleThreadExecutor(), { imageProxy ->
processQRCode(imageProxy) // QR 코드 분석
})
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis)
}, ContextCompat.getMainExecutor(this))
}
@OptIn(ExperimentalGetImage::class)
private fun processQRCode(imageProxy: ImageProxy) {
val mediaImage = imageProxy.image ?: return
val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
barcodeScanner.process(image)
.addOnSuccessListener { barcodes ->
for (barcode in barcodes) {
val qrCodeText = barcode.rawValue // QR 코드에서 추출된 텍스트
qrCodeText?.let {
Toast.makeText(this, "QR 코드 인식: $it", Toast.LENGTH_SHORT).show()
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(it)) // 링크 열기
startActivity(intent)
finish() // 액티비티 종료
}
}
}
.addOnFailureListener {
Log.e("QRScanner", "QR 코드 인식 실패", it)
}
.addOnCompleteListener {
imageProxy.close()
}
}
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder()
.build()
.also { it.setSurfaceProvider(previewView.surfaceProvider) }
val cameraSelector = CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK) // 후면 카메라 선택
.build()
try {
cameraProvider.unbindAll() // 기존 바인딩 해제
cameraProvider.bindToLifecycle(this, cameraSelector, preview) // 카메라 연결
} catch (e: Exception) {
e.printStackTrace()
}
}, ContextCompat.getMainExecutor(this))
}
private fun requestCameraPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), 101)
} else {
startCamera() // ✅ 권한이 있으면 바로 카메라 실행
}
}
}
1. 카메라 권한 요청
안드로이드 6.0(API 23) 이상에서는 카메라 권한을 동적으로 요청해야 합니다.
권한이 없으면 화면이 검게 나올 수 있으니 꼭 추가해주세요
private fun requestCameraPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), 101)
} else {
startCamera() // ✅ 권한이 있으면 바로 카메라 실행
}
}
2. QR 코드 인식
아래 내용은 카메라를 설정하고 실시간으로 QR 코드를 스캔하는 역할을 합니다.
// 카메라 프리뷰 설정
previewView = findViewById(R.id.previewView)
cameraProviderFuture = ProcessCameraProvider.getInstance(this)
// 카메라 바인딩 및 프리뷰 적용
cameraProviderFuture.addListener({
val cameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder().build().also { // 카메라 화면 표시
it.setSurfaceProvider(previewView.surfaceProvider) // 카메라 프리뷰를 화면에 표시
}
// 후면 카메라를 선택
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA // 후면 카메라 사용
// 이미지 분석(QR 코드 스캔) 설정
val imageAnalysis = ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) // STRATEGY_KEEP_ONLY_LATEST는 가장 최근 프레임만 처리하도록 설정
.build()
imageAnalysis.setAnalyzer(Executors.newSingleThreadExecutor(), { imageProxy ->
processQRCode(imageProxy) // QR 코드 분석
})
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis)
}, ContextCompat.getMainExecutor(this))
}
3. QR 코드에 첨부된 링크 열기
CameraX에서 캡처한 프레임을 ML Kit 바코드 스캐너를 사용해 QR 코드 데이터를 분석하는 역할을 합니다
QR 코드 스캔이 완료되면 자동으로 링크를 열어 줍니다.
@OptIn(ExperimentalGetImage::class)
private fun processQRCode(imageProxy: ImageProxy) {
// 캡쳐한 이미지를 가져온다
val mediaImage = imageProxy.image ?: return
val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
// QR 코드 인식 및 데이터 추출
barcodeScanner.process(image)
.addOnSuccessListener { barcodes ->
for (barcode in barcodes) {
val qrCodeText = barcode.rawValue // QR 코드에서 추출된 텍스트
// QR 코드를 토스트 메시지로 띄워주는 부분
qrCodeText?.let {
Toast.makeText(this, "QR 코드 인식: $it", Toast.LENGTH_SHORT).show()
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(it)) // 링크 열기
startActivity(intent)
finish() // 액티비티 종료
}
}
}
.addOnFailureListener {
Log.e("QRScanner", "QR 코드 인식 실패", it)
}
.addOnCompleteListener {
imageProxy.close()
}
}
2. activity_qr_code_scanner.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.camera.view.PreviewView
android:id="@+id/previewView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
3. 의존성 추가
//QR 코드 스캔 기능 구현하기 (ML Kit 활용)
implementation ("com.google.mlkit:barcode-scanning:17.3.0")
implementation ("androidx.camera:camera-core:1.4.1") // 카메라X 기본
implementation ("androidx.camera:camera-camera2:1.4.1") // CameraX (카메라 기능)
implementation ("androidx.camera:camera-lifecycle:1.4.1")
implementation ("androidx.camera:camera-view:1.4.1")
감사합니다
'안드로이드 코틀린' 카테고리의 다른 글
[Kotlin][Android] 뷰 사이즈 변경하기 (0) | 2025.03.07 |
---|---|
[Kotlin][Android] 뷰 가시성 변경하기 (0) | 2025.02.28 |
[Kotlin][Android] ZXing 라이브러리 사용하여 QR 코드 생성 및 Intent 로 공유하기 (2) | 2025.02.26 |
[Kotlin][Android] 복합 대입 연산자 활용하기 (0) | 2025.02.25 |
[Kotlin][Android] 문자열 템플릿 활용하기 (0) | 2025.02.14 |