본문 바로가기
Android Application/기초 사용법

안드로이드 이벤트버스(EventBus) 사용

by sdchjjj 2023. 4. 2.
728x90

안녕하세요.

 

이번 포스팅에서는 다른 포스팅에서 구현한 QR scan 기능에 EventBus를 달아보겠습니다.

 

아래 포스팅에서 구현한 소스를 refactoring 하겠습니다.

https://it-of-fortune.tistory.com/28

 

안드로이드 ML Kit - qr scan 구현

안녕하세요. 이번 포스팅에서는 ml kit과 androidx camera 라이브러리를 사용하여 QR scanner를 구현해 보겠습니다. 언어: 코틀린 sdk vsersion - compile: 33 - min: 21 - target: 33 dependency를 추가합니다. build.gradle(:a

it-of-fortune.tistory.com

 

언어: 코틀린

sdk vsersion

  - compile: 33

  - min: 21

  - target: 33

 

먼저, dependency를 추가합니다.

build.gradle(:app)

dependencies {
    ...
    implementation 'org.greenrobot:eventbus:3.2.0'
    ...
}

 

QrScanner 클래스를 Activity로부터 분리하겠습니다.

QrScanner.kt

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) {
            when (barcode.valueType) {
                Barcode.TYPE_URL -> {
                    val url = barcode.url!!.url
                }
            }
        }
    }
}

 

Event를 담을 data class를 생성합니다.

QrInformation.kt

data class QrInformation(
    val url: String?
)

 

Activity에 event subscriber를 달아주겠습니다.

QrScanActivity.kt

override fun onStart() {
    super.onStart()
    EventBus.getDefault().register(this)
}

override fun onStop() {
    super.onStop()
    EventBus.getDefault().unregister(this)
}

@Subscribe(threadMode = ThreadMode.MAIN)
fun onUrlScan(qrInformation: QrInformation?) {
    if (qrInformation != null) moveToQrContents(qrInformation.url)
}

 

이제 event를 post해주는 코드를 작성합니다.

QrScanner.kt

private fun scanCode(barcodes: List<Barcode>) {
    for (barcode in barcodes) {
        when (barcode.valueType) {
            Barcode.TYPE_URL -> {
                val url = barcode.url!!.url
                EventBus.getDefault().post(QrInformation(url))
            }
        }
    }
}

 

전체적인 Activity 소스입니다.

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)
        checkCameraPermission()
    }

    override fun onStart() {
        super.onStart()
        EventBus.getDefault().register(this)
    }

    override fun onStop() {
        super.onStop()
        EventBus.getDefault().unregister(this)
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onUrlScan(qrInformation: QrInformation?) {
        if (qrInformation != null) moveToQrContents(qrInformation.url)
    }

    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()
        }
    }

    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())
                }
        )
    }

    private fun moveToQrContents(contents: String?) {
        if (contents != null) {
            startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(contents)))
        }
    }
}

 

몇 번의 작업으로 간단하게 끝이 났습니다.

이제 테스트를 해보겠습니다.

 

구글 페이지로 이동하는 QR code를 사용합니다(figure1 참조).

figure1. QR code to google.com

 

figure2. run

 

무사히 refactoring 되었습니다.

 

이상 포스팅을 마치겠습니다.

 

감사합니다.

728x90

댓글