15
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

FlutterでiBeaconを発信/検出してみた

Last updated at Posted at 2020-01-15

FlutterアプリでiBeaconを検出したり、発信したりしてみたので、ざっくりまとめておく。

iBeaconとは

iBeaconそのものについては、下記の記事を参照。主にiOS等で使われるbeacon技術。

iBeacon - ウィキペディア
iBeaconとは - ケータイ Watch Watch

発信

発信側はpszklarska/beacon_broadcastを使って発信する。


BeaconBroadcast beaconBroadcast = BeaconBroadcast();
bool isAdvertising = await beaconBroadcast.isAdvertising();
BeaconStatus transmissionSupportStatus = await beaconBroadcast.checkTransmissionSupported();

if (!isAdvertising && transmissionSupportStatus == BeaconStatus.SUPPORTED) {
  final String iBeaconFormat = 'm:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24';
  await beaconBroadcast
      .setUUID(Uuid().v5(Uuid.NAMESPACE_URL, 'sample.beacon.com'))
      .setMajorId(1)
      .setMinorId(100)
      .setIdentifier('com.beacon.sample')
      .setLayout(iBeaconFormat) // Android Only
      .start();
  Timer(
      Duration(seconds: 10),
          () {
        beaconBroadcast.stop();
      }
  );
}

BeaconBroadcastの方はisAdvertisingで発信中かどうか確認して、checkTransmissionSupportedで動作する端末かどうか確認して、発信している。
ポイントはsetLayout(iBeaconFormat)の部分で、iBeaconのフォーマットを指定している点。
iOSだと基本的にiBeaconのフォーマットにしか対応していないみたいで、setLayoutに何も指定せずにAndroid端末からbeaconを発信しても、iOS端末でbeaconを検知できない。
ちなみにBeaconBroadcastはデフォルトではAltBeaconのフォーマットになる。

検出

beaconを検出する側はalann-maulana/flutter_beaconを使う。

await flutterBeacon.initializeScanning;

AuthorizationStatus status = await flutterBeacon.authorizationStatus;
if (! (status == AuthorizationStatus.allowed
    || status == AuthorizationStatus.always
    || status == AuthorizationStatus.whenInUse)) {
  Scaffold.of(context).showSnackBar(
    SnackBar(content: Text("位置情報サービスをオンにする必要があります"))
  );
  return;
}

final regions = <Region>[
  Region(
    identifier: 'com.beacon.sample',
    proximityUUID: Uuid().v5(Uuid.NAMESPACE_URL, 'sample.beacon.com'),
  ),
];

StreamSubscription streamRanging = flutterBeacon.ranging(regions).listen((RangingResult result) {
  if (result != null && result.beacons.isNotEmpty) {
    result.beacons.forEach((beacon) {
      if (beacon.proximityUUID.toLowerCase() == uuid.toLowerCase()) {
        print('beaconを検出したよ!');
      }
    });
  }
});

StreamSubscription streamMonitoring = flutterBeacon.monitoring(regions).listen((MonitoringResult result) {
  if (result != null && result.region != null) {
    if (result.region.proximityUUID.toLowerCase() == BEACON_UUID.toLowerCase() && result.monitoringState == MonitoringState.inside) {
      print('beacon圏内に入ったよ!');
    }
  }
});

flutterBeaconはrangingやmonitoringのstreamをlistenした時点で各プラットフォームのbeacon検出をスタートさせるようになっていて、止める場合はstreamRanging.cancel()とすると止めることができる。streamRanging.closeしちゃうとそれ以降リスタートできないので注意。

rangingはアプリが起動中、常に監視してRangingResult.beaconsに現在圏内にいるbeaconを配列で受け取ることができる。

monitoringはbeaconの圏内に入った/出たを検出できて、バックグラウンドでも動作する。ただ、iOSの場合は位置情報が常に許可になっていないとバックグラウンドで動作しない。
バックグラウンドでの動作を期待する場合は、AuthorizationStatus.alwaysfalseだったらダイアログを出して設定に誘導する等した方が良いかもしれない。

参考記事

15
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?