Bluetooth.Core
1.0.3
dotnet add package Bluetooth.Core --version 1.0.3
NuGet\Install-Package Bluetooth.Core -Version 1.0.3
<PackageReference Include="Bluetooth.Core" Version="1.0.3" />
<PackageVersion Include="Bluetooth.Core" Version="1.0.3" />
<PackageReference Include="Bluetooth.Core" />
paket add Bluetooth.Core --version 1.0.3
#r "nuget: Bluetooth.Core, 1.0.3"
#:package Bluetooth.Core@1.0.3
#addin nuget:?package=Bluetooth.Core&version=1.0.3
#tool nuget:?package=Bluetooth.Core&version=1.0.3
Bluetooth.Core & Bluetooth.Maui
<div style="max-width: 256px; margin-left: auto; margin-right: auto;">
</div>
A cross-platform .NET MAUI Bluetooth Low Energy (BLE) library providing a unified API for Android, iOS, and Windows platforms.
Features
- 🔍 Bluetooth Scanning - Discover nearby BLE devices with filtering
- 🔗 Device Connection - Connect and manage multiple devices
- 📡 GATT Operations - Read, write, and subscribe to characteristics
- 📢 Broadcasting - Act as a BLE peripheral (Android only)
- 🎯 Cross-Platform - Consistent API across Android, iOS, and Windows
- 🔄 Async/Await - Modern async patterns with cancellation support
- 💉 Dependency Injection - Built-in MAUI DI support
Installation
dotnet add package Bluetooth.Maui
Quick Start
Option 1: MAUI Dependency Injection (Recommended)
Register Bluetooth services in your MauiProgram.cs:
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseBluetooth(
configureScanner: scanner =>
{
// Optional: Configure scanner
scanner.AdvertisementFilter = ad => ad.IsConnectable;
}
);
return builder.Build();
}
}
Then inject IBluetoothScanner in your pages or view models:
public partial class MainPage : ContentPage
{
private readonly IBluetoothScanner _scanner;
public MainPage(IBluetoothScanner scanner)
{
InitializeComponent();
_scanner = scanner;
}
protected override async void OnAppearing()
{
base.OnAppearing();
// Explicitly initialize when ready (handles permissions)
await _scanner.InitializeAsync();
// Start scanning
await _scanner.StartAsync();
}
}
Option 2: Direct Instantiation
If you prefer full control over initialization timing:
// Create and initialize scanner
var scanner = await BluetoothScanner.GetOrCreateDefaultScannerAsync();
// Configure scanner
scanner.AdvertisementFilter = ad => ad.IsConnectable;
// Start scanning
await scanner.StartAsync();
Usage Examples
Scanning for Devices
var scanner = await BluetoothScanner.GetOrCreateDefaultScannerAsync();
// Subscribe to device discovery
scanner.DevicesAdded += (sender, args) =>
{
foreach (var device in args.Devices)
{
Console.WriteLine($"Found: {device.Name} ({device.Id})");
}
};
// Start scanning
await scanner.StartAsync();
// Stop scanning
await scanner.StopAsync();
Connecting to a Device
// Get a specific device
var device = await scanner.GetDeviceAsync(deviceId);
// Or wait for a device matching criteria
var device = await scanner.GetDeviceOrWaitForDeviceToAppearAsync(
filter: d => d.Name.Contains("MyDevice"),
timeout: TimeSpan.FromSeconds(10)
);
// Connect
await device.ConnectAsync();
// Check connection status
if (device.IsConnected)
{
Console.WriteLine("Connected!");
}
Exploring Services and Characteristics
// Discover services
await device.ExploreServicesAsync(exploreCharacteristicsToo: true);
// Get a specific service
var service = device.GetService(serviceGuid);
// Get a specific characteristic
var characteristic = service.GetCharacteristic(characteristicGuid);
Reading and Writing Characteristics
// Read value
var value = await characteristic.ReadAsync();
Console.WriteLine($"Value: {BitConverter.ToString(value.ToArray())}");
// Write value
byte[] data = { 0x01, 0x02, 0x03 };
await characteristic.WriteAsync(data);
// Write without response (faster)
await characteristic.WriteAsync(data, withoutResponse: true);
Subscribing to Notifications
// Subscribe to characteristic changes
characteristic.ValueUpdated += (sender, args) =>
{
Console.WriteLine($"New value: {BitConverter.ToString(args.Value.ToArray())}");
};
await characteristic.SubscribeAsync();
// Unsubscribe when done
await characteristic.UnsubscribeAsync();
Using Characteristic Access Services
For strongly-typed characteristic access:
// Define a characteristic access service
var batteryService = CharacteristicAccessServiceFactory.CreateForByte(
characteristicId: Guid.Parse("00002A19-0000-1000-8000-00805F9B34FB"),
name: "Battery Level"
);
// Read the battery level
var batteryLevel = await batteryService.ReadAsync(device);
Console.WriteLine($"Battery: {batteryLevel}%");
// Subscribe to battery level changes
await batteryService.SubscribeAsync(device, (value) =>
{
Console.WriteLine($"Battery changed: {value}%");
});
Broadcasting (Android Only)
var broadcaster = await BluetoothBroadcaster.GetOrCreateDefaultBroadcasterAsync();
// Start broadcasting
await broadcaster.StartAsync();
// Stop broadcasting
await broadcaster.StopAsync();
Advanced Configuration
Filtering Advertisements
scanner.AdvertisementFilter = advertisement =>
{
// Only process connectable devices
if (!advertisement.IsConnectable) return false;
// Only devices with specific service
if (!advertisement.ServicesGuids.Contains(myServiceGuid)) return false;
// Only devices with good signal strength
if (advertisement.RawSignalStrengthInDBm < -80) return false;
return true;
};
Handling Timeouts and Cancellation
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
try
{
await device.ConnectAsync(
timeout: TimeSpan.FromSeconds(10),
cancellationToken: cts.Token
);
}
catch (OperationCanceledException)
{
Console.WriteLine("Connection timed out or was cancelled");
}
Device Cleanup
// Clean up specific device
await scanner.CleanAsync(device);
// Clean up all devices
await scanner.CleanAsync();
// Dispose device (disconnects and cleans up)
await device.DisposeAsync();
Platform-Specific Considerations
Android
- Requires
BLUETOOTH_SCANandBLUETOOTH_CONNECTpermissions (Android 12+) - Requires
ACCESS_FINE_LOCATIONpermission for scanning - Broadcasting fully supported via
BluetoothGattServer
iOS
- Requires
NSBluetoothAlwaysUsageDescriptionin Info.plist - Limited background scanning capabilities
- Broadcasting not currently implemented (throws
NotImplementedException)
Windows
- Requires Bluetooth capability in package manifest
- Use
GattSession.MaintainConnectionfor persistent connections - Broadcasting not currently implemented (throws
NotImplementedException)
Architecture
Plugin.Bluetooth
├── Bluetooth.Core # Platform-agnostic abstractions
│ ├── Abstractions/ # Interfaces
│ ├── BaseClasses/ # Base implementations
│ ├── CharacteristicAccess/
│ └── Exceptions/
└── Bluetooth.Maui # Platform-specific implementations
├── Core/ # Fallback implementations
└── Platforms/
├── Android/ # Android BLE
├── iOS/ # CoreBluetooth
└── Windows/ # Windows.Devices.Bluetooth
API Overview
Core Interfaces
IBluetoothScanner- Device discovery and scanningIBluetoothDevice- Device representation and connection managementIBluetoothService- GATT service wrapperIBluetoothCharacteristic- GATT characteristic operationsIBluetoothBroadcaster- Peripheral/advertising modeIBluetoothAdvertisement- Advertisement data
Exception Handling
The library provides a comprehensive exception hierarchy:
try
{
await device.ConnectAsync();
}
catch (DeviceNotFoundException ex)
{
// Device not found during scan
}
catch (DeviceConnectionFailedException ex)
{
// Connection attempt failed
}
catch (DeviceNotConnectedException ex)
{
// Attempted operation on disconnected device
}
catch (BluetoothException ex)
{
// Generic Bluetooth error
}
Requirements
- .NET 10.0 or higher
- MAUI application
License
MIT License - Copyright (c) 2025 Laerdal Medical
See LICENSE.md for details.
Contributing
Contributions are welcome! Please ensure all public APIs are documented with XML comments.
Support
For issues and feature requests, please use the GitHub issue tracker.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Plugin.BaseTypeExtensions (>= 1.0.18)
- Plugin.ByteArrays (>= 1.0.27)
- Plugin.ExceptionListeners (>= 1.0.3)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Bluetooth.Core:
| Package | Downloads |
|---|---|
|
Bluetooth.Maui
Bluetooth.Maui for .NET Maui |
GitHub repositories
This package is not used by any popular GitHub repositories.