0

I have successfully implemented a QR Code Scanner in Jetpack Compose, but I would like to enhance the user experience by adding a small square focus that hovers over the icon of the QR code. This square focus will visually indicate to the user where to position the QR code for scanning. How can I achieve this effect and integrate it into my existing QR Code Scanner implementation?

By implementing the changes in the provided code, I would expect to see a small red square overlay on top of the camera preview, indicating the focus area for the QR code.Due to errors in the previous code implementation, the small square overlay was not drawn correctly on top of the camera preview, and the compilation errors prevented the code from functioning as intended.

Yaakoub-H
  • 3
  • 2

1 Answers1

0

You could try out Google Code Scanner Library https://developers.google.com/ml-kit/vision/barcode-scanning/code-scanner

below implementation might help you.

QRCodeScanner.kt
-----------------

import kotlinx.coroutines.flow.Flow

interface QRCodeScanner {

    fun startScanning(): Flow<String?>
}
QRCodeScannerImpl.kt
--------------------

import com.google.android.gms.common.moduleinstall.ModuleInstallClient
import com.google.android.gms.common.moduleinstall.ModuleInstallRequest
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.mlkit.vision.codescanner.GmsBarcodeScanner
import com.niyaj.popos.features.qrcode_scanner.domain.repository.QRCodeScanner
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.launch
import timber.log.Timber

class QRCodeScannerImpl(
    private val scanner: GmsBarcodeScanner,
    private val playModule: ModuleInstallClient,
) : QRCodeScanner {

    init {
        /** Checking does ScannerModule is installed on the device otherwise,
        install using ModuleClientAPI, for more visit 
        https://developers.google.com/android/guides/module-install-apis **/

        playModule
            .areModulesAvailable(scanner)
            .addOnSuccessListener {
                if (!it.areModulesAvailable()) {
                    Timber.d("Downloading QR Code Module")
                    // Modules are not present on the device install...
//                    playModule.deferredInstall(scanner)
                    val newRequest = ModuleInstallRequest.newBuilder().addApi(scanner).build()
                    playModule.installModules(newRequest)
                }
            }.addOnFailureListener {
                Timber.d("Failed to install QRCodeScanner Module")
            }
    }

    override fun startScanning() : Flow<String?> {
        return callbackFlow {
            scanner.startScan()
                .addOnSuccessListener {
                    launch {
                        send(getDetails(it))
                    }
                }.addOnFailureListener {
                    launch {
                        send(null)
                    }
                }
            awaitClose {  }
        }
    }

    private fun getDetails(barcode : Barcode) : String? {
        return when (barcode.valueType) {
            Barcode.TYPE_WIFI -> {
                val ssid = barcode.wifi!!.ssid
                val password = barcode.wifi!!.password
                val type = barcode.wifi!!.encryptionType
                "ssid : $ssid, password : $password, type : $type"
            }

            Barcode.TYPE_URL -> {
                "${barcode.url?.url}"
            }

            Barcode.TYPE_PRODUCT -> {
                barcode.displayValue
            }

            Barcode.TYPE_EMAIL -> {
                "${barcode.email?.address}"
            }

            Barcode.TYPE_CONTACT_INFO -> {
                "${barcode.contactInfo?.name?.formattedName}"
            }

            Barcode.TYPE_PHONE -> {
                "${barcode.phone?.number}"
            }

            Barcode.TYPE_CALENDAR_EVENT -> {
                "${barcode.calendarEvent?.description}"
            }

            Barcode.TYPE_GEO -> {
                "${barcode.geoPoint?.lat} ${barcode.geoPoint?.lng}"
            }

            Barcode.TYPE_ISBN -> {
                barcode.displayValue
            }

            Barcode.TYPE_DRIVER_LICENSE -> {
                "${barcode.driverLicense?.firstName} ${barcode.driverLicense?.lastName }${barcode.driverLicense?.lastName}"
            }

            Barcode.TYPE_SMS -> {
                "${barcode.sms}"
            }

            Barcode.TYPE_TEXT -> {
                barcode.rawValue
            }

            Barcode.TYPE_UNKNOWN -> {
                "${barcode.rawValue}"
            }

            else -> {
                null
            }
        }
    }
}

ScannerModule.kt

import android.app.Application
import android.content.Context
import com.google.android.gms.common.moduleinstall.ModuleInstall
import com.google.android.gms.common.moduleinstall.ModuleInstallClient
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.mlkit.vision.codescanner.GmsBarcodeScanner
import com.google.mlkit.vision.codescanner.GmsBarcodeScannerOptions
import com.google.mlkit.vision.codescanner.GmsBarcodeScanning
import com.niyaj.popos.features.qrcode_scanner.data.QRCodeScannerImpl
import com.niyaj.popos.features.qrcode_scanner.domain.repository.QRCodeScanner
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(SingletonComponent::class)
object ScannerModule {

    @Provides
    fun provideContext(app: Application):Context{
        return app.applicationContext
    }

    @Provides
    fun provideBarCodeOptions() : GmsBarcodeScannerOptions {
        return GmsBarcodeScannerOptions.Builder()
            .setBarcodeFormats(Barcode.FORMAT_QR_CODE)
            .build()
    }

    @Provides
    fun provideGooglePlayModule(context: Context) : ModuleInstallClient {
        return ModuleInstall.getClient(context)
    }

    @Provides
    fun provideBarCodeScanner(context: Context, options: GmsBarcodeScannerOptions): GmsBarcodeScanner {
        return GmsBarcodeScanning.getClient(context, options)
    }

    @Provides
    fun provideBarCodeScannerRepository(scanner : GmsBarcodeScanner, playModule : ModuleInstallClient): QRCodeScanner {
        return QRCodeScannerImpl(scanner, playModule)
    }
}
Sk Niyaj Ali
  • 16
  • 1
  • 2