edufolly / flutter_bluetooth_serial

A basic Flutter Bluetooth Serial
MIT License
479 stars 448 forks source link

Get currently connected device and it's connection #53

Closed kula124p closed 5 years ago

kula124p commented 5 years ago

Hello! So this is my use case: I'm building an BT controller app (big shock ik), however I don't want to do connecting or disconnecting atm in the app, so I use Android's built-in BT manager to do that. If device is connected when the app is opened, the status message is set accordingly. I didn't find method for this anywhere in the lib's code, I did find the deprecated isConnected that gives wrong status. I created this code for my app, and I can PR it if you think it's useful. Atm, I'm just getting the bool status of connection but I'm considering getting the underlying connection object as well. Speaking of which, I noticed BluetoothConnection does not have reference to connected BuetoothDevice. Adding that might be useful (for this UC at least). Full feature supporting this might be: -> getCurrentConnection method that returns BluetoothConnection object. -> The object has reference to the device so it's name, address etc can be read -> if method returns null, no device is currently connected -> Errors to be handled accordingly, if device is connected but connection object can't be retrieved for example. Few others come to mind... -> .... -> Profit!

Thoughts? If you like the idea, I'll do the PR, no worries.

AgainPsychoX commented 5 years ago

BT controller app

It would be hard to do it "legitlly" since only system apps have access to some special functionalities (example: obtaining MAC address (btw it now works in the plugin too with little nasty hack)).

(big shock ik),

Well, for real? Yea, why reinventing the wheel, especially if the steel wheel is already provided by Android system ;) This plugin allows to create others apps too. I am writing app for my dad aquarium controller that is using Bluetooth to communicate (atm suspended, since I am working on other projects, like this library).

Speaking of which, I noticed BluetoothConnection does not have reference to connected BuetoothDevice. Adding that might be useful (for this UC at least).

Is is done by reason: single responsibility - connection, providing input/output and close functionality. The same practice is used deep in platform code, also in raw sockets (i.e. Python). Note, that while creating the BluetoothConnection you already know the address you are connecting to.

I think there is a way to obtain channel or some kind of port in some environments, but afik I do not see something like this is official Android Bluetooth API. And digging trough implementation code to find some hacky way of doing it is (at least for now) not that important thing.


\

If device is connected when the app is opened, the status message is set accordingly. I didn't find method for this anywhere in the lib's code, I did find the deprecated isConnected that gives wrong status.

This deprecated isConnected is deprecated because there was only one connection possible back in time. For now it works only with the basic (deprecated) connection creation. It is implemented with isConnected of BluetoothConnection - so you should use it on your connection instead ;)

Please note, there is no way (at least for now?) to get connection status of some device if the connection was started by other application (same for the system) or in other session of your app :/ This issue will stand for this exact request.

</this one is a bug to be fixed>


-> getCurrentConnection method that returns BluetoothConnection object.

If you mean it for BluetoothDevice, note that the app could only access connection started by this app (and in current session). Also, such searching in all the connections for the few that are connected to specified device requires to store information about device we are connecting to - so see my sub-answer one above.

I created this code for my app, and I can PR it if you think it's useful.

I think, on this repository we should keep only some master example application in order to just show all the features, no matter how stupid they are in some context. For other apps using the plugin there could be list in README. If you want to share your app, you can write PR with new subheader in Getting started like

#### Apps using this plugin:

- [<your app name>](url to the app repository) - <some description?>
kula124p commented 5 years ago

Sorry for late response, busy week. Well, I went ahead with my use case and I concluded it was utterly stupid 🤦‍♂️ The problem is a simple one: when you are connected to the device via another app or the Android system for that matter, attempting to call BluetoothConnection.toAddress() for a device that is already connected will give you uncatchable PlatformException mentioned in another issue. This is because you are connecting to the device you are connected to and you are doing so from another app (reopening the opened socket I guess). This flow sucks. With that in mind, I agree with everything you said, I actually came to your way of thinking. My flow is probably impossible to pull off on Android... Basically, ignore it. Side note, my "big shock ik" comment was a joke, I was referring to the fact that most people using this lib are building some kind of Bluetooth controller app, or something similar. Not saying it can't be used for anything else, of course it can :) Since I really like this lib I want to contribute. How about this for isConnected:

// bt is the singleton instance 
  Future<bool> get isConnected => _bt.getBondedDevices()
    .then((devices) =>
      devices.firstWhere((d) => d.isConnected, orElse: () => null) != null);

Rationale being that you can't be connected to a device that you are not paired (bonded) with. List of this devices in never too big so performance-wise shouldn't be too heavy. Also, I'm thinking of adding the graphical widget that lists BT devices, maybe even has discovery feature and the connect button. That would save people time of writing boilerplate for connection menu and "reinventing the wheel" as you said. Also, the exception I have mentioned, can it be wrapped and rethrown so that Flutter can catch it? It tends to release PlatformException (catch never triggers) for some reason, apparently it's a "known issue" according to few articles... Usually happens with firebase Exceptions. I can try to fix that one, but my Java is rusty. When I do, review me strictly. Thank you for responding!

AgainPsychoX commented 5 years ago

attempting to call BluetoothConnection.toAddress() for a device that is already connected will give you uncatchable PlatformException mentioned in another issue.

Please mention the issue. I could find that one. :C Beside that, afik all PlatformException are catchable. And beside that too, I don't know what to do about that problem for really. It is normal to get the exception if you cannot connect to specified address. True underlying reason unfortunately might be unknown to the library and so the user app - either it was "already connected by other app" or "there is no device with that address detectable". If you see some possibility how to check is some other app already connected to selected device, it would be implemented to notify the user of the library.

How about this for isConnected

You mean global isConnected for FlutterBluetoothSerial instance? It is for now deprecated for a reason: it was used globally before, because there were globally only one connection doable. Now you can connect to multiple devices at the same time, so there is a BluetoothConnection with its isConnected.

As far I understand from the code, you want to have "is any device connected" getter?? I think it should not be at all in the library, or if really necessary, just named other than isConnected (idk, isConnectedToAnything /shrug).

Rationale being that you can't be connected to a device that you are not paired (bonded) with.

That might be not true, there are still insecure connections hidden in Android Java API 🤔 (and in the BT standard of course).

I'm thinking of adding the graphical widget that lists BT devices, maybe even has discovery feature and the connect button. That would save people time of writing boilerplate for connection menu and "reinventing the wheel" as you said.

I think there are already whole pages that are implementing it in examples (either discovery page or select to connect page), but sure - feel free to open PR with contribution to the example app code. I was trying to generalize whole listing devices and etc at the moment of writing second listing (for selection to connect to chat), but I stopped at only BluetoothDeviceListEntry because there were few differences between just discoverying and do connect screen (at least for me in time of writing these).

Also, the exception I have mentioned, can it be wrapped and rethrown so that Flutter can catch it? It tends to release PlatformException (catch never triggers) for some reason, apparently it's a "known issue" according to few articles... Usually happens with firebase Exceptions.

Again, I don't see issue like this in issues :C If you mean #18 , please take a look on my last comment especially. PlatformException is just encapsulated exception from platform code (in our case: Java/Android). The important is content of this exception, not its type. BTW I think there might be some dedicated exception rethrown by the library in some cases.

kula124p commented 5 years ago

Can't believe I didn't link the issue... Yes, the one you mentioned is the one I was referring to. I get why It can't be detected. It was weird that it just exits from the try without catching doe. I attached catch to the future call and called it in try block after that, just exits all the way (was trying to catch it anyway I can) and crashes the app ofc. Weird... Doesn't matter... I'll go ahead and finish up the app, and after I have the functional code I'll get it touch to see weather it can be useful to the lib. You can close the issue :+1: Thank you for replaying!

AgainPsychoX commented 5 years ago

It was weird that it just exits from the try without catching doe. I attached catch to the future call and called it in try block after that, just exits all the way (was trying to catch it anyway I can) and crashes the app ofc.

Please check the example code for catching connection error: https://github.com/edufolly/flutter_bluetooth_serial/blob/b69d01fe5821aa30fdc26130a0df44806ca9b2fe/example/lib/MainPage.dart#L295-L321

If it does not work for you, please open new issue, I would try to help.

Thank you for replaying!

You are welcome :)

AgainPsychoX commented 5 years ago

Oh, I got what you might referring to while writing "uncatchable PlatformException". It might be uncatchable, because you might be were catching it wrong (like me minutes ago, that's why I am writing this):

  @override
  void initState() {
    super.initState();
    try {
      BluetoothConnection.toAddress(widget.server.address).then((_connection) {
        print('Connected to the device');
        connection = _connection;
        setState(() {
          isConnecting = false;
        });

        connection.input.listen(_onDataReceived).onDone(() {
          print('Disconnected by remote request');
        });
      });
    } catch (exception) {
      print('Cannot connect, exception occured');
    }
  }

It is wrong, because this is Future awaited by callbacks, so error in then statement will not be dispatched to this try-catch. This is how it should look like:

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

    BluetoothConnection.toAddress(widget.server.address).then((_connection) {
      print('Connected to the device');
      connection = _connection;
      setState(() {
        isConnecting = false;
      });

      connection.input.listen(_onDataReceived).onDone(() {
        print('Disconnected by remote request');
      });
    }).catchError((error) {
      print('Cannot connect, exception occured');
      print(error);
    });
  }

Try-catch solution in comment before works, because it is async function, so it can catch errors from awaited futures.

LaraibIshtiaq commented 1 year ago

Hello! So this is my use case: I'm building an BT controller app (big shock ik), however I don't want to do connecting or disconnecting atm in the app, so I use Android's built-in BT manager to do that. If device is connected when the app is opened, the status message is set accordingly. I didn't find method for this anywhere in the lib's code, I did find the deprecated isConnected that gives wrong status. I created this code for my app, and I can PR it if you think it's useful. Atm, I'm just getting the bool status of connection but I'm considering getting the underlying connection object as well. Speaking of which, I noticed BluetoothConnection does not have reference to connected BuetoothDevice. Adding that might be useful (for this UC at least). Full feature supporting this might be: -> getCurrentConnection method that returns BluetoothConnection object. -> The object has reference to the device so it's name, address etc can be read -> if method returns null, no device is currently connected -> Errors to be handled accordingly, if device is connected but connection object can't be retrieved for example. Few others come to mind... -> .... -> Profit!

Thoughts? If you like the idea, I'll do the PR, no worries.

Hey can you do that PR? I need somehting like that too, i want the connection instance but cannot get a hold of it.

LaraibIshtiaq commented 1 year ago

Hello! So this is my use case: I'm building an BT controller app (big shock ik), however I don't want to do connecting or disconnecting atm in the app, so I use Android's built-in BT manager to do that. If device is connected when the app is opened, the status message is set accordingly. I didn't find method for this anywhere in the lib's code, I did find the deprecated isConnected that gives wrong status. I created this code for my app, and I can PR it if you think it's useful. Atm, I'm just getting the bool status of connection but I'm considering getting the underlying connection object as well. Speaking of which, I noticed BluetoothConnection does not have reference to connected BuetoothDevice. Adding that might be useful (for this UC at least). Full feature supporting this might be: -> getCurrentConnection method that returns BluetoothConnection object. -> The object has reference to the device so it's name, address etc can be read -> if method returns null, no device is currently connected -> Errors to be handled accordingly, if device is connected but connection object can't be retrieved for example. Few others come to mind... -> .... -> Profit!

Thoughts? If you like the idea, I'll do the PR, no worries.

Waiting for this PR

NasDev07 commented 6 months ago

help me an error occurs, if an error like this occurs what to do. when entering chat.

D/BluetoothAdapter( 4270): 163554551: getState(). Returning ON W/BluetoothAdapter( 4270): getBluetoothService() called with no BluetoothManagerCallback I/flutter ( 4270): Cannot connect, exception occured I/flutter ( 4270): PlatformException(connect_error, read failed, socket might closed or timeout, read ret: -1, java.io.IOException: read failed, socket might closed or timeout, read ret: -1 I/flutter ( 4270): at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:772) I/flutter ( 4270): at android.bluetooth.BluetoothSocket.readInt(BluetoothSocket.java:786) I/flutter ( 4270): at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:404) I/flutter ( 4270): at io.github.edufolly.flutterbluetoothserial.BluetoothConnection.connect(BluetoothConnection.java:57) I/flutter ( 4270): at io.github.edufolly.flutterbluetoothserial.BluetoothConnection.connect(BluetoothConnection.java:64) I/flutter ( 4270): at io.github.edufolly.flutterbluetoothserial.FlutterBluetoothSerialPlugin$FlutterBluetoothSerialMethodCallHandler.lambda$onMethodCall$4$io-github-edufolly-flutterbluetoothserial-FlutterBluetoothSerialPlugin$FlutterBluetoothSerialMethodCallHandler(FlutterBluetoothSerialPlugin.java:1007) I/flutter ( 4270): at io.github.edufolly.flutterbluetoothserial.FlutterBluetoothSerialPlugin$FlutterBluetoothSerialMethodCallHandler$$ExternalSyntheticLambda7.r

WhatsApp Image 2024-03-21 at 15 23 03_7c2e5778