Skip to content

A general library for searching and communicating with external devices. Currently support BLE.

License

Notifications You must be signed in to change notification settings

gogovan/flutter-device-searcher

Repository files navigation

flutter_device_searcher

A generic library to search for external device using various connection technologies. Support Bluetooth LE (Android/iOS) and USB (Android only).

Getting Started

  1. Update your app android/app/build.gradle and update minSdkVersion to at least 21
defaultConfig {
    applicationId "com.example.app"
    minSdkVersion 21
    // ...
}
  1. Add Jitpack in your android/build.gradle file
allprojects {
    repositories {
        // ...
        maven { url 'https://jitpack.io' }
    }
}
  1. Setup required permissions according to OS and technology:

Bluetooth

Android

  1. Add the following to your main AndroidManifest.xml. See Android Developers and this StackOverflow answer for more information about permission settings.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.flutter_device_searcher_example">

    <!-- Set android:required="false" if Bluetooth feature is not required by your app.-->
    <uses-feature android:name="android.hardware.bluetooth" android:required="true" />

    <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"
        android:usesPermissionFlags="neverForLocation" tools:targetApi="s" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"
        android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
        android:maxSdkVersion="30" />
    <!-- ... -->
</manifest>

iOS

  1. Include usage description keys for Bluetooth into info.plist. iOS XCode Bluetooth permission instruction

USB

Android

  1. Add the following to your main AndroidManifest.xml.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.flutter_device_searcher_example">

    <!-- Set android:required="false" if USB feature is not required by your app.-->
    <uses-feature android:name="android.hardware.usb.host" android:required="true" />
    
    <uses-permission android:name="hk.gogovan.flutter_device_searcher.USB_PERMISSION" />
    <!-- ... -->
</manifest>

Usage

Connect to device

  1. Create a searcher according to connection technology desired. All searchers implement DeviceSearcherInterface.
  • For BLE, use BluetoothSearcher
  • For USB, use UsbSearcher
  1. Invoke and listen to the Dart Stream returned from search() method. Subclasses of DeviceSearchResults are sent to your listener.
  • For BLE, you will receive a BluetoothResult.
    • id is an identifier for the device, it being a MAC address (may be randomized) in Android and a random UUID in iOS.
      • This may change over different connections even to the same device, so do not store it over app sessions or hold onto it for extended period of time.
    • name is the display name for the device.
  • For USB, you will receive a UsbResult.
    • deviceName is the name of the device as identified by the OS. Use this to connect to device in the UsbDevice constructor.
      • This may change over different connections even to the same device, so do not store it over app sessions or hold onto it for extended period of time.
    • Other information are also retrieved and can be found in UsbResult. You can use these data to determine which device you want to connect to.
final searchStream = btSearcher?.search().listen(cancelOnError: true, (event) {
  final id = event.id;
  // Store the event for later connection.
});
  1. Stop the search before connecting to a device, by cancelling the search stream. Failure to stop the search may cause inability to connect to devices in some phones.
   await searchStream.cancel();
  1. To connect a device, create a DeviceInterface implementation such as BluetoothDevice, passing the device you want to connect. Then call connect to connect to the device.
  final btDevice = BluetoothDevice(deviceSearcher, searchedBtResult[index]);
  await btDevice.connect();

Transfer data after connection

Bluetooth

  • After connecting to device, you may query available services and characteristics.
  final list = await btDevice.getServices();
  • Synchronous read/write from/to the device is done by read and write call respectively.
  • Asynchronous read is done by readAsStream method, which returns a Dart Stream. Listen to stream to receive results.

USB

  • Set interface index and then endpoint number before sending or receiving data. Details of these can be found in the UsbResult.
await usbDevice?.setInterfaceIndex(index);
await usbDevice?.setEndpointIndex(index);
  • After interface and endpoint is set, use transfer to either read or write data, depending on whether the interface is read or write.
List<int> result = await usbDevice?.transfer(Uint8List(0));

Disconnect from device

  • To disconnect from the device, call disconnect on the device.
  await btDevice.disconnect();

BluetoothConnectionMixin

If you are using Bluetooth, you can also elect to use the provided BluetoothConnectionMixin, which handles device searching and connection management.

Override the methods includeResult, includeService and includeCharacteristic methods to specify which Bluetooth device, service and characteristic you are interested in. It should filter results, services and characteristics down to one of each.

About

A general library for searching and communicating with external devices. Currently support BLE.

Topics

Resources

License

Stars

Watchers

Forks