この投稿は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ベースでの記事が続々と出ると思いますので、私からは、最初の一歩という形の記事にさせていただきました。