AndroidでiBeacon信号を受信してみよう

  • 120
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

この投稿は2013年のiBeacon Advent Calendarの7日目の記事です。

はじめまして、主に、日本Androidの会 秋葉原支部で活動をしているKazuyukiEguchiです。

Advant Calendarに参加するのも初めてでこれで良いのか!?心配ですが。。。

AndroidでiBeacon信号を受信してみよう

Android 4.3から公式にBluetooth 4.0 LEのAPIがサポートされました。このAPIをうまく利用すると、iBeaconの電波を受信し、UUID,Major,Minorの値を取得することができます。

Manifestファイルに特権の追加

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

これは、今までのBluetooth APIを利用するときと変わりません。

Android Play にアプリをアップロードする際は、Bluetooth 4.0 LE搭載の機種でしか動作できませんよというおまじないも、Manifestファイルに記述してください。

<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

ソースコード記述編

Bluetooth Adapterの取得


final BluetoothManager bluetoothManager =
        (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();

Bluetooth LEデバイスの検索

mBluetoothAdapter.startLeScan(mLeScanCallback);

を呼び出すと、Bluetooth LEデバイスの探索を開始します。
コールバック関数の中身ですが、

private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
    @Override
    public void onLeScan(final BluetoothDevice device, int rssi,byte[] scanRecord) {
         // デバイスが検出される度に呼び出されます。
    });
};

実は、上記のコードだけで、iBeaconを検出することができているんです。

iBeaconにおけるUUID,Major,Minorの情報がないじゃんと思われますが、iBeaconの仕組みは、Bluetooth LEのAdvertisementパケットに工夫をして、iBeaconとして利用していますので、コールバック関数内のonLeScanの引数であるscanRecordの中に、UUID,Major,Minorの信号が含まれているんです。

取り出し例

if(scanRecord.length > 30)
{
    if((scanRecord[5] == (byte)0x4c) && (scanRecord[6] == (byte)0x00) &&
       (scanRecord[7] == (byte)0x02) && (scanRecord[8] == (byte)0x15))
    {
            String uuid = IntToHex2(scanRecord[9] & 0xff) 
            + IntToHex2(scanRecord[10] & 0xff)
            + IntToHex2(scanRecord[11] & 0xff)
            + IntToHex2(scanRecord[12] & 0xff)
            + "-"
            + IntToHex2(scanRecord[13] & 0xff)
            + IntToHex2(scanRecord[14] & 0xff)
            + "-"
            + IntToHex2(scanRecord[15] & 0xff)
            + IntToHex2(scanRecord[16] & 0xff)
            + "-"
            + IntToHex2(scanRecord[17] & 0xff)
            + IntToHex2(scanRecord[18] & 0xff)
            + "-"
            + IntToHex2(scanRecord[19] & 0xff)
            + IntToHex2(scanRecord[20] & 0xff)
            + IntToHex2(scanRecord[21] & 0xff)
            + IntToHex2(scanRecord[22] & 0xff)
            + IntToHex2(scanRecord[23] & 0xff)
            + IntToHex2(scanRecord[24] & 0xff);

            String major = IntToHex2(scanRecord[25] & 0xff) + IntToHex2(scanRecord[26] & 0xff);
            String minor = IntToHex2(scanRecord[27] & 0xff) + IntToHex2(scanRecord[28] & 0xff);
        }
}

上記のソースコードで、iOS7端末上で、Beacon送信している状態のパケット、Esitimote Beacon、その他iBeacon互換デバイスの信号の受信が出来ました。

これから、iBeacon Advent Calendar 2013では、Androidベースでの記事が続々と出ると思いますので、私からは、最初の一歩という形の記事にさせていただきました。

この投稿は iBeacon Advent Calendar 20137日目の記事です。