Direct advertising does work - at least with HTC M8 phone and Android 5.0 (API level 21 and higher).
The solution has been to add the device addresses to the ScanFilter.
If you leave the filters empty, the scanning callbacks won't be called.
Here my working code:
public static final String TAG = "My_BLE_app";
public static final String DEVICE_1 = "D4:BE:84:72:5B:8E";
public static final String DEVICE_2 = "C4:39:07:19:60:E2";
private Context mContext;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothLeScanner mScanner;
private ScanSettings mSettings;
private List<ScanFilter> mFilters = new ArrayList<ScanFilter>();
First the method for initializing BLE:
public boolean init() {
BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
if (mBluetoothAdapter == null)
return false;
mScanner = mBluetoothAdapter.getBluetoothLeScanner();
mSettings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
mFilters.add(new ScanFilter.Builder().setDeviceAddress(DEVICE_1).build());
mFilters.add(new ScanFilter.Builder().setDeviceAddress(DEVICE_2).build());
return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
}
And then the scanning callbacks:
private ScanCallback mDirectedScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
processResult(result);
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
for (ScanResult result: results) {
processResult(result);
}
}
private void processResult(ScanResult result) {
BluetoothDevice device = result.getDevice();
if (device == null)
return;
String address = device.getAddress();
if (!BluetoothAdapter.checkBluetoothAddress(address))
return;
int rssi = result.getRssi();
Log.d(TAG, "address=" + address + ", rssi=" + rssi);
// TODO connect to the device in under 1 second
}
};
Finally the code to start the scanning:
mScanner.startScan(mFilters, mSettings, mDirectedScanCallback);
One question is still open though:
I don't know how to detect the type of scan at the Android side - that is if the scan was directed or not.