Flutter で QR コードスキャンを実装できる mobile_scanner を iOS アプリで試してみた

2023.09.17

こんにちは、CX事業本部 Delivery部の若槻です。

前回のエントリでは、Flutter Web アプリに QR コードスキャナーを実装してみました。

その際に使用した mobile_scanner というパッケージでは、Web 以外にも Android 、iOS および macOS に対応しています。

今回は、Flutter で QR コードスキャンを実装できる mobile_scanner を iOS アプリで試してみました。

試してみた

環境

Flutter、Dart

$ flutter --version
Flutter 3.7.7 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 2ad6cd72c0 (6 months ago) • 2023-03-08 09:41:59 -0800
Engine • revision 1837b5be5f
Tools • Dart 2.19.4 • DevTools 2.20.1

Xcode

$ /usr/bin/xcodebuild -version
Xcode 14.3.1
Build version 14E300c

iPhone

  • iOS 16.6.1
  • iPhone 12 Pro

Flutter プロジェクト作成

flutter create my_flutter_app
code my_flutter_app

パッケージ導入

flutter pub add mobile_scanner

導入されました。

$ git diff pubspec.yaml
diff --git a/pubspec.yaml b/pubspec.yaml
index 637449d..8a242bc 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -34,6 +34,7 @@ dependencies:
   # The following adds the Cupertino Icons font to your application.
   # Use with the CupertinoIcons class for iOS style icons.
   cupertino_icons: ^1.0.2
+  mobile_scanner: ^3.4.1
 
 dev_dependencies:
   flutter_test:

Info.plist へのキー追加

ios/Runner/Info.plistNSCameraUsageDescription を追加して、アプリケーションがカメラへのアクセスを求める理由を記述します。

$ git diff
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 04c8489..5b3e103 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -47,5 +47,7 @@
        </array>
        <key>UIViewControllerBasedStatusBarAppearance</key>
        <false/>
+       <key>NSCameraUsageDescription</key>
+       <string>This app needs camera access to scan QR codes</string>
 </dict>
 </plist>

ちなみに端末のフォトライブラリへアクセスする場合はさらに NSPhotoLibraryUsageDescription を追加する必要がありますが、今回は省きます。

実装

mobile_scanner をインポートして使用する処理を実装します。

lib/main.dart

import 'package:flutter/material.dart';
import 'package:mobile_scanner/mobile_scanner.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String scannedValue = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter Demo QR Code Scanner'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            SizedBox(
              height: 600,
              child: MobileScanner(
                controller: MobileScannerController(
                  detectionSpeed:
                      DetectionSpeed.noDuplicates, // 同じ QR コードを連続でスキャンさせない
                ),
                onDetect: (capture) {
                  // QR コード検出時の処理
                  final List<Barcode> barcodes = capture.barcodes;
                  final value = barcodes[0].rawValue;
                  if (value != null) {
                    // 検出した QR コードの値でデータを更新
                    setState(() {
                      scannedValue = value;
                    });
                    debugPrint(value);
                  }
                },
              ),
            ),
            Text(
              scannedValue == '' ? 'QR コードをスキャンしてください。' : 'QRコードを検知しました。',
              style: const TextStyle(fontSize: 15),
            ),
            // QR コードの値を表示
            Text(scannedValue == '' ? "" : "value: $scannedValue"),
          ],
        ),
      ),
    );
  }
}
  • MobileScanner() を使用すると端末のカメラが起動します。
  • onDetect プロパティで QR コードがスキャンされた際の処理を記述します。
  • capture.barcodes で読み取ったバーコードのリストを取得します。
  • MobileScannerControllerdetectionSpeed プロパティでスキャン時の速度を指定できます。
    • 今回は noDuplicates により同じ QR コードを連続でスキャンさせないようにしています。

動作確認

カメラ機能は Simulator では動作しないので、次のエントリを参考に MacBook に接続した実際の iPhone デバイスで動作確認します。

flutter run -d 00008101-001661062280001E

起動したアプリでカメラが起動します。

カメラ映像内に QR コードを検出すると、スキャンされて値が取得できていますね。

同画面が端末上で動作している様子を撮影した写真。

ホットリロードするとカメラが停止する

ちなみにアプリをホットリロードすると次のようにカメラが停止する場合があります。この場合はアプリケーションを一度バックグラウンドに移行して再度フォアグラウンドに戻すか、再起動するとまたカメラが起動します。

おわりに

Flutter で QR コードスキャンを実装できる mobile_scanner を iOS アプリで試してみました。

mobile_scanner を実際のデバイスである iPhone 上で動作させることができました。また、アプリケーションが端末のカメラや通信機能などハードウェア機能を利用する場合に今回の方法を使用すると容易にデバッグができて良いですね。是非お試しください。

参考

以上