AndroidでEddystone信号を受信してみよう
Eddystoneの公式HPのサンプルソースコードは、Android 5.0向けになっているので、 4.3,4.4のAPIで記述してみる。
Manifestファイルに特権の追加
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
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) {
// デバイスが検出される度に呼び出されます。
});
};
実は、上記のコードだけで、Eddystoneを検出することができているんです。
取り出し例
if(scanRecord.length > 14)
{
if((scanRecord[0] == (byte) 0x02) &&
(scanRecord[1] == (byte) 0x01) &&
(scanRecord[2] == (byte) 0x06) &&
(scanRecord[3] == (byte) 0x03) &&
(scanRecord[4] == (byte) 0x03) &&
(scanRecord[5] == (byte) 0xaa) &&
(scanRecord[6] == (byte) 0xfe) &&
(scanRecord[8] == (byte) 0x16) &&
(scanRecord[9] == (byte) 0xaa) &&
(scanRecord[10] == (byte) 0xfe))
{
switch(scanRecord[11])
{
case 0x0:
Log.d(TAG,"Eddystone-UID");
Log.d(TAG,"Ranging Data=" + IntToHex2(scanRecord[12]));
String namespace =
IntToHex2(scanRecord[13]) +
IntToHex2(scanRecord[14]) +
IntToHex2(scanRecord[15]) +
IntToHex2(scanRecord[16]) +
IntToHex2(scanRecord[17]) +
IntToHex2(scanRecord[18]) +
IntToHex2(scanRecord[19]) +
IntToHex2(scanRecord[20]) +
IntToHex2(scanRecord[21]) +
IntToHex2(scanRecord[22]);
String uid =
IntToHex2(scanRecord[23]) +
IntToHex2(scanRecord[24]) +
IntToHex2(scanRecord[25]) +
IntToHex2(scanRecord[26]) +
IntToHex2(scanRecord[27]) +
IntToHex2(scanRecord[28]);
Log.d(TAG,namespace+uid);
break;
case 0x10:
Log.d(TAG,"Eddystone-URL");
Log.d(TAG,"TX Power=" + IntToHex2(scanRecord[12]));
int len = scanRecord[7] - 6;
String Scheme = "";
switch(scanRecord[13])
{
case 0x0:
Scheme = "http://www.";
break;
case 0x1:
Scheme = "https://www.";
break;
case 0x2:
Scheme = "http://";
break;
case 0x3:
Scheme = "https://";
break;
}
String url = "";
for(int i = 0 ; i < len ; i++)
{
url = url + decodeURL(scanRecord[14 + i]);
}
Log.d(TAG,Scheme + url);
break;
case 0x20:
Log.d(TAG,"Eddystone-TLM");
Log.d(TAG,"Version=" + IntToHex2(scanRecord[12]));
Log.d(TAG,"VBATT=" + IntToHex2(scanRecord[13]) + IntToHex2(scanRecord[14]));
Log.d(TAG,"TEMP=" + IntToHex2(scanRecord[15]) + IntToHex2(scanRecord[16]));
Log.d(TAG,"ADVCNT=" + IntToHex2(scanRecord[17]) + IntToHex2(scanRecord[18])+ IntToHex2(scanRecord[19]) + IntToHex2(scanRecord[20]));
Log.d(TAG,"SECCNT=" + IntToHex2(scanRecord[21]) + IntToHex2(scanRecord[22])+ IntToHex2(scanRecord[23]) + IntToHex2(scanRecord[24]));
break;
}
}
}
URLをデコードするための関数の定義
private String decodeURL(int Value)
{
switch(Value)
{
case 0:
return ".com/";
case 1:
return ".org/";
case 2:
return ".edu/";
case 3:
return ".net/";
case 4:
return ".info/";
case 5:
return ".biz/";
case 6:
return ".gov/";
case 7:
return ".com";
case 8:
return ".org";
case 9:
return ".edu";
case 10:
return ".net";
case 11:
return ".info";
case 12:
return ".biz";
case 13:
return ".gov";
}
if((Value > 0x20) && (Value < 0x7f))
{
return String.format("%c",Value);
}
return "";
}