株式会社プレイモーションで CROSS ME(クロスミー) というマッチングアプリの Android 版を担当している tatuas です。

 

今月 12 日よりリリースした新機能 CROSS ME SPOT は、同じ場所にいる人同士がマッチングできる、国内初の機能です。余談ですが、今年 10 月にプレイモーションにジョインして以降、自分としては初めての新機能実装となり、今回のリリースに大変ワクワクしています。

 

CROSS ME SPOT

 

CROSS ME SPOT では、同じ空間にいる人同士の検出に、 Beacon を用いています。一般的に Beacon は、 iOS7 以降で利用可能な屋内測位システムと認識されているかと思いますが、技術的には BLE ( Bluetooth Low Enargy ) を使った近距離通信ですので、 BLE が搭載された Android 4.3 以降の端末であれば、iOS 端末と同様に信号を受け取ること自体は可能です。

 

ただ iOS 端末と違ってAndroid 端末の場合、端末ごとにハードウェアや挙動の違いがあるため、その点を考慮しつつ、 CROSS ME SPOT の実現方法を模索しました。

 

今回 Android 端末で Beacon を検出する方法として、 Radius Network 社が開発している android-beacon-library を採用することにしました。すでに他のアプリで実績があるほか、最近 Android Oreo 対応も入るなど、継続的にメンテナンスされていて安心感があります。また、 Beacon を取得・検出する方法が比較的容易だったことも理由です。

android-beacon-library で Beacon を検出する

 

android-beacon-library では、 2 つの方法で Beacon 情報を検出・取得することができます。 1 つめは、 Android 端末が特定の Beacon 領域への出入り状況を取得する方法、 2 つめは Android 端末周辺に存在する Beacon 情報を取得する方法です。

 

以下はそれぞれの方法で取得する際の擬似コードです。実際には動作しませんが、大まかなイメージは掴んでいただけるかと思います。

 

1. Android 端末が特定の Beacon 領域への出入り状況を取得する方法

 


val beaconManager = BeaconManager.getInstanceForApplication(context)

val region = Region(uniqueId, uuid, major, minor) // 監視したい Beacon

beaconManager.addMonitorNotifier(object : MonitorNotifier {
    override fun didEnterRegion(region: Region) {
        Log.i(TAG, "入室")
    }

    override fun didExitRegion(region: Region) {
        Log.i(TAG, "退室")
    }

    override fun didDetermineStateForRegion(state: Int, region: Region) {
        Log.i(TAG, "状態に変化あり")
    }
})

beaconManager.startMonitoringBeaconsInRegion(region)


2. Android 端末周辺に存在する Beacon 情報を取得する方法

 


val beaconManager = BeaconManager.getInstanceForApplication(context)

val region = Region("", null, null, null) // 周辺にある全ての Beacon

beaconManager.addRangeNotifier(object : RangeNotifier {
    override fun didRangeBeaconsInRegion(beaconList: MutableCollection, region: Region) {
        Log.i(TAG, beaconList.toString()) // Android 端末周辺に存在する Beacon 情報
        Log.i(TAG, region.toString()) // 監視している Beacon
    }
})

beaconManager.startRangingBeaconsInRegion(region)


 

実際に動作するサンプルも用意しています。

GitHub – tatuas/BeaconSample

取得できる Beacon の情報

 

android-beacon-library では、取得できる Beacon の情報は数多くありますが、詳細はドキュメントに譲り、今回の実装で主に見ている値をまとめます。

 

  • UUID:同一グループの Beacon かどうかを識別するための文字列
  • Major:個別の Beacon を識別する整数で、 Minor とセットで一意に設定する
  • Minor:個別の Beacon を識別する整数で、 Major とセットで一意に設定する
  • 距離:検出している Beacon と端末との距離(メートル単位)

 

UUID はその名称から、重複が許されていない Beacon の個別識別子にように見えますが、実際には同一グループの UUID という意味です。Beacon 自体の識別には、この UUID と Major 並びに Minor を用いることが多いようです。例えば iOS の場合、 1 つのアプリがスキャンできる Beacon の台数は 20 台までという制限があるので、同一空間内の Beacon をグループと定義して UUID を統一し、 Major と Minor の組み合わせで、 20 台以上の Beacon をそれぞれ識別する、という方法を取ることができます。

 

CROSS ME SPOT での使用例

 

実際の店舗では、以下のように複数台の Beacon が設置されています。

 

店舗イメージ図

 

最初の仕様策定では、1 つめの Android 端末が特定の Beacon 領域への出入り状況を取得する方法で Beacon を検知することを想定していました。ところが実際に各 Beacon を登録して、Beacon 領域の出入を Android 端末で検出してみたところ、正しく出入りを検出できなくなる場合があり、今ひとつ安定しなかったため、この方法は最終的に採用しませんでした。

 

そのため今回では、 2 つめの Android 端末周辺に存在する Beacon 情報を取得する方法を採用しています。この場合は、 Android 端末が検出できた
Beacon を Collection 型で返却してくれますので、アプリ側で取得できた Beacon 情報を距離の近い順に並べ替え、もっとも近い Beacon の情報をサーバに送信するようにしています。サーバは送信された Beacon 情報をもとに、各店舗の Beacon 情報と照らし合わせ、その Android 端末がどの店舗に存在しているのかを推測しています。またバッテリー消費量も配慮し、アプリが起動中のみ一定間隔で Beacon 情報を取得するようにしています。

 

最後に

 

最後に宣伝となりますが、 CROSS ME SPOT は、第一弾として、2017年12月12日(火)から12月25日(月)の期間、株式会社セクションエイトが運営するバー The Public stand の全店舗(銀座店、渋谷店、六本木店、歌舞伎町店、恵比寿店)にて体験することができますので、実際に CROSS ME SPOT をお試し頂ければと思います!

 

The Public Stand

 

また期間中に CROSS ME をインストールして頂くと、もれなく The Public stand で使える SPECIAL COUPON が貰えますので、そちらも合わせてご活用ください!

 

Coupon

tatuas
2017 年中途入社の Android エンジニアです。現在はクロスミーの Android 版を担当しています。