So erkennen Sie Bluetooth-Geräte in der Nähe mit .NET und Xamarin.Android

So erkennen Sie Bluetooth-Geräte in der Nähe mit .NET und Xamarin.Android

Ich arbeite gerade an einer Xamarin.Android-App – für diese App muss ich erkennen, welche Bluetooth-Geräte für mein Android-Telefon verfügbar sind (damit der Benutzer auswählen kann, mit welchem ​​er gekoppelt werden soll).

Für moderne Versionen von Android ist es nicht so einfach, nur einen BroadcastReceiver zu verwenden (obwohl das Teil der Lösung ist). In diesem Beitrag schreibe ich über die Schritte, die erforderlich sind, um die Bluetooth-Hardware auf Ihrem Android-Telefon erfolgreich mit .NET zu verwenden.

Beachten Sie Folgendes:Ich kann die Erkennung von Bluetooth-Geräten testen, indem ich meinen Code direkt auf einem Android-Gerät bereitstelle, aber ich kann den Android-Emulator nicht verwenden, da er keine Bluetooth-Unterstützung bietet.

Wie üblich habe ich meinen Code auf GitHub hochgeladen (Sie können ihn hier herunterladen).

AndroidManifest.xml mit Bluetooth- und Standortberechtigungen aktualisieren

Zuerst musste ich sicherstellen, dass meine Anwendung dem Gerät mitteilte, auf welche Hardwaredienste es zugreifen musste. Zum Erkennen und Interagieren mit Bluetooth-Hardware gibt es vier Dienste, die der Anwendung AndroidManifest.xml hinzugefügt werden müssen:

  • Bluetooth
  • Bluetooth-Administrator
  • Zugriff auf den groben Standort
  • Greifen Sie auf den genauen Standort zu

Wenn die Anwendung zum ersten Mal auf dem Android-Gerät geladen wird, wird der Benutzer aufgefordert, der Anwendung die Erlaubnis zu erteilen, diese Hardwaredienste zu verwenden.

Ich habe meine AndroidManifest.xml-Datei unten eingefügt – Ihre wird etwas anders aussehen, aber ich habe den wichtigen Teil rot hervorgehoben.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          android:versionCode="1"
          android:versionName="1.0"
          package="Bluetooth_Device_Scanner.Bluetooth_Device_Scanner">
  <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="27" />
  <application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
  </application>
  <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" />
</manifest>

Listen Sie die Bluetooth-Geräte auf, mit denen das Android-Gerät bereits gekoppelt wurde

Dieser Teil ist sehr einfach – denken Sie daran, dass der unten stehende Code nur für die Konsole auflistet die Bluetooth-Geräte, die bereits erkannt und mit dem Android-Gerät gekoppelt wurden. Andere Geräte, die noch nicht miteinander gekoppelt wurden, werden nicht aufgelistet (darüber schreibe ich später in diesem Artikel).

if (BluetoothAdapter.DefaultAdapter != null && BluetoothAdapter.DefaultAdapter.IsEnabled)
{
    foreach (var pairedDevice in BluetoothAdapter.DefaultAdapter.BondedDevices)
    {
        Console.WriteLine(
            $"Found device with name: {pairedDevice.Name} and MAC address: {pairedDevice.Address}");
    }
}

Dazu gibt es nicht viel mehr zu sagen – ich kann das so ziemlich überall im C#-Code einfügen und es funktioniert wie erwartet.

Listen Sie neue Bluetooth-Geräte auf, indem Sie eine BluetoothDeviceReceiver-Klasse erstellen, die BroadcastReceiver erweitert

Als nächstes wollte ich die Bluetooth-Geräte auflisten, die nicht mit dem Android-Gerät gekoppelt wurden. Ich kann dies tun, indem ich eine Empfängerklasse erstelle, die die Basisklasse „BroadcastReceiver“ erweitert und die Methode „OnReceive“ überschreibt – ich habe den Code für meine Klasse unten eingefügt.

using System;
using Android.Bluetooth;
using Android.Content;
 
namespace Bluetooth_Device_Scanner
{
    public class BluetoothDeviceReceiver : BroadcastReceiver
    {
        public override void OnReceive(Context context, Intent intent)
        {
            var action = intent.Action;
            
            if (action != BluetoothDevice.ActionFound)
            {
                return;
            }
 
            // Get the device
            var device = (BluetoothDevice)intent.GetParcelableExtra(BluetoothDevice.ExtraDevice);
 
            if (device.BondState != Bond.Bonded)
            {
                Console.WriteLine($"Found device with name: {device.Name} and MAC address: {device.Address}");
            }
        }
    }
}

Diese Empfängerklasse wird bei der Anwendung registriert und angewiesen, sich zu aktivieren, wenn das Android-Gerät bestimmte Ereignisse erkennt – beispielsweise das Finden eines neuen Bluetooth-Geräts. Xamarin.Android tut dies durch etwas, das als „Intent“ bezeichnet wird. Der folgende Code zeigt, wie der Empfänger registriert wird, um auszulösen, wenn ein Bluetooth-Gerät erkannt wird.

// Register for broadcasts when a device is discovered
_receiver = new BluetoothDeviceReceiver();
RegisterReceiver(_receiver, new IntentFilter(BluetoothDevice.ActionFound));

Wenn das Android-Gerät ein neues Bluetooth-Gerät findet und die OnReceive-Methode aufruft, prüft die Klasse, ob das Ereignis definitiv das richtige ist (d. h. BluetoothDevice.ActionFound).

Dann prüft es, ob die Geräte nicht bereits gekoppelt sind (d. h. „verbunden“), und meine Klasse schreibt erneut einige Details über das gefundene Bluetooth-Gerät in die Konsole.

Aber wir sind noch nicht ganz fertig – es gibt noch einen weiteren sehr wichtigen Code, der für moderne Android-Versionen erforderlich ist.

Zu guter Letzt – prüfen Sie, ob die Berechtigungen zur Laufzeit angewendet werden

Dies ist der Teil, der manchmal in anderen Tutorials übersehen wird, und das liegt möglicherweise daran, dass dies nur für neuere Versionen von Android erforderlich ist, sodass ältere Tutorials diesen Schritt nicht benötigt hätten.

Auch wenn die Zugriffsberechtigungen für Grob- und Feinstandort bereits in der Datei „AndroidManifest.xml“ angegeben sind, müssen Sie grundsätzlich auch überprüfen, ob die Berechtigungen zur Laufzeit korrekt festgelegt sind, wenn Sie eine neuere Version als Version 23 des Android SDK verwenden. Wenn dies nicht der Fall ist, müssen Sie Code hinzufügen, um den Benutzer aufzufordern, diese Berechtigungen zu erteilen.

Ich habe meine MainActivity-Klasse unten eingefügt. Diese Klasse:

  • Überprüft Berechtigungen,
  • Fordert den Benutzer zur Eingabe fehlender Berechtigungen auf
  • Registriert den Empfänger zum Auslösen, wenn Bluetooth-Geräte erkannt werden, und
  • Startet die Suche nach Bluetooth-Geräten.
using Android;
using Android.App;
using Android.Bluetooth;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Support.V4.App;
using Android.Support.V4.Content;
 
namespace Bluetooth_Device_Scanner
{
    [Activity(Label = "Bluetooth Device Scanner", MainLauncher = true)]
    public class MainActivity : Activity
    {
        private BluetoothDeviceReceiver _receiver;
 
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
 
            SetContentView(Resource.Layout.activity_main);
 
            const int locationPermissionsRequestCode = 1000;
 
            var locationPermissions = new[]
            {
                Manifest.Permission.AccessCoarseLocation,
                Manifest.Permission.AccessFineLocation
            };
 
            // check if the app has permission to access coarse location
            var coarseLocationPermissionGranted =
                ContextCompat.CheckSelfPermission(this, Manifest.Permission.AccessCoarseLocation);
 
            // check if the app has permission to access fine location
            var fineLocationPermissionGranted =
                ContextCompat.CheckSelfPermission(this, Manifest.Permission.AccessFineLocation);
 
            // if either is denied permission, request permission from the user
            if (coarseLocationPermissionGranted == Permission.Denied ||
                fineLocationPermissionGranted == Permission.Denied)
            {
                ActivityCompat.RequestPermissions(this, locationPermissions, locationPermissionsRequestCode);
            }
 
            // Register for broadcasts when a device is discovered
            _receiver = new BluetoothDeviceReceiver();
 
            RegisterReceiver(_receiver, new IntentFilter(BluetoothDevice.ActionFound));
 
            BluetoothDeviceReceiver.Adapter.StartDiscovery();
        }
    }
}

Jetzt ruft die Anwendung die OnReceive-Methode der BluetoothDeviceReceiver-Klasse auf, wenn sie Bluetooth-Hardware erkennt.

Abschluss

Hoffentlich ist dies für jeden nützlich, der eine Xamarin.Android-Anwendung schreibt, die mit Bluetooth-Geräten interagiert – ich habe eine Weile damit gekämpft und konnte keinen Artikel finden, der alle Teile des Puzzles detailliert beschreibt:

  • Aktualisieren Sie das Manifest mit den 4 erforderlichen Anwendungsberechtigungen
  • Erstellen Sie eine Klasse, die BroadcastReceiver erweitert,
  • Überprüfen Sie zur Laufzeit, ob die Standortberechtigungen erteilt wurden, und fragen Sie den Benutzer, falls dies nicht der Fall ist, und
  • Registrieren Sie die Empfängerklasse und starten Sie die Erkennung.

Über mich: Ich poste regelmäßig über Microsoft-Technologien und .NET – wenn Sie interessiert sind, folgen Sie mir bitte auf Twitter oder sehen Sie sich hier meine früheren Beiträge an. Danke!