こんにちは、CX事業本部 Delivery部の若槻です。
flutter_nearby_connectionsは、FlutterアプリでP2P(peer-to-peer)通信を可能とするプラグインパッケージです。近接しているiOSやAndroidデバイスの間でBluetoothやWi-FiによるP2P通信が可能となります。
今回は、flutter_nearby_connectionsを使用してiOS Simulatorのデバイス間でのP2P通信を試してみました。
やってみた
Flutterプロジェクト新規作成
flutter create flutter_sample_app
パッケージインストール
flutter_nearby_connections
をインストールして追加します。
flutter pub add flutter_nearby_connections
追加できました。
pubspec.yaml
dependencies:
flutter_nearby_connections: ^1.1.1
またその他必要なパッケージとしてdevice_info_plusおよびflutter_styled_toastをインストールします。
flutter pub add device_info_plus flutter_styled_toast
実装
Info.plist
に次の通りキーを追加します。(この時VSCodeから編集する場合はXMLの記述の自動フォーマットによる型くずれに注意してください。こちらで回避策を紹介しています。)
ios/Runner/Info.plist
<key>NSBonjourServices</key>
<array>
<string>_mpconn._tcp</string>
</array>
<key>UIRequiresPersistentWiFi</key>
<true/>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>flutter_nearby_connection</string>
それぞれのキーの用途はこのようになります。
- NSBonjourServicesでは、
_{YOUR_SERVICE_TYPE}._tcp
のようにアプリが使用するBonjourサービスタイプを指定します。 - UIRequiresPersistentWiFiでは、アプリがWi-Fi接続を要求するかどうかを指定します。
- NSBluetoothAlwaysUsageDescriptionでは、アプリがBluetoothにアクセスする理由を記述します。Bluetooth接続をする場合は必須です。
次にmain.dart
にExampleのコードをそのまま記述しますが、古い環境向けの記述となっているため、若干の修正が必要です。
device_info
は配布停止しているので、device_info_plus
を使うようにインポートする記述に置き換えます。これによりデバイスやOSの情報を取得できるようにします。
- import 'package:device_info/device_info.dart';
+ import 'package:device_info_plus/device_info_plus.dart';
device_info_plus
によるデバイスモデル名の取得でタイプエラーを抑制するようにします。また通信時に利用する端末名が重複しないように、環境変数で渡した名前を末尾に付与するようにします。
+ const USERNAME = String.fromEnvironment("USERNAME");
+
nearbyService = NearbyService();
String devInfo = '';
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
if (Platform.isAndroid) {
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
devInfo = androidInfo.model;
}
if (Platform.isIOS) {
IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
+ devInfo = iosInfo.localizedModel!;
- devInfo = iosInfo.localizedModel;
}
await nearbyService.init(
serviceType: 'mpconn',
+ deviceName: devInfo + ' ' + String.fromEnvironment("USERNAME"),
- deviceName: devInfo,
strategy: Strategy.P2P_CLUSTER,
callback: (isRunning) async {
if (isRunning) {
if (widget.deviceType == DeviceType.browser) {
await nearbyService.stopBrowsingForPeers();
await Future.delayed(Duration(microseconds: 200));
await nearbyService.startBrowsingForPeers();
} else {
await nearbyService.stopAdvertisingPeer();
await nearbyService.stopBrowsingForPeers();
await Future.delayed(Duration(microseconds: 200));
await nearbyService.startAdvertisingPeer();
await nearbyService.startBrowsingForPeers();
}
}
});
ちなみに上記でStrategyとして指定したP2P_CLUSTER
では「M-to-N」通信が可能となります。P2P_STAR
を指定すると「1-to-N」通信、P2P_POINT_TO_POINT
を指定すると「1-to-1」通信が可能となります。
動作確認
iOS Simulatorで動作確認をしてみます。
iPhoneを3台起動します。
Flutterアプリを複数台のiOS Simulatorデバイスで同時に実行する方法はこちらを参考にしてください。
flutter devices
でそれぞれのデバイスIDを確認し、flutter run
でそれぞれのデバイスと任意の重複しない名前を指定しアプリを実行します。
$ flutter devices
5 connected devices:
iPhone 14 Pro (mobile) • 303EE434-DF48-40EF-B58C-AF4B6778F1B4 • ios • com.apple.CoreSimulator.SimRuntime.iOS-16-1 (simulator)
iPhone 14 Pro Max (mobile) • 2CA618C6-E1DF-42E2-B555-541EE8A289B3 • ios • com.apple.CoreSimulator.SimRuntime.iOS-16-1 (simulator)
iPhone 14 Pro Max 2 (mobile) • 2922EF27-FB61-4D23-B640-053CDFE46AC4 • ios • com.apple.CoreSimulator.SimRuntime.iOS-16-1 (simulator)
macOS (desktop) • macos • darwin-arm64 • macOS 12.6 21G115 darwin-arm
$ flutter run -d 303EE434-DF48-40EF-B58C-AF4B6778F1B4 --dart-define=USERNAME=John
$ flutter run -d 2CA618C6-E1DF-42E2-B555-541EE8A289B3 --dart-define=USERNAME=Risa
$ flutter run -d 2922EF27-FB61-4D23-B640-053CDFE46AC4 --dart-define=USERNAME=Tanaka
アプリを実行できました。
そして実際にアプリを使用して3台のデバイス間でトポロジー通信をさせている様子です。
BROWSERとなっている1台の端末と、ADVERTISERの2台の端末の間で通信ができています。
注意点
flutter_nearby_connections
はすごく簡単にP2P通信が実装できてとても楽しいパッケージですが、現在アクティブにメンテナンスされていない(最終更新は20ヶ月前)ため、本番導入する際はご注意ください。
そのため類似のパッケージを探したところflutter_blue_plusというパッケージがアクティブにメンテナンスが行われており良さそうでした。次回はこちらを試してみたいと思います。
参考
- flutter_nearby_connections で Bluetooth 通信
- String.fromEnvironment constructor - String - dart:core library - Dart API
以上