A comprehensive Flutter plugin for Bluetooth Serial Port Profile (SPP) communication with full terminal functionality.
Features
- Device Management: Scan and connect to paired Bluetooth devices
- Serial Communication: Send and receive data over Bluetooth SPP
- Background Service: Maintain connection when app is backgrounded
- Hex Mode: Support for hexadecimal data transmission
- Newline Handling: Various newline format support (CR, LF, CRLF)
- Permission Management: Runtime permission handling for Android 12+
- Real-time Streaming: Event-based data streaming
- Error Handling: Comprehensive error reporting and handling
Platform Support
Platform | Support |
---|---|
Android | ✅ Full |
iOS | ⚠️ Basic |
Installation
Add this to your package's pubspec.yaml
file:
dependencies:
spp_connection_plugin: ^0.0.7
Android Setup
Add the following permissions to your android/app/src/main/AndroidManifest.xml
:
<!-- Bluetooth permissions -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
<!-- Bluetooth permissions for older Android versions -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30"/>
<!-- Bluetooth permissions for Android 12+ -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
Usage
Basic Implementation
import 'package:spp_connection_plugin/spp_connection_plugin.dart';
class BluetoothExample extends StatefulWidget {
@override
_BluetoothExampleState createState() => _BluetoothExampleState();
}
class _BluetoothExampleState extends State<BluetoothExample> {
final SppConnectionPlugin _bluetooth = SppConnectionPlugin();
@override
void initState() {
super.initState();
_initBluetooth();
}
Future<void> _initBluetooth() async {
// Check permissions
bool hasPermissions = await _bluetooth.hasPermissions();
if (!hasPermissions) {
hasPermissions = await _bluetooth.requestPermissions();
}
if (hasPermissions) {
// Get paired devices
final devices = await _bluetooth.getPairedDevices();
// Connect to a device
await _bluetooth.connectToDevice(devices.first.address);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<BluetoothConnectionState>(
stream: _bluetooth.connectionStateStream,
builder: (context, snapshot) {
final state = snapshot.data ?? BluetoothConnectionState.disconnected;
return Center(
child: Text('Connection: ${state.displayName}'),
);
},
),
);
}
}
Sending and Receiving Data
// Listen to incoming data
_bluetooth.dataStream.listen((data) {
final text = String.fromCharCodes(data);
print('Received: $text');
});
// Send text data
await _bluetooth.sendText('Hello World');
// Send hex data
await _bluetooth.sendHex('48 65 6C 6C 6F'); // "Hello" in hex
// Send raw bytes
final data = Uint8List.fromList([0x48, 0x65, 0x6C, 0x6C, 0x6F]);
await _bluetooth.sendData(data);
Configuration Options
// Enable hex mode
_bluetooth.setHexMode(true);
// Set newline type
_bluetooth.setNewlineType(TextUtils.newlineCRLF);
// Start background service
await _bluetooth.startBackgroundService();
API Reference
Main Class: SppConnectionPlugin
Device Management
Future<bool> isBluetoothSupported()
Future<bool> isBluetoothEnabled()
Future<void> enableBluetooth()
Future<List<BluetoothDeviceModel>> getPairedDevices()
Connection Management
Future<void> connectToDevice(String address)
Future<void> disconnect()
BluetoothConnectionState get connectionState
Stream<BluetoothConnectionState> get connectionStateStream
Data Transmission
Future<void> sendData(Uint8List data)
Future<void> sendText(String text)
Future<void> sendHex(String hexString)
Stream<Uint8List> get dataStream
Permission Management
Future<bool> hasPermissions()
Future<bool> requestPermissions()
Settings
void setHexMode(bool enabled)
void setNewlineType(String newline)
Future<void> startBackgroundService()
Future<void> stopBackgroundService()
Models
BluetoothDeviceModel
class BluetoothDeviceModel {
final String name;
final String address;
final int type;
final bool bonded;
String get displayName; // Returns name if available, otherwise address
}
BluetoothConnectionState
enum BluetoothConnectionState {
disconnected,
connecting,
connected,
disconnecting,
}
Utilities
TextUtils
static Uint8List fromHexString(String hexString)
static String toHexString(Uint8List bytes)
static String toCaretString(String input, {bool keepNewline = true})
static bool isValidHexString(String hexString)
Example App
The plugin includes a comprehensive example app demonstrating all features:
- Device listing and selection
- Terminal interface with real-time communication
- Hex mode support
- Connection status monitoring
- Settings and configuration options
Run the example:
cd example
flutter run
Troubleshooting
Common Issues
- Permission Denied: Ensure all required permissions are declared and granted
- Connection Failed: Check if device is paired and within range
- Data Not Received: Verify the correct SPP UUID and data format
Android 12+ Considerations
Android 12 introduced new Bluetooth permissions. The plugin automatically handles the transition between old and new permission models.
Contributing
Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.
License
This project is licensed under the MIT License - see the LICENSE file for details.