In diesem Beitrag möchte ich dir zeigen wie du eine Android App für den Aufbau einer Bluetooth Low Energy Verbindung mit der IDE Android Studio programmierst.
leeres Android Projekt
Zunächst erstellen wir ein neues leeres Projekt mit einer Activity. Dazu navigieren wir im Hauptmenü über „File“ > „New“ > „New Project…“.
Aus diesem Fenster wählen wir dann „Empty Activity“ und bestätigen die Auswahl mit der Schaltfläche „Next“.
Im nächsten Fenster konfigurieren wir unsere App,
- wir vergeben also den Name der App „BLE_TestApp“,
- geben das Java Package für unseren späteren Quellcode an „de.myapp.bletestapp“,
- den Speicherort „C:\Git\MyBLETestApp“, sowie
- die Programmiersprache „Java“ und
- das min. API Level „28 > Android 9“
Diese Einstellungen bestätigen wir mit der Schaltfläche „Finish“.
Hier nun das leere, jedoch wie oben konfigurierte Android Studio Projekt bequem zum Download:
setzen der benötigten Berechtigungen zum Zugriff auf Bluetooth
Damit wir auf den BluetoothAdapter zugreifen können müssen wir zunächst in der Datei „Manifest.xml“ die Berechtigungen setzen.
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
Ab der Android Version 6.0 benötigen wir noch zusätzlich den Zugriff auf den Standort dazu wird die nachfolgende Berechtigung benötigt.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
Und wir müssen das Bluetooth LE Feature aktivieren:
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
Programmieren
Im ersten Schritt wollen wir zunächst nach einem (oder mehrere) Bluetooth LE Geräte suchen und uns den Namen sowie die MAC-Adresse anzeigen lassen.
Der zweite Schritt soll den Aufbau einer Verbindung zu einem BLE Gerät dienen und der dritte und letzte Schritt wir den Datenaustausch mit einem sollchen Bluetooth Low Energy Gerät beinhalten.
erster Schritt – erzeugen einer Liste und Schaltfläche zum Suchen von BLE Geräten
Das Design für die Android App wird in einer XML Struktur „gezeichnet“ hier können wir jedoch auf einen WYSIWYG Editor zurückgreifen (der aber manchmal so seine kleinen Tücken hat).
Wir öffnen nun die Datei „activity_main.xml“ welche wir im Pfad „app“ > „res“ > „layout“ finden.
Diese Datei öffnen wir nun mit einem doppelklick und es sollte sich der besagte Editor öffnen.
Zunächst entfernen wir das TextView Element „Hello World!“ indem wir dieses markieren und die Taste „Entf“ betätigen.
Als nächstes Platzieren wir unsere Schaltfläche (Button) zum starten der Suche nach BLE Geräte, sowie ein TextView Element für die gefundenen Geräte.
Da wir jedoch ggf. sehr viele solcher Geräte finden können zeichnen wir das TextView Element in einer ScrollView somit können wir dann später bequem in der Liste scrollen und müssen nicht das gesamte Display bewegen.
Berechtigungen prüfen und ggf. nachfordern
In der AndroidManifest.xml habe wir die Berechtigungen definiert welche wir für diese App benötigen. Aus meiner Erfahrung kann ich jedoch berichten das es nicht zwingend funktioniert das diese Berechtigungen gesetzt sind somit prüfen wir beim starten der App ob diese Berechtigungen gesetzt sind.
@Override protected void onCreate(Bundle savedInstanceState) { ... if(!hasRequiredPermissions()){ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH}, PackageManager.PERMISSION_GRANTED); ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_ADMIN}, PackageManager.PERMISSION_GRANTED); ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PackageManager.PERMISSION_GRANTED); } } private boolean hasRequiredPermissions(){ boolean hasBluetoothPermission = hasPermission(Manifest.permission.BLUETOOTH); boolean hasBluetoothAdminPermission = hasPermission(Manifest.permission.BLUETOOTH_ADMIN); boolean hasLocationPermission = hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION); return hasBluetoothPermission && hasBluetoothAdminPermission && hasLocationPermission; } private boolean hasPermission(String permission){ return ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED; }
erstellen einer Verbindung zum BluetoothAdapter
Damit wir BLE Geräte suchen können müssen wir zunächst eine Verbindung zum BluetoothAdapter des Android Gerätes aufbauen.
Diesen BluetoothAdapter „erhalten“ wir vom BluetoothManager welchen wir wiederum vom System bekommen.
private BluetoothManager bluetoothManager; private BluetoothAdapter bluetoothAdapter; private BluetoothLeScanner bluetoothLeScannerLeScanner; @Override protected void onCreate(Bundle savedInstanceState) { ... bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); bluetoothAdapter = bluetoothManager.getAdapter(); bluetoothLeScannerLeScanner = bluetoothAdapter.getBluetoothLeScanner(); if (bluetoothAdapter != null && !bluetoothAdapter.isEnabled()) { Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent, REQUEST_ENABLE_BT); } }
Sollte wider erwartend das Android Gerät nicht über eine Bluetoothschnittstelle verfügen so wird hier eine Exception geworfen.
suchen nach BLE Geräten
Zum starten der Suche nach BLE Geräten haben wir die Schaltfläche „Suchen“ implementiert. Dieser Schaltfläche wollen wir nun als Action die Funktion geben das die Suche gestartet und nach 5 Sekunden automatisch abgebrochen wird. Zusätzlich wird die Schaltfläche während der suche deaktiviert und vor jedem start des Scans die letzten Daten aus dem TextView Element gelöcht (Funktion resetFoundDevices()).
private static final String TAG = "BLE_TESTApp"; private Button searchBtn; private TextView bleDevicesTextView; private Handler handler = new Handler(); private static final long INTERVAL = 5000; private ScanCallback leScanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { BluetoothDevice device = result.getDevice(); String text = String.format("%d - %s, %s\r\n", deviceCounter, device.getName(), device.getAddress()); bleDevicesTextView.setText(bleDevicesTextView.getText().toString().concat(text)); devices.put(deviceCounter, device); deviceCounter++; } }; @Override protected void onCreate(Bundle savedInstanceState) { searchBtn = findViewById(R.id.searchBtn); bleDevicesTextView = findViewById(R.id.bleDevicesTextView); searchBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { resetFoundDevices(); Log.i(TAG, "Suche nach BLE Geräte > beginn"); searchBtn.setEnabled(false); AsyncTask.execute(new Runnable() { @Override public void run() { bluetoothLeScannerLeScanner.startScan(leScanCallback); } }); handler.postDelayed(new Runnable() { @Override public void run() { Log.i(TAG, "Suche nach BLE Geräte > ende"); searchBtn.setEnabled(true); AsyncTask.execute(new Runnable() { @Override public void run() { bluetoothLeScannerLeScanner.stopScan(leScanCallback); } }); } }, INTERVAL); } }); }
Zwischenstand – suche nach BLE Geräten
Wenn du den letzten Abschnitt übernommen hast, dann kannst du nun nach Bluetooth Low Energy Geräten suchen.
Der Timeout für die Suche nach BLE Geräte ist in dem Quellcode auf 5 Sekunden eingestellt, sollte das Gerät welches du suchst nicht dabei sein so empfehle ich einen höheren Wert zu nutzen.
Hier nun das Android Studio Projekt mit der Funktion „nach BLE Geräten suchen“ zum bequemen Download:
Ausblick
Im ersten Teil haben wir nun nach Bluetooth Low Energy Geräte gesucht und den Namen sowie die MAC Adresse angezeigt. Des Weiteren haben wir eine Map mit den Index sowie dem Gerät erzeugt und können nun im zweiten Teil eine Verbindung zu einem BLE Gerät aufbauen.
Für dieses Tutorial verwende ich den BLE-Nano welchen ich bereits im Beitrag XYZ vorgestellt habe. Generell funktioniert dieses jedoch mit (fast) jedem Bluetooth LE Gerät welches eine Verbindung zulässt.
Hallo,
sehr schöne Anleitung. Vor allem gefällt mir, dass der Code gleich dabei ist. Aber wo finde ich Teil 2 oder Teil 3?
Viele Grüße
Hi Thomas,
vielen Dank für dein Kommentar, die weiteren Teile sind im Aufbau d.h. diese folgen in den nächsten Wochen.
Gruß,
Stefan Draeger
Hallo,
Zunächst einmal vielen Dank für Ihre Hilfe. Ich konnte Ihr Programm herunterladen, aber leider hat es nicht funktioniert, die verfügbaren BLE-Geräte anzuzeigen. Können Sie mir helfen?
Ich danke Ihnen im Voraus.
Hallo,
was ist denn der genaue Fehler? Gibt es eine Exception im Log?
Gerne auch per E-Mail an info@draeger-it.blog.
Gruß,
Stefan Draeger
Hallo,
Ich habe die Lösung für mein Problem gefunden. Ihre Anwendung funktioniert zwar gut, erfordert jedoch keine Autorisierung zur Aktivierung von GPS. In Android-Version 6.0 und höher muss GPS aktiviert werden, damit die scanCallback-Funktion ordnungsgemäß funktioniert. Andernfalls werden die Funktionen onScanResult (), onScanFailed () oder onScanBatchResult () nicht aufgerufen.
Nochmals vielen Dank für Ihre Hilfe.
Marouane
Hallo Stefan Draeger,
Vielen Dank für die Anleitung. die hat mir super weiter geholfen auch wenn sie nicht vollständig ist.
Wo rauf möchte ich hier hinaus? Ich habe versucht eine App zu bauen mit der ich mit einem HM-10 BLE Controller zu kommunizieren, dabei hatte ich immer das Problem das ich keine Bluetooth Geräte gefunden hatte. Aber mit App wie dem BLE Scanner hat es funktioniert.
Ich hatte mich zunächst an dem Beispiel Code Bluetooth LE GATT von Android orientiert. Aber das hat mich nicht weiter gebracht. Ich hatte große Hoffnung, das mir dieses Beispiel hilft die Sachen besser zu verstehen. Das hat es auch, auch wenn es nicht funktioniert hat.
Letzt endlich haben mich die beiden folgenden Stack Overflow Antworten auf den richtigen Weg gebracht:
https://stackoverflow.com/questions/53711220/android-ble-discovery-issue
https://stackoverflow.com/questions/42250866/android-cant-find-any-ble-devices/42267678#42267678
Mir fehlte die ganze Zeit die Abfrage, ob meine App auch den Standortdienst verwenden darf. Als dieser akzeptiert war, funktionierte es einwandfrei.
Deswegen möchte ich meine Erkenntnisse teilen:
AndriodManifest.xml:
https://pastebin.com/T7Q52w2d
Hi Ramon,
danke für dein Kommentar, ich habe den Code einmal auf Pastebin.com hochgeladen denn das würde sonst den Rahmen eines Kommentars sprengen.
Gruß,
Stefan
Die XML hat er verworfen 🙁
Deswegen liste ich nur die User-Permissions und -Features auf:
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“
uses-permission-sdk-23 android:name=“android.permission.ACCESS_FINE_LOCATION“
uses-permission-sdk-23 android:name=“android.permission.ACCESS_COARSE_LOCATION“
uses-feature android:name=“android.hardware.bluetooth_le“ android:required=“true“
uses-feature android:name=“android.hardware.location.gps“
Hallo,
bei mir das gleiche, die originale App von Herrn Draeger findet nichts, die alternative Variante von Ramon Schönke klappt.
Insgesamt danke für diesen aufschlussreichen Input!
Guten Abend Herr Draeger,
vielen Dank für den lehrreichen Artikel! Sie haben mir und sicher auch einigen anderen enorm weitergeholfen.
Wir warten mit Spannung auf die Fortsetzung dieses Tutorials!