How to Create a QR Code Scanner in Jetpack Compose
Jetpack Compose is Android’s recommended modern toolkit for building native UI. It simplifies and accelerates UI development on Android. In this article, we are going to create a QR code scanner to demonstrate how to use Dynamsoft Barcode Reader and Dynamsoft Camera Enhancer in Jetpack Compose.
Here is a video of the final result:
SDKs Used
- Dynamsoft Camera Enhancer. An SDK which makes it easy to use cameras on mobile platforms.
- Dynamsoft Barcode Reader. An SDK to read barcodes and QR codes with great performance.
New Project
Open Android Studio and create a new project with an empty compose activity.
Add Dependencies
-
Open
settings.gradle
to add Dynamsoft’s maven repository.dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() + maven { + url "https://download2.dynamsoft.com/maven/aar" + } } }
-
Add Dynamsoft Barcode Reader and Dynamsoft Camera Enhancer to the module’s
build.gradle
.implementation 'com.dynamsoft:dynamsoftcameraenhancer:2.3.11@aar' implementation 'com.dynamsoft:dynamsoftbarcodereader:9.6.20@aar'
Add Camera View
Dynamsoft Camera Enhancer provides a CameraView class for camera preview. We can add it to the content and make it occupies the entire screen.
Here is the code to do this:
class MainActivity : ComponentActivity() {
private lateinit var mCameraEnhancer: CameraEnhancer
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
QRCodeScannerTheme {
// A surface container using the 'background' color from the theme
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
AndroidView(factory = {context ->
mCameraEnhancer = CameraEnhancer(context.findActivity())
val mCameraView: DCECameraView
mCameraView = DCECameraView(context)
mCameraView.overlayVisible = true
mCameraEnhancer.cameraView = mCameraView
mCameraView
})
}
}
}
}
}
It requires the activity instance for initialization. We can define a findActivity
function for Context
to get it.
//https://stackoverflow.com/a/74696154/17238341
fun Context.findActivity(): ComponentActivity? = when (this) {
is ComponentActivity -> this
is ContextWrapper -> baseContext.findActivity()
else -> null
}
Request Camera Permission and Start the Camera
We have to request camera permission to use the camera.
-
Define a launcher to request permission. If the permission is granted, then start the camera.
setContent { QRCodeScannerTheme { val context = LocalContext.current val launcher = rememberLauncherForActivityResult( contract = ActivityResultContracts.RequestPermission(), onResult = { granted -> if (granted == true) { mCameraEnhancer.open() } } ) } }
-
The launcher is called when the app starts using
LaunchedEffect
.setContent { QRCodeScannerTheme { //... LaunchedEffect(key1 = true){ launcher.launch(Manifest.permission.CAMERA) } } }
Use Dynamsoft Barcode Reader to Read QR Codes
-
Set the license. You can apply for a trial license here. If the license is not set, the result will be masked.
private fun initLicense(){ BarcodeReader.initLicense( "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==" //one-day trial ) { isSuccess, error -> if (!isSuccess) { error.printStackTrace() }else{ Log.d("DBR","license initialized") } } }
Call the function in
LaunchedEffect
:LaunchedEffect(key1 = true){ initLicense() }
-
Create an instance of Barcode Reader and bind the barcode reader with the camera enhancer.
private lateinit var mBarcodeReader: BarcodeReader private fun initDBR(){ try { // Create an instance of Dynamsoft Barcode Reader. mBarcodeReader = BarcodeReader() // Bind the Camera Enhancer instance to the Barcode Reader instance to get frames from the camera. mBarcodeReader.setCameraEnhancer(mCameraEnhancer) }catch (e: BarcodeReaderException){ e.printStackTrace() } }
Call the function in
LaunchedEffect
:LaunchedEffect(key1 = true){ initDBR() }
-
Start scanning after the camera is opened and display the QR code result on the screen in a Text control above the camera view.
setContent { QRCodeScannerTheme { var barcodeTextResult by remember { mutableStateOf("") } val launcher = rememberLauncherForActivityResult( contract = ActivityResultContracts.RequestPermission(), onResult = { granted -> hasCameraPermission = granted if (granted == true) { mCameraEnhancer.open() startScanning() { result -> barcodeTextResult = result.barcodeFormatString+": "+result.barcodeText } } } ) //... Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) { AndroidView(factory = {context -> mCameraEnhancer = CameraEnhancer(context.findActivity()) val mCameraView: DCECameraView mCameraView = DCECameraView(context) mCameraView.overlayVisible = true mCameraEnhancer.cameraView = mCameraView mCameraView }) BarcodeText(text = barcodeTextResult) } } } //... @Composable fun BarcodeText(text:String) { Text( text = text, color = Color.White, fontSize = 20.sp ) } private fun startScanning(scanned:(TextResult) -> Unit){ try{ mBarcodeReader.setTextResultListener { id, imageData, textResults -> if (textResults.size>0) { scanned(textResults[0]) } } mBarcodeReader.startScanning() } catch (e: BarcodeReaderException) { e.printStackTrace() } }
All right, we’ve now finished creating the QR code scanner in Jetpack Compose.
Source Code
Check out the source code of the demo to have a try: https://github.com/tony-xlh/QR-Code-Scanner-Jetpack-Compose