**使用ライブラリ名(例):** ZXing
以下は、Jetpack Compose Multiplatform(主にAndroid対象)で、画面中央の正方形領域でQRコードをスキャンし、読み込んだテキストをSnackbarで表示するサンプルコード例です。
ライブラリの依存関係はbuild.gradle.kts側で設定するため、ここでは使用するライブラリ名のみ明記しています。
カメラ映像取得にはCameraX、QRコード解析にはZXingを想定しています。
```kotlin
import
androidx.camera.core.ImageAnalysis
import
androidx.camera.core.ImageProxy
import
androidx.camera.core.ImageCapture
import
androidx.camera.core.Preview
import
androidx.camera.lifecycle.ProcessCameraProvider
import
androidx.compose.foundation.background
import
androidx.compose.foundation.layout.*
import
androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds
import
androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.content.ContextCompat
import
com.google.zxing.MultiFormatReader
import
com.google.zxing.BinaryBitmap
import
com.google.zxing.LuminanceSource
import
com.google.zxing.common.HybridBinarizer
import kotlinx.coroutines.delay
@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
@Composable
fun QrCodeReaderScreen() {
val lifecycleOwner = LocalLifecycleOwner.current
val cameraProviderFuture = remember {
ProcessCameraProvider.getInstance(LocalContext.current)
}
var scannedText by remember { mutableStateOf<String?>(null) }
val snackbarHostState = remember { SnackbarHostState() }
LaunchedEffect(scannedText) {
scannedText?.let { text ->
snackbarHostState.showSnackbar("Scanned:
$text")
// スキャン後、表示を少し待って再スキャン可能な状態へ戻す例
delay(2000)
scannedText = null
}
}
// カメラ準備ができたらPreviewとImageAnalysisをセットアップ
LaunchedEffect(cameraProviderFuture) {
val cameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder().build()
val imageAnalysis = ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build().also {
it.setAnalyzer(ContextCompat.getMainExecutor(LocalContext.current)) { imageProxy ->
val result = analyzeImage(imageProxy)
if (result != null && scannedText == null) {
scannedText = result
}
imageProxy.close()
}
}
val cameraSelector =
androidx.camera.core.CameraSelector.DEFAULT_BACK_CAMERA
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview, imageAnalysis)
// Preview用のSurface
preview.setSurfaceProvider { request ->
val surfaceTexture =
android.graphics.SurfaceTexture(0).apply {
detachFromGLContext()
}
val surface = android.view.Surface(surfaceTexture)
request.provideSurface(surface, ContextCompat.getMainExecutor(LocalContext.current)) {
surface.release()
surfaceTexture.release()
}
}
}
Scaffold(
snackbarHost = { SnackbarHost(snackbarHostState) }
) { paddingValues ->
Box(modifier = Modifier.fillMaxSize().padding(paddingValues)) {
// カメラプレビュー表示用のView
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = { context ->
android.view.TextureView(context).apply {
// CameraXのPreview用SurfaceProviderは上記で設定済みのため実際の表示処理はここでは省略。
// 実際にはCameraX PreviewViewを用いることを推奨(AndroidViewでPreviewViewを表示)。
}
}
)
// 中央に正方形の枠をオーバーレイ
Box(
modifier = Modifier
.align(
Alignment.Center)
.size(200.dp)
.clipToBounds()
.background(Color.Transparent)
.border(width = 2.dp, color = Color.White, shape = RoundedCornerShape(4.dp))
)
}
}
}
/**
* ImageProxyからQRコードを解析
*/
fun analyzeImage(imageProxy: ImageProxy): String? {
val buffer = imageProxy.planes[0].buffer
val bytes = ByteArray(buffer.remaining())
buffer.get(bytes)
// 画像の向きやColorFormatに合わせたLuminanceSourceの作成が必要
val source: LuminanceSource = object : LuminanceSource(imageProxy.width, imageProxy.height) {
override fun getMatrix(): ByteArray = bytes
override fun getRow(y: Int, row: ByteArray?): ByteArray {
val start = y * width
return bytes.copyOfRange(start, start width)
}
}
val bitmap = BinaryBitmap(HybridBinarizer(source))
return try {
val result = MultiFormatReader().decode(bitmap)
result.text
} catch (e: Exception) {
null
}
}
```
**ポイント:**
- 上記コード例はあくまで概念的なサンプルであり、実際に動作させるにはCameraXのPreviewViewの導入やSurfaceProviderの正しい設定、ImageProxyのカラー変換処理等が必要になる場合があります。
- 「ZXing」ライブラリを使用することでQRコードのデコードを行っています。
- スキャン結果をSnackbarで表示し、2秒後に再スキャンできるようにクリアしています。
- 正方形領域は単に中央に白枠を配置しているだけで、実際の解析範囲を限定したい場合はImageAnalysis処理側でクロップなどの加工が必要です。