6

Come reagire alla pubblicità diretta (ADV_DIRECT_IND == 0001) in Android?Reagire alla pubblicità diretta BLE (ADV_DIRECT_IND) in Android

C'è un gadget BLE che invia pubblicità diretta a un telefono Android (utilizzando l'indirizzo MAC del telefono fisso per il momento) e nella mia app per Android mi piacerebbe reagire e avviare una connessione al gadget e leggere il org.bluetooth.characteristic.location_and_speed valore dal gadget:

screenshot

prega di avvisare se è possibile con i mezzi di Android 5 API.

risposta

3

La pubblicità diretta funziona - almeno con HTC M8 telefono e Android 5.0 (API di livello 21 o superiore).

La soluzione è stata quella di aggiungere gli indirizzi dei dispositivi allo ScanFilter.

Se si lasciano i filtri vuoti, le richiamate di scansione non verranno richiamate.

Ecco il mio codice di lavoro:

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>(); 

In primo luogo il metodo di inizializzazione 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); 
} 

E poi i callback di scansione:

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 
    } 
}; 

Infine, il codice per avviare la scansione :

mScanner.startScan(mFilters, mSettings, mDirectedScanCallback); 

Una domanda è ancora aperta anche se:

Non so come individuare il tipo di scansione sul lato Android - cioè se la scansione è stato diretto oppure no.

1

Per rispondere parzialmente aperta la questione:
Ho notato che il ScanRecord.getBytes() è vuota - all '\ 0' - per una scansione diretta (ADV_DIRECT_IND) - ma conterrebbe i dati pubblicitari altrimenti (ADV_IND).