flutter_blue_plus を使った Flutter での BLEスキャン実装で表示するものをフィルタする

### はじめに

以下の記事を書いていた際に実装した Flutter の処理に少し手を加えてみました。

●flutter_blue_plus を使った BLEスキャンを Flutter で実装してみる： Android Studio で Androidアプリをビルド - Qiita
　https://qiita.com/youtoy/items/66b0563005c62b926ce1

### 追加する内容

対象を絞らず BLEスキャンをすると、たくさんのデバイスを検出してしまうことが多いです。

これだと、自分がスキャンしたい特定のデバイスが検出できているかが分かりにくいので、スキャンデバイスから特定のデバイスのみを絞り込むという内容を加えてみます。


## 試してみる

冒頭に掲載していた記事で書いたプログラムに、最小限の変更を加えたものを作ってみます。

### 実装内容

絞り込みの条件には、デバイス名を用います。

またデバイス名の絞り込み条件について、ひとまず名前に「toio」「BBC micro:bit」を含むものにしてみます。


### 実装した内容

実際のコードは、以下のとおりです。


```dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'BLE Scan Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'BLE Scan Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final List<String> _scanResults = [];
  StreamSubscription<List<ScanResult>>? _scanSubscription;

  // スキャン開始
  Future<void> _startScan() async {
    // 前回の結果をクリア
    setState(() {
      _scanResults.clear();
    });

    await FlutterBluePlus.adapterState
        .firstWhere((state) => state == BluetoothAdapterState.on);

    // 結果の取得
    _scanSubscription = FlutterBluePlus.onScanResults.listen(
          (results) {
        for (var result in results) {
          final deviceId = result.device.remoteId.toString();
          final deviceName = result.advertisementData.advName;
          // ["BBC micro:bit", "toio"] のいずれかの文字列を含むかチェック
          if (!["BBC micro:bit", "toio"]
              .any((filter) => deviceName.contains(filter))) {
            continue;
          }
          final info = '$deviceId: "$deviceName"';
          if (!_scanResults.contains(info)) {
            setState(() {
              _scanResults.add(info);
            });
          }
        }
      },
      onError: (e) => print('Error: $e'),
    );

    // タイムアウト15秒でスキャン実行
    await FlutterBluePlus.startScan(timeout: const Duration(seconds: 15));

    await FlutterBluePlus.isScanning
        .firstWhere((isScanning) => isScanning == false);

    FlutterBluePlus.cancelWhenScanComplete(_scanSubscription!);
    _scanSubscription = null;
  }

  @override
  void dispose() {
    _scanSubscription?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: _scanResults.isEmpty
          ? const Center(child: Text('スキャン結果はありません'))
          : ListView.builder(
        itemCount: _scanResults.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(_scanResults[index]),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _startScan,
        tooltip: 'BLEスキャン',
        child: const Icon(Icons.search),
      ),
    );
  }
}
```

#### 実行結果

上記を実行してみた結果を掲載してみます。

スキャンを実行する前に toio 2台と micro:bit 1台を検出できるようにしておき、その後にスキャンを試しました。

![485497533_4028890260717906_6778357144454176494_n コピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/464e230f-23c5-403a-ad5a-2fca8ce0583d.jpeg)

上記のとおり、スキャン対象として絞り込んだデバイスのみ表示されるようになりました。