Android Bluetooth LE - Frage zur Funktionalität

xXSkyWalkerXx1

Mitglied
Hallo 🙂

Also ich bin gerade dabei eine App zu entwickeln, stoße aber auf ein Paar wichtige Fragen:
  1. Kann ich mit meinem Handy über BT-LE (Low Energy) mit einem anderen Handy kommunizieren - also Daten austauschen?
  2. Kann man mit BT-LE sowohl Client als auch Host zur gleichen Zeit sein?
    Also, dass ich gleichzeitig Daten von anderen Handys abrufen und meine Daten an andere weitergeben kann.
Gerade Frage 1 ist etwas tricky, da ich auf Google nur darüber lesen kann, dass man über BT-LE sich mit "smarten" Geräten verbinden kann,
meist wird sich auf SmartWatches und ähnliches bezogen.

Im Anhang befindet sich ein Anwendungsfalldiagram. Jeder Benutzer soll vom Anderen Daten abrufen.
Dadurch, dass jemand anderes zu dir eine Verbindung herstellt und man das Gleiche zu einem anderen Benutzer tut, agiert man
ja so als Client & Host zur gleichen Zeit.

Danke im Vorraus.
Grüße, xXSkyWalkerXx1! 🙂
 

Anhänge

  • Anwendungsfall.png
    Anwendungsfall.png
    6,6 KB · Aufrufe: 2
Kann ich mit meinem Handy über BT-LE (Low Energy) mit einem anderen Handy kommunizieren - also Daten austauschen?
Prinzipiell ja, ein Android-Smartphone kann auch als Server auftreten.

Ich wollte diese Möglichkeit mal zum Testen verwenden, habe es dann aber nicht mehr verfolgt.

Kann man mit BT-LE sowohl Client als auch Host zur gleichen Zeit sein?
Das hängt IMHE vom BLE-Chip ab, prinzipiell ja.
 
Irgendwie wird nicht gescant / kein Callback aufgerufen... 🤔

[CODE title="Logcat Output bei Ausführung"]2021-09-02 14:58:28.997 21444-21444/com.skyapp.app I/BluetoothManager: openGattServer
2021-09-02 14:58:28.998 21444-21444/com.skyapp.app D/BluetoothGattServer: registerCallback()
2021-09-02 14:58:28.998 21444-21444/com.skyapp.app D/BluetoothGattServer: registerCallback() - UUID=<removed>
2021-09-02 14:58:29.002 21444-21488/com.skyapp.app D/BluetoothGattServer: onServerRegistered() - status=0 serverIf=6
2021-09-02 14:58:29.002 21444-21444/com.skyapp.app D/BluetoothGattServer: addService() - service: <removed>
2021-09-02 14:58:29.003 21444-21444/com.skyapp.app I/BluetoothAdapter: getBluetoothLeScanner
2021-09-02 14:58:29.004 21444-21444/com.skyapp.app D/BluetoothAdapter: isLeEnabled(): ON
2021-09-02 14:58:29.004 21444-21488/com.skyapp.app D/BluetoothGattServer: onServiceAdded() - handle=54 uuid=<removed> status=0
2021-09-02 14:58:29.006 21444-21488/com.skyapp.app D/BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=8 mScannerId=0[/CODE]

[CODE lang="java" title="Bluetooth-LE-Scanner Part"]// Define our Filter for the Bluetooth LE scan
List<ScanFilter> filters = new ArrayList<>();
ScanFilter.Builder scanFilterBuilder = new ScanFilter.Builder();
scanFilterBuilder.setServiceUuid(ParcelUuid.fromString(APP_UUID));
filters.add(scanFilterBuilder.build());
// Define our ScanSettings for the Bluetooth LE scan
ScanSettings.Builder scanSettingsBuild = new ScanSettings.Builder();
scanSettingsBuild.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
scanSettingsBuild.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER);
scanSettingsBuild.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE);
ScanSettings scanSettings = scanSettingsBuild.build();

// Define our callback for our Bluetooth LE scans
scanCallback = new BtLeScanCallback(this, true,customAdapter);
// Get our Bluetooth LE scanner
btLeScanner = btAdapter.getBluetoothLeScanner();
// Start filtered (by UUID) scan
btLeScanner.startScan(filters, scanSettings, scanCallback);[/CODE]

App läuft... BT aktiviert... BT am Laptop (LE fähig) schon die ganze Zeit aktiviert (&findbar)... aber kein Aufruf eines Callbacks.
Also entweder findet es nichts oder warum auch immer wird kein Callback aufgerufen.

Hat jemand von euch etwas mehr Erfahrung mit Bluetooth LE und weiß worin der Fehler liegt/liegen könnte? 😀
 
Ich habe nach diesem Buch gearbeitet:


Zuerst muss gesichert sein, dass der Partner (Chip) Advertising-Signale sendet.

Um das zu Prüfen gibt es Apps, ich glaube Nordic ist da ein passendes Stichwort.

Dann muss sich der Client verbinden und das Profil abfragen, also Services und Characteristiken.

Auf den lesenden Characteristiken kann dann ein Listener registriert werden.

Ich habe jetzt nicht alles im Kopf, bin nicht mehr der Jüngste.

Schreibende Characteristiken müssen enabled werden, glaube ich.
 
Hoffe das Hilft weiter.
Habe die App Mal heruntergeladen, um mit seinem Code das einfach Mal zu probieren.
Aber bei seinem Code passiert bei mir nichts, wie bei meiner App.

Ich habe eine Bluetooth-Maus und mein Laptop - eins von beiden hätte es definitiv finden müssen.

Und wenn ich das ganze mit 'ner App aus dem Play-Store versuche, dann findet es einiges.
(App-Name vom Play-Store: "Bluetooth Le Scanner")
 
Sheesh!! @Jw456
Hab gerade nochmal meine App getestet und es funzt - es lag entweder an fehlender Berechtigung und/oder, da ich den Scan mit einer UUID filtern lassen habe, hat es keine anderen Geräte gefunden. 🙂)
 
Ok
Wenn du dir mal deine Scanner app vom play store anschaust. Da wirst du als User in der app nach der Berechtigung gefragt. Und wenn du dir es in den Einstellungen anschaust ist sie dort auch erteilt.

Das wird aber auch in dem link denn ich gegeben habe gesagt das diese Berechtigung seit android 6 erteilt werden muss.
 
Ich komme einfach nicht weiter... 😀
Bereits zig How-To's durchgeschaut und so ziemlich überall wie in meinem Code.
Vom ScanCallback (durch connectGatt()) sollte es zu BluetoothGattCallback überführen. Allerdings gelangt es zu BluetoothGattCallback erst, nachdem connectGatt() insg. ~20 Mal aufgerufen wird, dann scheinen es zu viele Verbindungen zu sein und sie werden autom. geschlossen.
Ich verstehe nur außerdem nicht warum BluetoothGattCallback (onConnectionStateChange()) erst nach den 20 Malen aufgerufen wird. :?

[CODE lang="java" title="Simple Pseudo Code"]btLeScanner.startScan(scanCallback);

public class BtLeScanCallback extends ScanCallback {
@Override
public void onScanResult(int callbackType, ScanResult result) {
BluetoothDevice device = result.getDevice();
BluetoothGatt bluetoothGatt = device.connectGatt(context, autoConnect, callback, BluetoothDevice.TRANSPORT_LE);
}

public class BtGattCallback extends BluetoothGattCallback {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.i(TAG, "ConnectionState: " + newState);

switch (newState){
case STATE_CONNECTED:
Log.i(TAG, "State connected.");
gatt.discoverServices();
break;
case STATE_DISCONNECTED:
Log.i(TAG, "State disconnected.");
gatt.close();
break;
}
}[/CODE]
 
So sieht es bis zu den 20 Malen aus, wo connectGatt() aufgerufen wird, und ab "ConnectionState" (also die rote Schrift) werden erst die Callback Methoden aufgerufen, doch da ist der Status immer DISCONNECTED, da die Geräte autom. disconnected werden, da zu viele Geräte registriert wurden, obwohl sie im GattCallback entfernt werden.
Screenshot - 05_10.png
 
Ich glaube, dass Problem besteht darin, dass scheinbar connectGatt() keine Callback-Methode triggert.
Schließlich wird sie erst getriggert, wenn zu viele Connections stattfanden und deshalb alle autom. getrennt werden.

In connectGatt() wird allerdings connect() aufgerufen, welche doch aber eigentlich die Callback-Methode triggern sollte.
 
Hallo so wie es ausschaut versuchst du ja zu allen Geräten die gefunden werden eine Verbindung aufzubauen.
Eigentlich baut man ja nur eine Verbindung mit den Gerät auf mit dem man sich wirklich verbinden will.

Denn scann scheinst du ja ständig zu widerholen. Wenn viele Geräte in der Nähe sind werden viele Verbindung aufgebaut.

Ich würde die Geräte vom scann in eine Liste packen und mir das richtige rausgesuchen und dann verbinden.
 
Ich dachte ich kann mit bis zu 6 Geräten gleichzeitig verbunden sein?
Meinem Code nach wird eine Verbindung zum Gerät aufgebaut, sobald es gefunden wurde. Darauf werde ich im Callback benachrichtigt. Sobald dies geschehen ist, wird 'discoverServices()' aufgerufen und in dessen Callback wird nach Ablauf die Verbindung geschlossen (disconnect & close).
Daher dürfte es sowieso nie mehr als 6 gleichzeitige Verbindungen besitzen.

Aber ja, an sich könnte eine geordnete Suche das Problem lösen, da ich ja gerade mich quasi wild durch die Gegen verbinde. ^^

[EDIT] Nope, hat mein Problem nicht gefixt. Habe es nun so probiert, dass es nach dem 1. Gerät die Suche beendet. Aber es wurde immer noch kein Callback wurde aufgerufen. 😵
 
Zuletzt bearbeitet:
Ich dachte ich kann mit bis zu 6 Geräten gleichzeitig verbunden sein?
Meinem Code nach wird eine Verbindung zum Gerät aufgebaut, sobald es gefunden wurde. Darauf werde ich im Callback benachrichtigt. Sobald dies geschehen ist, wird 'discoverServices()' aufgerufen und in dessen Callback wird nach Ablauf die Verbindung geschlossen (disconnect & close).
Daher dürfte es sowieso nie mehr als 6 gleichzeitige Verbindungen besitzen.

Aber ja, an sich könnte eine geordnete Suche das Problem lösen, da ich ja gerade mich quasi wild durch die Gegen verbinde. ^^
Mir scheint, Du siehst einige Dinge falsch.

Meinem Code nach wird eine Verbindung zum Gerät aufgebaut, sobald es gefunden wurde. Darauf werde ich im Callback benachrichtigt. Sobald dies geschehen ist, wird 'discoverServices()' aufgerufen und in dessen Callback wird nach Ablauf die Verbindung geschlossen (disconnect & close).
Daher dürfte es sowieso nie mehr als 6 gleichzeitige Verbindungen besitzen.
Wenn es möglich ist, sich mit 6 Devices zu verbinden, muss es auch möglich sein, auf 6 Devices discoverServices aufzurufen.

discoverServices ist notwendig, damit man überhaupt mit den Devices arbeiten kann.

Ich hatte 2018 mal eine Minischulung, in der gesagt wurde, dass sich ein Central mit bis zu 8 Peripherals verbinden kann.

Ich weiss aber nicht mehr, ob dies für Bluetooth mit oder ohne LE (Low Energy) galt.
 
Vom ScanCallback (durch connectGatt()) sollte es zu BluetoothGattCallback überführen. Allerdings gelangt es zu BluetoothGattCallback erst, nachdem connectGatt() insg. ~20 Mal aufgerufen wird, dann scheinen es zu viele Verbindungen zu sein und sie werden autom. geschlossen.
Ich verstehe nur außerdem nicht warum BluetoothGattCallback (onConnectionStateChange()) erst nach den 20 Malen aufgerufen wird. :?
Vom ScanCallback (durch connectGatt()) sollte es zu BluetoothGattCallback überführen.
Seltsame Formulierung, aber ok, erst scannen, dann verbinden.
Allerdings gelangt es zu BluetoothGattCallback erst, nachdem connectGatt() insg. ~20 Mal aufgerufen wird, dann scheinen es zu viele Verbindungen zu sein und sie werden autom. geschlossen.
Du solltest connectGatt nur einmal aufrufen und dann erst mal auf das Ergebnis warten.
Ich verstehe nur außerdem nicht warum BluetoothGattCallback (onConnectionStateChange()) erst nach den 20 Malen aufgerufen wird. :?
Das Device muss erst mal antworten.
BLE arbeitet mit Zeitfenstern, die Antwort (der Callback) erscheint also verzögert und asynchron.
 
Seltsame Formulierung, aber ok, erst scannen, dann verbinden.

Du solltest connectGatt nur einmal aufrufen und dann erst mal auf das Ergebnis warten.

Das Device muss erst mal antworten.
BLE arbeitet mit Zeitfenstern, die Antwort (der Callback) erscheint also verzögert und asynchron.
Wie bereits erwähnt, wird aber nicht Mal ein Callback ausgeführt, selbst wenn ich nach dem 1. Gerät den Scan stoppe.
Da geht es weiterhin nur bis onClientRegistered, aber nicht bis onConnectionStateChange.
 
Mache das conneckt nicht in der Scann Callback Methode.


Ich hoffe auch das du das verbinden nicht im Mainthread machst.
Netzwerk Zugriffe bei Android dürfen nicht im Mainthread sein. Da gehört Bluetooth für mich mit dazu.
 
Java:
BluetoothGatt bluetoothGatt = device.connectGatt(context, autoConnect, callback, BluetoothDevice.TRANSPORT_LE

Benutze mal nicht den Transport Parameter.
 
@Jw456
Denke schon, dass das connectGatt() in der Callback-Methode so passt - kann mir nicht vorstellen, dass das Verbinden außerhalb erfolgen soll.
Hab's aber Mal so umgesetzt, genau so wie den Parameter BluetoothDevice.TRANSPORT_LE zu entfernen: funktioniert trotzdem nicht.
Nachdem die Verbindung zum 1. Gerät aufgebaut wird, vergehen ~30s bis die Callback-Methode aufgerufen wird, wobei da der Verbindungsstatus bei DISCONNECTED liegt. Wahrscheinlich, weil auch hier Android alle Verbindungen kappt, wegen dem TimeOut von 30s oder so...

Ich werd' nochmal schauen wie genau der Aufbau stattfindet - vllt habe ich irgendwas übersehen.
Trotzdem, danke euch! 🙂
 
Denke ich nicht woher weißt du ob das erste Gerät auch eines ist was genau deine uuid entspricht. Genau das Gerät ist mit dem du dich verbinden willst.

Speichere deine gefunden Geräte in eine ArrayList. Und suche dir nach dem Scannen das richtige aus der Liste raus und verbinde dich damit.
Lasse dir die Liste anzeigen und wähle davon eines aus.

Frage bist du im UI oder in einem Thread? Welche Fehlermeldung kommt denn?
 
Ich starte den Scan von einem Fragment aus. Und Fehlermeldungen bekomme ich nicht.
So sieht die Logcat Ausgabe nach jeder Connection aus.
[CODE lang="java" title="Logcat Output"]2021-10-07 12:02:09.238 20172-20172/com.skyapp.app D/BluetoothGatt: registerApp()
2021-10-07 12:02:09.240 20172-20172/com.skyapp.app D/BluetoothGatt: registerApp() - UUID=30cc2b1a-3450-4572-9f04-09789e5cfcdb
2021-10-07 12:02:09.255 20172-20188/com.skyapp.app D/BluetoothGatt: onClientRegistered() - status=0 clientIf=9
2021-10-07 12:02:39.265 20172-20188/com.skyapp.app D/BluetoothGattServer: onServerConnectionState() - status=0 serverIf=8 device=<MAC>
2021-10-07 12:02:39.266 20172-20200/com.skyapp.app D/BluetoothGatt: onClientConnectionState() - status=133 clientIf=9 device=<MAC>
2021-10-07 12:02:39.266 20172-20200/com.skyapp.app E/BtGattCallback: ConnectionStateChanged!
2021-10-07 12:02:39.266 20172-20200/com.skyapp.app I/BtGattCallback: State disconnected.
2021-10-07 12:02:39.266 20172-20200/com.skyapp.app D/BluetoothGatt: close()
2021-10-07 12:02:39.266 20172-20200/com.skyapp.app D/BluetoothGatt: unregisterApp() - mClientIf=9[/CODE]

Ich habe es jetzt Mal so geändert, dass es die Geräte in einer Liste speichert und nur dann verbindet, wenn das Gerät noch nicht in der Liste ist (Liste wird noch nicht period. gereinigt). Dabei stoppt es zuerst den Scan, verbindet dann und sobald die Callback-Methode (onConnectionStateChange) aufgerufen wird, wird der Scan wieder gestartet. So verbindet es sich mit jedem Gerät, nix ist direkt zeitbasierend, da der Scan erst nach jeder Verbindung (egal ob connected/disconnected, etc.) wieder gestartet wird.
Hierbei passiert nach connectGatt() allerdings ~20s lang nichts, erst nach der verstrichenen Zeit wird der Callback aufgerufen.

Kann es sein, dass ich mich mit dem Gerät einfach nicht verbinden kann?
Probiere aktuell mich über BLE mit meinem Laptop zu verbinden (lediglich aus Testzwecken).


[EDIT]
Denke ich nicht woher weißt du ob das erste Gerät auch eines ist was genau deine uuid entspricht.
Aktuell scanne ich ohne Filter.
Final ist gedacht mit Filter zu scannen, um nur mit Geräten zu verbinden, die App-Nutzer (meiner App) sind, was, wenn ich mich nicht irre, mit einer UUID als Filter im Scan funktionieren sollte.
 
Wenn das Problem ist, dass sich Deine App mit mehreren Geräten verbindet,
dann entferne alle Geräte bis auf eines aus der Nähe Deines Smartphones und versuche Dich mit diesem einen Gerät zu verbinden.

Wenn das klappt, dann mit weiteren Geräten verbinden.
 

Zurück
Oben