requestLEScan static method

Future<BluetoothLEScan> requestLEScan(
  1. BluetoothLEScanOptions options
)

Request the user to start scanning for Bluetooth LE devices in the area. Not every browser supports this method yet so check it using hasRequestLEScan. However even if the browser supports it, the Future may never complete on browsers. This has been the case for Chrome on linux and windows even with the correct flag enabled. Chrome on Android does seem to work. Add a Future.timeout to combat this.

The devices found through this are emitted using the 'advertisementreceived' event on addEventListener.

It will only emit devices that match the options so it could happen that there are no devices in range while the scan is running. See BluetoothLEScanOptions for details on the options.

Once a scan is running (and there were no errors) it can be stopped by calling BluetoothLEScan.stop on the returned object from the Future. If this object doesn't get saved then there is no way to stop the scan, it should be able to start multiple scans with different scan options.

Implementation

static Future<BluetoothLEScan> requestLEScan(
    final BluetoothLEScanOptions options) async {
  if (!hasRequestLEScan()) {
    throw NativeAPINotImplementedError("requestLEScan");
  }
  final promise = _nativeBluetooth.requestLEScan(options);
  try {
    final result = await _JSUtil.promiseToFuture(promise);
    return BluetoothLEScan.fromJSObject(result);
  } catch (e) {
    final error = e.toString();
    if (error.startsWith("InvalidStateError")) {
      // The user probably canceled the permission dialog
      if (error.toLowerCase().contains("user cancel")) {
        // TODO: check if this is also the message on other browsers!
        throw UserCancelledDialogError(error
            .replaceFirst("InvalidStateError", "")
            .replaceFirst(": ", ""));
      }
      throw StateError(
          error.replaceFirst("InvalidStateError", "").replaceFirst(": ", ""));
    } else if (error.startsWith("NotSupportedError")) {
      throw NativeAPINotImplementedError("requestLEScan");
    } else if (error.startsWith("NotAllowedError")) {
      throw PermissionError("requestLEScan");
    } else if (error.startsWith("SecurityError")) {
      if (error.toLowerCase().contains("gesture")) {
        throw MissingUserGestureError("requestLEScan");
      }
      throw PolicyError("requestLEScan");
    }

    if (e is Error) {
      rethrow;
    }
    throw BrowserError(error);
  }
}