AndroidのBLEを使って受信してみる。(ビーコン受信とか向け)
・Android 7.1.1
1.受信コード
・AndroidManifest.xmlにパーミッション追記
<uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
bluetoothと位置情報の許可を出す(Androidのバージョンによって位置情報の許可は不要)
・activity_main.xmlにボタンを配置して、MainActivityのonCreateに追記する。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // ボタン押す findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { BluetoothManager bluetoothManager = (BluetoothManager)getSystemService(BLUETOOTH_SERVICE); BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter(); bluetoothAdapter.startLeScan(new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { String str = "onLeScan name:"+device.getName() + ", mac:"+device.getAddress() + ", rssi:"+rssi + ", len:"+scanRecord.length + ", uuid:"+device.getUuids(); Log.d("test", str); } }); } }); }
ボタンを押すと受信を開始して、ログに出力します。
2.受信コード2
上記の受信コードでは、BluetoothAdapterのstartLeScanにdeprecateの横線が入ります。別の方法としてBluetoothLeScannerを使います。
BluetoothManager bluetoothManager = (BluetoothManager)getSystemService(BLUETOOTH_SERVICE); BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter(); BluetoothLeScanner bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner(); bluetoothLeScanner.startScan(new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); BluetoothDevice bluetoothDevice = result.getDevice(); Log.d("test", "onScanResult Name:"+bluetoothDevice.getName()+", Address:"+bluetoothDevice.getAddress()+", uuids:"+bluetoothDevice.getUuids()); Log.d("test", "onScanResult str:"+result.getScanRecord().toString()); } });
これで受信が出来ます。
3.データ部について
1のコードでは、byte[] scanRecordにバイト配列で受信データが入ります。あとは独自でパースして使います。
2のコードでは、ScanResult resultの中にデータが入るのですが、パース後のデータになります。
ScanResult.getScanRecord().toString()するとこんな感じで入ってます。
mAdvertiseFlags = -1, mServiceUuids = null, mManufacturerSpecificData = { 6 = [x, x, x, x, x...] }, mServiceData = {}, mTxPowerLevel = -2147483648, mDeviceName = null
mManufacturerSpecificDataがデータの部分なのですが、生データではなくパース後のデータになっており、ヘッダの一部が除かれています。
1のbyte[] scanRecordで下記のデータであれば、
1E FF 06 00 01 09 20 02 08 CE 21 AA 89 DC...
2のmManufacturerSpecificDataには、
{6=[1, 9, 32, 2, 8, -50, 33, -86, -119, -36,...
のようになります。(「6」は3バイト目)
「1E FF」の先頭部分を使うことはほぼないと思いますが。
あと、mManufacturerSpecificDataのデータはSparseArray<byte[]>になっています。
中身を表示例。
SparseArray<byte[]> sparseArray = result.getScanRecord().getManufacturerSpecificData(); for (int ii=0; ii<sparseArray.size(); ii++) { int key = sparseArray.keyAt(ii); byte[] buff = sparseArray.get(key); Log.d("test", "onScanResult key:"+key); StringBuilder sb = new StringBuilder(); for (byte b : buff) sb.append(String.format("%02X ", b)); Log.d("test", "onLeScan scanRecord:"+sb.toString()); }