flutter_classic_bluetooth v1.0.0
pub.dev GitHub

Run a server

Advertise a service, accept incoming connections, and let other devices connect to you.

Install#

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

Listening#

final server = await bluetooth.startServer(
  serviceName: 'My App Serial',
  uuid: BtcUuid.spp,
);

server.connections.listen((connection) {
  print('client connected');
  connection.input.lines().listen((line) => print('client said: $line'));
});

serviceName is what appears in the other device's SDP browse, so make it recognisable. Each incoming client arrives as a full BtcConnection, the same type connect returns, so everything on the send and receive page applies unchanged.

Be discoverable#

Listening is not enough on its own. A client that has never paired with you cannot find you unless the adapter is discoverable.

final caps = await bluetooth.getPlatformCapabilities();
if (caps.canSetDiscoverable) {
  await bluetooth.setDiscoverable(300);   // seconds
}

On Android this shows a system dialog the user has to accept. Windows and Linux apply it directly, macOS and iOS have no API for it. Already paired clients can connect without this.

Your own service UUID#

Use SPP when you want generic serial terminals to be able to connect. Use a UUID of your own when the two ends are both your software and you would rather not have unrelated apps attach.

final server = await bluetooth.startServer(
  serviceName: 'Fleet Sync',
  uuid: '7f2c9e40-1b3a-4d6e-9f10-2c8b5a7d3e91',
);

Both ends must agree. The client passes the same string to connect.

Several clients#

The connections stream keeps emitting, so a server can hold more than one client where the platform supports it. Track them yourself, since closing the server socket does not close connections it already handed you.

final clients = <BtcConnection>[];

server.connections.listen((connection) {
  clients.add(connection);
  connection.stateStream.listen((s) {
    if (s == BtcConnectionState.disconnected) clients.remove(connection);
  });
});

Future<void> broadcast(String line) async {
  for (final c in clients) {
    await c.output.writeLine(line);
  }
}

Shutting down#

for (final c in clients) {
  await c.finish();
}
await server.close();

Close the connections first, then the listening socket. The other order leaves clients hanging until they notice the link went quiet.

Where it works#

PlatformServer mode
AndroidYes
WindowsYes
macOSYes
LinuxYes
iOSNo

iOS cannot act as an RFCOMM server. startServer throws BtcUnsupportedException, so gate the feature on caps.canCreateServer rather than on the platform name.