Advertisement
rajath_pai

FlutterBluetoothSerial

Aug 4th, 2021
1,071
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Dart 11.18 KB | None | 0 0
  1. part of flutter_bluetooth_serial;
  2.  
  3. class FlutterBluetoothSerial {
  4.   // Plugin
  5.   static const String namespace = 'flutter_bluetooth_serial';
  6.  
  7.   static FlutterBluetoothSerial _instance = new FlutterBluetoothSerial._();
  8.   static FlutterBluetoothSerial get instance => _instance;
  9.  
  10.   static final MethodChannel _methodChannel =
  11.       const MethodChannel('$namespace/methods');
  12.  
  13.   FlutterBluetoothSerial._() {
  14.     _methodChannel.setMethodCallHandler((MethodCall call) async {
  15.       switch (call.method) {
  16.         case 'handlePairingRequest':
  17.           if (_pairingRequestHandler != null) {
  18.             return _pairingRequestHandler!(
  19.                 BluetoothPairingRequest.fromMap(call.arguments));
  20.           }
  21.           break;
  22.  
  23.         default:
  24.           throw 'unknown common code method - not implemented';
  25.       }
  26.     });
  27.   }
  28.  
  29.   /* Status */
  30.   /// Checks is the Bluetooth interface avaliable on host device.
  31.   Future<bool?> get isAvailable async =>
  32.       await _methodChannel.invokeMethod('isAvailable');
  33.  
  34.   /// Describes is the Bluetooth interface enabled on host device.
  35.   Future<bool?> get isEnabled async =>
  36.       await _methodChannel.invokeMethod('isEnabled');
  37.  
  38.   /// Checks is the Bluetooth interface enabled on host device.
  39.   @Deprecated('Use `isEnabled` instead')
  40.   Future<bool?> get isOn async => await _methodChannel.invokeMethod('isOn');
  41.  
  42.   static final EventChannel _stateChannel =
  43.       const EventChannel('$namespace/state');
  44.  
  45.   /// Allows monitoring the Bluetooth adapter state changes.
  46.   Stream<BluetoothState> onStateChanged() => _stateChannel
  47.       .receiveBroadcastStream()
  48.       .map((data) => BluetoothState.fromUnderlyingValue(data));
  49.  
  50.   /// State of the Bluetooth adapter.
  51.   Future<BluetoothState> get state async => BluetoothState.fromUnderlyingValue(
  52.       await (_methodChannel.invokeMethod('getState') as Future<dynamic>));
  53.  
  54.   /// Returns the hardware address of the local Bluetooth adapter.
  55.   ///
  56.   /// Does not work for third party applications starting at Android 6.0.
  57.   Future<String?> get address => _methodChannel.invokeMethod("getAddress");
  58.  
  59.   /// Returns the friendly Bluetooth name of the local Bluetooth adapter.
  60.   ///
  61.   /// This name is visible to remote Bluetooth devices.
  62.   ///
  63.   /// Does not work for third party applications starting at Android 6.0.
  64.   Future<String?> get name => _methodChannel.invokeMethod("getName");
  65.  
  66.   /// Sets the friendly Bluetooth name of the local Bluetooth adapter.
  67.   ///
  68.   /// This name is visible to remote Bluetooth devices.
  69.   ///
  70.   /// Valid Bluetooth names are a maximum of 248 bytes using UTF-8 encoding,
  71.   /// although many remote devices can only display the first 40 characters,
  72.   /// and some may be limited to just 20.
  73.   ///
  74.   /// Does not work for third party applications starting at Android 6.0.
  75.   Future<bool?> changeName(String name) =>
  76.       _methodChannel.invokeMethod("setName", {"name": name});
  77.  
  78.   /* Adapter settings and general */
  79.   /// Tries to enable Bluetooth interface (if disabled).
  80.   /// Probably results in asking user for confirmation.
  81.   Future<bool?> requestEnable() async =>
  82.       await _methodChannel.invokeMethod('requestEnable');
  83.  
  84.   /// Tries to disable Bluetooth interface (if enabled).
  85.   Future<bool?> requestDisable() async =>
  86.       await _methodChannel.invokeMethod('requestDisable');
  87.  
  88.   /// Opens the Bluetooth platform system settings.
  89.   Future<void> openSettings() async =>
  90.       await _methodChannel.invokeMethod('openSettings');
  91.  
  92.   /* Discovering and bonding devices */
  93.   /// Checks bond state for given address (might be from system cache).
  94.   Future<BluetoothBondState> getBondStateForAddress(String address) async {
  95.     return BluetoothBondState.fromUnderlyingValue(await (_methodChannel
  96.             .invokeMethod('getDeviceBondState', {"address": address})
  97.         as FutureOr<dynamic>));
  98.   }
  99.  
  100.   /// Starts outgoing bonding (pairing) with device with given address.
  101.   /// Returns true if bonded, false if canceled or failed gracefully.
  102.   ///
  103.   /// `pin` or `passkeyConfirm` could be used to automate the bonding process,
  104.   /// using provided pin or confirmation if necessary. Can be used only if no
  105.   /// pairing request handler is already registered.
  106.   ///
  107.   /// Note: `passkeyConfirm` will probably not work, since 3rd party apps cannot
  108.   /// get `BLUETOOTH_PRIVILEGED` permission (at least on newest Androids).
  109.   Future<bool?> bondDeviceAtAddress(String address,
  110.       {String? pin, bool? passkeyConfirm}) async {
  111.     if (pin != null || passkeyConfirm != null) {
  112.       if (_pairingRequestHandler != null) {
  113.         throw "pairing request handler already registered";
  114.       }
  115.       setPairingRequestHandler((BluetoothPairingRequest request) async {
  116.         Future.delayed(Duration(seconds: 1), () {
  117.           setPairingRequestHandler(null);
  118.         });
  119.         if (pin != null) {
  120.           switch (request.pairingVariant) {
  121.             case PairingVariant.Pin:
  122.               return pin;
  123.             default:
  124.               // Other pairing variant requested, ignoring pin
  125.               break;
  126.           }
  127.         }
  128.         if (passkeyConfirm != null) {
  129.           switch (request.pairingVariant) {
  130.             case PairingVariant.Consent:
  131.             case PairingVariant.PasskeyConfirmation:
  132.               return passkeyConfirm;
  133.             default:
  134.               // Other pairing variant requested, ignoring confirming
  135.               break;
  136.           }
  137.         }
  138.         // Other pairing variant used, cannot automate
  139.         return null;
  140.       });
  141.     }
  142.     return await _methodChannel
  143.         .invokeMethod('bondDevice', {"address": address});
  144.   }
  145.  
  146.   /// Removes bond with device with specified address.
  147.   /// Returns true if unbonded, false if canceled or failed gracefully.
  148.   ///
  149.   /// Note: May not work at every Android device!
  150.   Future<bool?> removeDeviceBondWithAddress(String address) async =>
  151.       await _methodChannel
  152.           .invokeMethod('removeDeviceBond', {'address': address});
  153.  
  154.   // Function used as pairing request handler.
  155.   Function? _pairingRequestHandler;
  156.  
  157.   /// Allows listening and responsing for incoming pairing requests.
  158.   ///
  159.   /// Various variants of pairing requests might require different returns:
  160.   /// * `PairingVariant.Pin` or `PairingVariant.Pin16Digits`
  161.   /// (prompt to enter a pin)
  162.   ///   - return string containing the pin for pairing
  163.   ///   - return `false` to reject.
  164.   /// * `BluetoothDevice.PasskeyConfirmation`
  165.   /// (user needs to confirm displayed passkey, no rewriting necessary)
  166.   ///   - return `true` to accept, `false` to reject.
  167.   ///   - there is `passkey` parameter available.
  168.   /// * `PairingVariant.Consent`
  169.   /// (just prompt with device name to accept without any code or passkey)
  170.   ///   - return `true` to accept, `false` to reject.
  171.   ///
  172.   /// If returned null, the request will be passed for manual pairing
  173.   /// using default Android Bluetooth settings pairing dialog.
  174.   ///
  175.   /// Note: Accepting request variant of `PasskeyConfirmation` and `Consent`
  176.   /// will probably fail, because it require Android `setPairingConfirmation`
  177.   /// which requires `BLUETOOTH_PRIVILEGED` permission that 3rd party apps
  178.   /// cannot acquire (at least on newest Androids) due to security reasons.
  179.   ///
  180.   /// Note: It is necessary to return from handler within 10 seconds, since
  181.   /// Android BroadcastReceiver can wait safely only up to that duration.
  182.   void setPairingRequestHandler(
  183.       Future<dynamic> handler(BluetoothPairingRequest request)?) {
  184.     if (handler == null) {
  185.       _pairingRequestHandler = null;
  186.       _methodChannel.invokeMethod('pairingRequestHandlingDisable');
  187.       return;
  188.     }
  189.     if (_pairingRequestHandler == null) {
  190.       _methodChannel.invokeMethod('pairingRequestHandlingEnable');
  191.     }
  192.     _pairingRequestHandler = handler;
  193.   }
  194.  
  195.   /// Returns list of bonded devices.
  196.   Future<List<BluetoothDevice>> getBondedDevices() async {
  197.     final List list = await (_methodChannel.invokeMethod('getBondedDevices'));
  198.     return list.map((map) => BluetoothDevice.fromMap(map)).toList();
  199.   }
  200.  
  201.   static final EventChannel _discoveryChannel =
  202.       const EventChannel('$namespace/discovery');
  203.  
  204.   /// Describes is the dicovery process of Bluetooth devices running.
  205.   Future<bool?> get isDiscovering async =>
  206.       await _methodChannel.invokeMethod('isDiscovering');
  207.  
  208.   /// Starts discovery and provides stream of `BluetoothDiscoveryResult`s.
  209.   Stream<BluetoothDiscoveryResult> startDiscovery() async* {
  210.     late StreamSubscription subscription;
  211.     StreamController controller;
  212.  
  213.     controller = new StreamController(
  214.       onCancel: () {
  215.         // `cancelDiscovery` happens automaticly by platform code when closing event sink
  216.         subscription.cancel();
  217.       },
  218.     );
  219.  
  220.     await _methodChannel.invokeMethod('startDiscovery');
  221.  
  222.     subscription = _discoveryChannel.receiveBroadcastStream().listen(
  223.           controller.add,
  224.           onError: controller.addError,
  225.           onDone: controller.close,
  226.         );
  227.  
  228.     yield* controller.stream
  229.         .map((map) => BluetoothDiscoveryResult.fromMap(map));
  230.   }
  231.  
  232.   /// Cancels the discovery
  233.   Future<void> cancelDiscovery() async =>
  234.       await _methodChannel.invokeMethod('cancelDiscovery');
  235.  
  236.   /// Describes is the local device in discoverable mode.
  237.   Future<bool?> get isDiscoverable =>
  238.       _methodChannel.invokeMethod("isDiscoverable");
  239.  
  240.   /// Asks for discoverable mode (probably always prompt for user interaction in fact).
  241.   /// Returns number of seconds acquired or zero if canceled or failed gracefully.
  242.   ///
  243.   /// Duration might be capped to 120, 300 or 3600 seconds on some devices.
  244.   Future<int?> requestDiscoverable(int durationInSeconds) async =>
  245.       await _methodChannel
  246.           .invokeMethod("requestDiscoverable", {"duration": durationInSeconds});
  247.  
  248.   /* Connecting and connection */
  249.   // Default connection methods
  250.   BluetoothConnection? _defaultConnection;
  251.  
  252.   @Deprecated('Use `BluetoothConnection.isEnabled` instead')
  253.   Future<bool> get isConnected async => Future.value(
  254.       _defaultConnection == null ? false : _defaultConnection!.isConnected);
  255.  
  256.   @Deprecated('Use `BluetoothConnection.toAddress(device.address)` instead')
  257.   Future<void> connect(BluetoothDevice device) =>
  258.       connectToAddress(device.address);
  259.  
  260.   @Deprecated('Use `BluetoothConnection.toAddress(address)` instead')
  261.   Future<void> connectToAddress(String? address) => Future(() async {
  262.         _defaultConnection = await BluetoothConnection.toAddress(address);
  263.       });
  264.  
  265.   @Deprecated(
  266.       'Use `BluetoothConnection.finish` or `BluetoothConnection.close` instead')
  267.   Future<void> disconnect() => _defaultConnection!.finish();
  268.  
  269.   @Deprecated('Use `BluetoothConnection.input` instead')
  270.   Stream<Uint8List>? onRead() => _defaultConnection!.input;
  271.  
  272.   @Deprecated(
  273.       'Use `BluetoothConnection.output` with some decoding (such as `ascii.decode` for strings) instead')
  274.   Future<void> write(String message) {
  275.     _defaultConnection!.output.add(utf8.encode(message) as Uint8List);
  276.     return _defaultConnection!.output.allSent;
  277.   }
  278.  
  279.   @Deprecated('Use `BluetoothConnection.output` instead')
  280.   Future<void> writeBytes(Uint8List message) {
  281.     _defaultConnection!.output.add(message);
  282.     return _defaultConnection!.output.allSent;
  283.   }
  284. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement