📸
Jetpack ComposeでQRコードを読み取る
読んでほしい人
- Jetpack Composeで開発をやっている人
- QRコードのスキャンをやってみたい人
補足情報
こちらの動画を参考に進めてください。
そもそもQRコードとは?
QRコード(キューアールコード)は、あらゆるデータ(数字、英字、漢字、カタカナ、ひらがな、記号、バイナリ、制御コードなど)を扱うことができる2次元コードのことで、1つのQRコードで最大文字数が7089文字(数字のみの場合)という大量のデータを格納できます。最近では、郵便局での送り状の作成や、SNSアカウントのログイン、ライブチケットのスキャンなど、いたるところで活用されています。
Android Studioの設定に慣れている必要があります。xmlをコピペするだけですが、設定する場面があります。こちらのGithubのxmlのコードが必要です。動画の通りにやっていけば、設定はできます。
こちらを追加する。
<!-- drawable/qrcode-scan.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M4,4H10V10H4V4M20,4V10H14V4H20M14,15H16V13H14V11H16V13H18V11H20V13H18V15H20V18H18V20H16V18H13V20H11V16H14V15M16,15V18H18V15H16M4,20V14H10V20H4M6,6V8H8V6H6M16,6V8H18V6H16M6,16V18H8V16H6M4,11H6V13H4V11M9,11H13V15H11V13H9V11M11,6H13V10H11V6M2,2V6H0V2A2,2 0 0,1 2,0H6V2H2M22,0A2,2 0 0,1 24,2V6H22V2H18V0H22M2,18V22H6V24H2A2,2 0 0,1 0,22V18H2M22,22V18H24V22A2,2 0 0,1 22,24H18V22H22Z" />
</vector>
記事の内容
buidl.gradleにQRコードのライブラリを追加する:
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}
android {
namespace = "com.example.qrapp"
compileSdk = 34
defaultConfig {
applicationId = "com.example.qrapp"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.1"
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
}
dependencies {
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
implementation("androidx.activity:activity-compose:1.8.2")
implementation(platform("androidx.compose:compose-bom:2023.08.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
androidTestImplementation(platform("androidx.compose:compose-bom:2023.08.00"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
// QRのためのライブラリzxingを追加
implementation ("com.journeyapps:zxing-android-embedded:4.3.0")
implementation ("com.google.zxing:core:3.4.1")
}
QRコードのスキャンをする設定をAndroidManifest.xml
に追加する必要があります。
この設定を追加する:
<!-- QR CODEの設定を追加 -->
<activity android:name="com.journeyapps.barcodescanner.CaptureActivity"
android:screenOrientation="fullSensor"
tools:replace="android:screenOrientation"
/>
さっきファイル作ったので、qr_scan
が作れないので名前をqr_scan_test
にしてます💦
drawable
というディレクトを右クリックして、スクリーンショットのように、ファイルの新規作成をおこないます。
ファイル名を入力する
こちらの作成されたxmlファイルにGithubのxmlのコードを貼り付ける
修正後QRのiconが表示された!
デモ用のサンプルコード:
package com.example.qrapp
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.content.ContextCompat
import com.example.qrapp.ui.theme.QRAppTheme
import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanOptions
class MainActivity : ComponentActivity() {
// QRコードの読み取り結果を格納する変数
private var textResult = mutableStateOf("")
// QRコードの読み取り結果を格納する変数を返す
private val barCodeLauncher = registerForActivityResult(ScanContract()) { result ->
if (result.contents == null) {
Toast.makeText(this@MainActivity, "Cancelled", Toast.LENGTH_LONG).show()
} else {
textResult.value = result.contents
}
}
// カメラのパーミッションをリクエストする
private fun showCamera() {
val options = ScanOptions()
options.setDesiredBarcodeFormats(ScanOptions.QR_CODE)
options.setPrompt("QRコードを読み取ってください")
options.setCameraId(0)
options.setBeepEnabled(false)
barCodeLauncher.launch(options)
}
// カメラのパーミッションをリクエストする
private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) {
isGranted ->
if(isGranted) {
showCamera()
}
}
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
QRAppTheme {
// QRコードの読み取り結果を表示するUI
Scaffold(
bottomBar = {
BottomAppBar(
actions = {},
// 画面右下にQRコードを読み取るためのボタンを表示
floatingActionButton = {
FloatingActionButton(onClick = { checkCameraPermission(this@MainActivity) }) {
Icon(
painter = painterResource(id = R.drawable.qr_scan),
contentDescription = "QR Scan"
)
}
},
)
}
) { innerPadding ->
// QRコードの読み取り結果を画面中央に表示
Column(
modifier = Modifier.fillMaxSize()
.padding(innerPadding),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
painter = painterResource(id = R.drawable.qr_scan),
modifier = Modifier.size(100.dp),
contentDescription = "QR"
)
// QRコードの読み取り結果をUIに表示
Text(text = textResult.value,
fontSize = 30.sp,
fontWeight = FontWeight.Bold
)
}
}
}
}
}
// カメラのパーミッションをチェックする
private fun checkCameraPermission(context: Context) {
if(ContextCompat.checkSelfPermission(
context,
android.Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED) {
showCamera()
} else if(shouldShowRequestPermissionRationale(android.Manifest.permission.CAMERA)) {
Toast.makeText(this@MainActivity, "Camera required", Toast.LENGTH_LONG).show()
} else {
requestPermissionLauncher.launch(android.Manifest.permission.CAMERA)
}
}
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
QRAppTheme {
}
}
実際に使ってみる:
最後に
QRコードに興味がありネイティブで機能を実装してみました。Flutterではやったことなくて、ネイティブで今回実装してみましたが、まさかxml書くとは思いませんでしたね💦
ご興味ある方は試してみてください。
Discussion