728x90
안녕하세요.
이번 포스팅에서는 ml kit과 androidx camera 라이브러리를 사용하여 QR scanner를 구현해 보겠습니다.
언어: 코틀린
sdk vsersion
- compile: 33
- min: 21
- target: 33
dependency를 추가합니다.
build.gradle(:app)
dependencies {
...
implementation 'com.google.mlkit:barcode-scanning:17.1.0'
implementation "androidx.camera:camera-camera2:1.3.0-alpha05"
implementation "androidx.camera:camera-lifecycle:1.3.0-alpha05"
implementation "androidx.camera:camera-view:1.3.0-alpha05"
...
}
Manifest에 CAMERA 권한을 추가합니다.
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.laboratory">
...
<uses-permission android:name="android.permission.CAMERA" />
...
</manifest>
QrScanActivity를 생성하여, 이곳에서 scan을 진행하겠습니다.
activity_qr_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=".QrScanActivity">
<androidx.camera.view.PreviewView
android:id="@+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="400dp"
android:layout_marginTop="77dp"
app:layout_constraintTop_toTopOf="parent"
tools:background="@color/white" />
</androidx.constraintlayout.widget.ConstraintLayout>
QrScanActivity.kt
class QrScanActivity : AppCompatActivity() {
private var _binding: ActivityQrScanBinding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = ActivityQrScanBinding.inflate(layoutInflater)
setContentView(binding.root)
}
}
ImageAnalysis.Analyzer를 상속받는 이미지 스캔 클래스와 이미지에서 정보를 따내는 함수를 작성합니다.
타입이 url일 경우 해당 url로 이동하도록 하겠습니다.
QrScanActivity.kt
inner class QrScanner : ImageAnalysis.Analyzer {
@ExperimentalGetImage
override fun analyze(image: ImageProxy) {
val mediaImage = image.image
if (mediaImage != null) {
val inputImage =
InputImage.fromMediaImage(mediaImage, image.imageInfo.rotationDegrees)
val scanner = BarcodeScanning.getClient(
BarcodeScannerOptions.Builder()
.setBarcodeFormats(
Barcode.FORMAT_QR_CODE,
Barcode.FORMAT_AZTEC
)
.build()
)
scanner.process(inputImage)
.addOnSuccessListener { barcodes ->
scanCode(barcodes)
}
image.close()
}
}
}
private fun scanCode(barcodes: List<Barcode>) {
for (barcode in barcodes) {
// See API reference for complete list of supported types
when (barcode.valueType) {
Barcode.TYPE_URL -> {
val url = barcode.url!!.url
moveToQrContents(url)
}
}
}
}
private fun moveToQrContents(contents: String?) {
if (contents != null) {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(contents)))
}
}
setBarcodeFormats 부분에서 format 설정을 해줄 수 있으며, scanCode에서의 Type으로 barcode의 정보를 확인할 수 있습니다.
Format과 Type의 종류는 아래와 같습니다.
Barcode.class
public class Barcode {
public static final int FORMAT_UNKNOWN = -1;
public static final int FORMAT_ALL_FORMATS = 0;
public static final int FORMAT_CODE_128 = 1;
public static final int FORMAT_CODE_39 = 2;
public static final int FORMAT_CODE_93 = 4;
public static final int FORMAT_CODABAR = 8;
public static final int FORMAT_DATA_MATRIX = 16;
public static final int FORMAT_EAN_13 = 32;
public static final int FORMAT_EAN_8 = 64;
public static final int FORMAT_ITF = 128;
public static final int FORMAT_QR_CODE = 256;
public static final int FORMAT_UPC_A = 512;
public static final int FORMAT_UPC_E = 1024;
public static final int FORMAT_PDF417 = 2048;
public static final int FORMAT_AZTEC = 4096;
public static final int TYPE_UNKNOWN = 0;
public static final int TYPE_CONTACT_INFO = 1;
public static final int TYPE_EMAIL = 2;
public static final int TYPE_ISBN = 3;
public static final int TYPE_PHONE = 4;
public static final int TYPE_PRODUCT = 5;
public static final int TYPE_SMS = 6;
public static final int TYPE_TEXT = 7;
public static final int TYPE_URL = 8;
public static final int TYPE_WIFI = 9;
public static final int TYPE_GEO = 10;
public static final int TYPE_CALENDAR_EVENT = 11;
public static final int TYPE_DRIVER_LICENSE = 12;
}
권한을 확인하는 코드를 작성합니다.
QrScanActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = ActivityQrScanBinding.inflate(layoutInflater)
setContentView(binding.root)
checkCameraPermission()
}
private fun checkCameraPermission() {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), 1)
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
) {
startCamera()
}
}
카메라와 프리뷰 코드를 작성합니다.
QrScanActivity.kt
private fun startCamera() {
ProcessCameraProvider.getInstance(this).addListener({
try {
val processCameraProvider =
ProcessCameraProvider.getInstance(this).get() as ProcessCameraProvider
bindPreview(processCameraProvider)
} catch (e: Exception) {
e.printStackTrace()
}
}, ContextCompat.getMainExecutor(this))
}
private fun bindPreview(processCameraProvider: ProcessCameraProvider) {
processCameraProvider.unbindAll()
processCameraProvider.bindToLifecycle(
this,
CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build(),
Preview.Builder().build().apply {
setSurfaceProvider(binding.cameraPreview.surfaceProvider)
},
ImageCapture.Builder().build(),
ImageAnalysis.Builder()
.setTargetRotation(Surface.ROTATION_270)
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build().apply {
setAnalyzer(Executors.newSingleThreadExecutor()!!, QrScanner())
}
)
}
테스트는 구글 페이지로 이동하는 QR code로 진행하겠습니다(figure1 참조).
잘 이동하는 것을 확인할 수 있습니다.
이상 포스팅을 마치겠습니다.
감사합니다.
728x90
'Android Application > 기초 사용법' 카테고리의 다른 글
안드로이드 retrofit2 사용(with Coroutine) - 로또 api 요청 (0) | 2023.04.02 |
---|---|
안드로이드 이벤트버스(EventBus) 사용 (0) | 2023.04.02 |
안드로이드 힐트(hilt) 의존성 주입 사용 (1) | 2023.03.31 |
안드로이드 리사이클러뷰(recyclerview) 사용(with DiffUtil) (0) | 2023.03.30 |
안드로이드 네비게이션(navigation) 사용 (0) | 2023.03.30 |
댓글