Das ist der Werbetreibende (Hinweis data
als AdvertiseData
Typ bestanden)Android: Bluetooth Low Energy Scanner empfängt Null-Daten
private void advertise() {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothLeAdvertiser advertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
AdvertiseSettings settings = new AdvertiseSettings.Builder()
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED)
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM)
.setConnectable(false)
.build();
ParcelUuid pUuid = new ParcelUuid(UUID.fromString("cf2c82b6-6a06-403d-b7e6-13934e602664"));
AdvertiseData data = new AdvertiseData.Builder()
//.setIncludeDeviceName(true)
.addServiceUuid(pUuid)
.addServiceData(pUuid, "123456".getBytes(Charset.forName("UTF-8")))
.build();
AdvertiseCallback advertiseCallback = new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
Log.i(tag, "Advertising onStartSuccess");
super.onStartSuccess(settingsInEffect);
}
@Override
public void onStartFailure(int errorCode) {
Log.e(tag, "Advertising onStartFailure: " + errorCode);
super.onStartFailure(errorCode);
}
};
advertiser.startAdvertising(settings, data, advertiseCallback);
}
Es beginnt erfolgreich.
Dies ist der Scanner
private void discover() {
ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_BALANCED)
.build();
mBluetoothLeScanner.startScan(null, settings, mScanCallback);
}
private ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
Log.i(tag, "Discovery onScanResult");
if (result == null) {
Log.i(tag, "no result");
return;
}
ScanRecord scanRecord = result.getScanRecord();
List<ParcelUuid> list = scanRecord != null ? scanRecord.getServiceUuids() : null;
if (list != null) {
Log.i(tag, scanRecord.toString());
for (ParcelUuid uuid : list) {
byte[] data = scanRecord.getServiceData(uuid);
}
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
Log.i(tag, "Discovery onBatchScanResults");
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
Log.e(tag, "Discovery onScanFailed: " + errorCode);
}
};
In der Callback onScarnResult
ich die Scan-Datensatz toString()
protokollieren, die diesen Ausgang
ScanRecord [mAdvertiseFlags=2,
mServiceUuids=[cf2c82b6-6a06-403d-b7e6-13934e602664],
mManufacturerSpecificData={},
mServiceData={000082b6-0000-1000-8000-00805f9b34fb=[49, 50, 51, 52, 53, 54]},
mTxPowerLevel=-2147483648, mDeviceName=null]
die UUID Matches erzeugt, leider das Ergebnis
byte[] data = scanRecord.getServiceData(uuid)
ist null
. bemerkte ich, dass die toString
Ausgabe der ASCII-Codes der beworbenen Datenzeichen „123456“ hatte, die 49,50,51,52,53,54
mServiceData={000082b6-0000-1000-8000-00805f9b34fb=[49, 50, 51, 52, 53, 54]}
sind Ich möchte das Recht beworben, Daten empfangen , mache ich etwas falsch?
EDIT: das Manifest hat Berechtigungen für Bluetooth, BT-Admin und Standort. Der dritte startet eine Anfrage zur Laufzeit in Android 6
EDIT: durch Drucken des gesamten Scanrecord Sie diese Ausgabe
Scanrecord bekommen [mAdvertiseFlags = -1, mServiceUuids = [cf2c82b6-6a06-403d-b7e6 -13934e602664], mManufacturerSpecificData = {}, { mServiceData = 000082b6-0000-1000-8000-00805f9b34fb = [49, 50, 51, 52, 53, 54]}, mTxPowerLevel = -2147483648, mDeviceName = null]
Grundsätzlich können Sie die Uuid d nicht verwenden Dies wird vom Werbetreibenden unterstützt, der sich im Array mServiceUuids befindet, da der mit mServiceData verknüpfte Schlüssel ein anderer ist. Also änderte ich den Code auf diese Weise die Datenzuordnung zu navigieren und den Wert bekommen (bitte sehen Sie die beiden if-Blöcke)
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
for (ScanResult result : results) {
ScanRecord scanRecord = result.getScanRecord();
List<ParcelUuid> uuids = scanRecord.getServiceUuids();
Map<ParcelUuid, byte[]> map = scanRecord.getServiceData();
if (uuids != null) {
for (ParcelUuid uuid : uuids) {
byte[] data = scanRecord.getServiceData(uuid);
Log.i(tag, uuid + " -> " + data + " contain " + map.containsKey(uuid));
}
}
if (map != null) {
Set<Map.Entry<ParcelUuid, byte[]>> set = map.entrySet();
Iterator<Map.Entry<ParcelUuid, byte[]>> iterator = set.iterator();
while (iterator.hasNext()) {
Log.i(tag, new String(iterator.next().getValue()));
}
}
}
}
In der Tat, die Linie
map.containsKey(uuid)
false zurück, weil Die Uuid des Werbetreibenden wird von der Datenzuordnung nicht verwendet.
Ich musste die Karte navigieren, um den Wert zu finden (2. Wenn-Block), aber ich habe keine Mittel zu wissen, ob das der Wert ist, der mich interessiert. So oder so kann ich den Wert nicht erhalten wenn das System einen anderen Schlüssel eingibt, den ich nicht kenne, während ich den Code des Scanners in der Empfänger-App abspiele.
Wie kann ich mit diesem Problem auf dem Empfänger umgehen? Ich würde gerne das Datenfeld verwenden, aber der String-Schlüssel, um sie zu bekommen, ist nicht a priori bekannt und wird vom System entschieden.