Android App Programmierung: Bluetooth Low Energy Connection (BLE) – (Teil 1 suchen nach BLE Geräte)

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…“.

Android Studio - wählen eines Projektes
Android Studio – wählen eines Projektes

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“.

Android Studio : konfigurieren des neuen Projektes
Android Studio : konfigurieren des neuen Projektes

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.

Speicherort der Datei "AndroidManifest.xml"
Speicherort der Datei „AndroidManifest.xml“
<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.

Pfad zur Layoutdatei "activity_main.xml"
Pfad zur Layoutdatei „activity_main.xml“

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.

5 Gedanken zu „Android App Programmierung: Bluetooth Low Energy Connection (BLE) – (Teil 1 suchen nach BLE Geräte)

  • 30. Juni 2020 um 12:59
    Permalink

    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

    Antwort
    • 30. Juni 2020 um 13:15
      Permalink

      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

      Antwort
  • 3. Juli 2020 um 13:22
    Permalink

    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

    Antwort
    • 3. Juli 2020 um 21:00
      Permalink

      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

      Antwort
  • 3. Juli 2020 um 13:27
    Permalink

    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“

    Antwort

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.