flutter_classic_bluetooth v1.0.0
pub.dev GitHub

Windows, macOS and Linux

Desktop Bluetooth Classic works, with a different gap on each platform.

Install#

flutter pub add flutter_classic_bluetooth
import 'package:flutter_classic_bluetooth/flutter_classic_bluetooth.dart';

The backends#

PlatformNative API
WindowsWinsock2 AF_BTH sockets
macOSIOBluetooth
LinuxBlueZ 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#

FeatureWindowsmacOSLinux
DiscoveryYesYesYes
Paired devicesYesYesYes
RFCOMM connectYesYesYes
RFCOMM serverYesYesYes
PairYesYesNo
UnpairNoNoNo
Enable / disable adapterNoNoYes
Set discoverableYesNoYes
Connection RSSINoYesNo

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 clang

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