Skip to content

infiniteloopcloud/simpleblue

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Simpleblue

Features

  • Supports both Android and iOS.
  • Small codebase, so breaking changes on the underlying system (ex. bluetooth related updates) can be easily upgraded.
  • Easy to use, only a few functions to create a working app.

Android

Add the following permissions to your AndroidManifest.xml file. To handle permissions you can use permission_handler package.

<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />

<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="28" />

iOS

Add the following properties to Info.plist in Xcode.

  • Privacy - Bluetooth Always Usage Description
  • Privacy - Bluetooth Peripheral Usage Description

Usage

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';

import 'package:simpleblue/model/bluetooth_device.dart';
import 'package:simpleblue/simpleblue.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

const serviceUUID = null;
const scanTimeout = 15000;

class _MyAppState extends State<MyApp> {
  final _simplebluePlugin = Simpleblue();
  
  bool _isBluetoothTurnedOn = false;
  var devices = <String, BluetoothDevice>{};

  String receivedData = '';

  @override
  void initState() {
    super.initState();

    _simplebluePlugin.listenConnectedDevice().listen((connectedDevice) {
      debugPrint("Connected device: $connectedDevice");

      if (connectedDevice != null) {
        setState(() {
          devices[connectedDevice.uuid] = connectedDevice;
        });
      }

      connectedDevice?.stream?.listen((received) {
        setState(() {
          receivedData += "${DateTime.now().toString()}: $received\n";
        });
      });
    }).onError((err) {
      debugPrint(err);
    });

    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      scan();
    });

    _simplebluePlugin.getDevices().then((value) => setState(() {
      for (var device in value) {
        devices[device.uuid] = device;
      }
    }));
    
    _simplebluePlugin.isTurnedOn().then((value) => setState(() {
      _isBluetoothTurnedOn = value ?? false;
    }));

    _simplebluePlugin.listenStateChanges().listen((state) {
      debugPrint('Bluetooth state changed to: $state');

      setState(() {
        _isBluetoothTurnedOn = state == SimpleblueState.on;
      });
    });
  }

  void scan() async {
    final isBluetoothGranted = Platform.isIOS || (await Permission.bluetooth.status) == PermissionStatus.granted ||
        (await Permission.bluetooth.request()) == PermissionStatus.granted;

    if (isBluetoothGranted) {
      print("Bluetooth permission granted");

      final isLocationGranted = Platform.isIOS || (await Permission.location.status) == PermissionStatus.granted ||
          (await Permission.location.request()) == PermissionStatus.granted;

      if (isLocationGranted) {
        print("Location permission granted");
        _simplebluePlugin.scanDevices(serviceUUID: serviceUUID, timeout: scanTimeout).listen((event) {
          setState(() {
            for (var device in event) {
              devices[device.uuid] = device;
            }
          });
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Column(children: [
          if (_isBluetoothTurnedOn)
            TextButton(
                child: Text('Turn Off Bluetooth'),
                onPressed: () {
                  _simplebluePlugin.turnOff();
                }),
          if (!_isBluetoothTurnedOn)
            TextButton(
                child: Text('Turn On Bluetooth'),
                onPressed: () {
                  _simplebluePlugin.turnOn();
                }),
          TextButton(
              child: Text('Get Devices'),
              onPressed: () {
                _simplebluePlugin.getDevices().then((value) {
                  setState(() {
                    for (var device in value) {
                      devices[device.uuid] = device;
                    }
                  });
                });
              }),
          TextButton(
              child: Text('Scan Devices'),
              onPressed: () {
                scan();
              }),
          Expanded(
            child: buildDevices(),
          ),
          SizedBox(
              height: 200,
              child: Align(
                  alignment: Alignment.topLeft,
                  child: Text(
                    receivedData,
                    style: const TextStyle(fontSize: 10),
                  )))
        ]),
      ),
    );
  }

  final _connectingUUIDs = <String>[];

  Widget buildDevices() {
    final devList = devices.values.toList();
    return ListView.builder(
        itemCount: devList.length,
        itemBuilder: (context, index) {
          final device = devList[index];

          return ListTile(
            onTap: () {
              if (device.isConnected) {
                _simplebluePlugin.disconnect(device.uuid);
              } else {
                setState(() {
                  _connectingUUIDs.add(device.uuid);
                });
                _simplebluePlugin.connect(device.uuid).then((value) {
                  setState(() {
                    _connectingUUIDs.remove(device.uuid);
                  });
                });
              }
            },
            leading: _connectingUUIDs.contains(device.uuid)
                ? Icon(Icons.bluetooth, color: Colors.orange)
                : (device.isConnected
                ? Icon(Icons.bluetooth_connected, color: Colors.blue)
                : Icon(
              Icons.bluetooth,
              color: Colors.grey.shade300,
            )),
            title: Text('${device.name ?? 'No name'}\n${device.uuid}'),
            subtitle: device.isConnected
                ? Row(
              children: [
                TextButton(
                    child: Text('Write 1'),
                    onPressed: () {
                      _simplebluePlugin.write(device.uuid, "sample data".codeUnits);
                    }),
                TextButton(
                    child: Text('Write 2'),
                    onPressed: () {
                      _simplebluePlugin.write(device.uuid, "sample data 2".codeUnits);
                    })
              ],
            )
                : null,
          );
        });
  }
}