Windows, macOS and Linux
Desktop Bluetooth Classic works, with a different gap on each platform.
Install#
flutter pub add flutter_classic_bluetoothimport 'package:flutter_classic_bluetooth/flutter_classic_bluetooth.dart';The backends#
| Platform | Native API |
|---|---|
| Windows | Winsock2 AF_BTH sockets |
| macOS | IOBluetooth |
| Linux | BlueZ RFCOMM sockets over D-Bus |
The Dart API is identical across all three. Anything unavailable throws BtcUnsupportedException rather than failing quietly or returning an empty result.
What differs#
| Feature | Windows | macOS | Linux |
|---|---|---|---|
| Discovery | Yes | Yes | Yes |
| Paired devices | Yes | Yes | Yes |
| RFCOMM connect | Yes | Yes | Yes |
| RFCOMM server | Yes | Yes | Yes |
| Pair | Yes | Yes | No |
| Unpair | No | No | No |
| Enable / disable adapter | No | No | Yes |
| Set discoverable | Yes | No | Yes |
| Connection RSSI | No | Yes | No |
Windows#
Nothing to configure. No manifest entry, no capability declaration, no extra dependency. Pairing works and shows the Windows pairing flow; removing a pairing has no public API, so that has to happen in Settings.
macOS#
Add the Bluetooth entitlement to both DebugProfile.entitlements and Release.entitlements, or a sandboxed build sees nothing:
<key>com.apple.security.device.bluetooth</key>
<true/>macOS is the only platform that reports live signal strength on an open connection.
final caps = await bluetooth.getPlatformCapabilities();
if (caps.canReadConnectionRssi) {
final rssi = await connection.readRssi();
print('$rssi dBm');
}Everywhere else readRssi throws, because no public Bluetooth Classic API exposes it. Discovery-time RSSI on BtcDevice.rssi is separate and available everywhere.
Linux#
The native plugin links against GTK and BlueZ, so the development packages have to be present or the build fails at CMake:
sudo apt-get install -y libgtk-3-dev libbluetooth-dev ninja-build cmake pkg-config clangLinux is the only desktop that can turn the adapter on and off. It cannot pair, because BlueZ delegates PIN and passkey handling to a system pairing agent that a Flutter app does not provide. Pair with bluetoothctl or the desktop's Bluetooth settings, then connect normally.
One UI, every platform#
Reading capabilities rather than checking Platform.isWindows keeps the code honest, and keeps working when a gap gets filled in a later release.
final caps = await bluetooth.getPlatformCapabilities();
setState(() {
showScanButton = caps.canDiscoverDevices;
showPairButton = caps.canBondDevices;
showForgetButton = caps.canUnbondDevices;
showAdapterToggle = caps.canEnableBluetooth;
showServerTab = caps.canCreateServer;
});Wrap anything you cannot gate in a try for BtcUnsupportedException, so an unexpected platform degrades instead of crashing.