はじめに
今回の内容は、以下の記事の続きのようなものです。
●Flutterアプリ(flutter_blue_plus の Android用サンプル)と micro:bit CreateAI のプログラムを BLE通信でつないでみる - Qiita
https://qiita.com/youtoy/items/b8e14601ecab557d3f72
上記の記事では、flutter_blue_plus のサンプルアプリを Androidスマホで動かしてみました。
今回は、flutter_blue_plus を使った Flutter での BLEスキャンを実装してみます。
利用するパッケージ
前回同様、以下のパッケージを使います。
●flutter_blue_plus | Flutter package
https://pub.dev/packages/flutter_blue_plus
実際に試していく
下準備
Android Studio で、新規の Flutter用プロジェクトを作成し、今回用の下準備を進めます。
パッケージのインストール
以下のコマンドで、flutter_blue_plus をインストールします(自分の環境は FVM を使っているので、先頭部分に fvm をつけています)。
fvm flutter pub add flutter_blue_plus
パーミッションの追加
「android/app/src/main/AndroidManifest.xml」にパーミッションを追加します。
追加する内容は、flutter_blue_plus の公式ページの以下に書かれているものです。
●flutter_blue_plus | Flutter package
https://pub.dev/packages/flutter_blue_plus#add-permissions-for-android-no-location
自分のスマホは Android 15 なので、以下の部分だけ追記します。
<!-- Tell Google Play Store that your app uses Bluetooth LE
Set android:required="true" if bluetooth is necessary -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false" />
<!-- New Bluetooth permissions in Android 12
https://developer.android.com/about/versions/12/features/bluetooth-permissions -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
追記後の冒頭部分は、以下のとおりです。
スキャンする処理を実装する
公式ページの以下の部分に、スキャンに関するコードが載っています。
●flutter_blue_plus | Flutter package
https://pub.dev/packages/flutter_blue_plus#scan-for-devices
これを、処理の中に組み込んでいきます。
画面構成
今回のアプリの画面構成は、とりあえずシンプルなもので試してみます。
具体的には、「スキャンを開始するボタン」と「スキャンできたデバイスを表示する部分」がメインの要素になる形にしました。
コード
コードは以下のとおりです。
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();
});
// BluetoothがONになるまで待機
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;
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),
),
);
}
}
スキャン結果
アプリをビルドして Androidスマホ上で動かします。
画面右下のボタンを押下するとスキャンが始まり、冒頭の記事でも扱っていた micro:bit もスキャン結果の中に出てきました。

おわりに
とりあえず、flutter_blue_plus を使った BLEスキャンの実装を試せました。
最終的にやりたいことは、特定のデバイスに接続して、そのデバイスと Flutterアプリとの間で通信をさせることなので、その実装も試していければと思います。
その他
スキャン用の処理が書かれた部分のリンクで、「Common Problems」というものがあって気になったので、(いつか使う時があるかもしれないのもあり)メモしておきます。
●flutter_blue_plus | Flutter package
https://pub.dev/packages/flutter_blue_plus#common-problems
【追記】 対象の絞り込みを行うもの
その後、「デバイス名に特定の文字列を含むもののみを表示する」という処理を加えたものも作ってみました。
●flutter_blue_plus を使った Flutter での BLEスキャン実装で表示するものをフィルタする - Qiita
https://qiita.com/youtoy/items/0247179d4065c8d69d19