I can not connect to the BLE device using Plugin.BLE

Hello!
I am trying to connect to a BLE device and read its services on android, but I get an empty list, although I am sure that there are services. I think that there is a problem at the connection stage. Here is a snippet of my code
`
private async void StartScann()
{
if (_bluetoothBLE.State != BluetoothState.Off)
{
_adapter.ScanTimeout = 10000;
_adapter.ScanMode = ScanMode.Balanced;

            _adapter.DeviceDiscovered += (obj, a) =>
            {
                if(obj == null || a == null || a.Device == null || a.Device.Name == null)
                {
                    return;
                }

                if (a.Device.Name.Contains("170"))
                {
                    _device = a.Device;
                    _bluetoothBLE.Adapter.ConnectToDeviceAsync(_device, new Plugin.BLE.Abstractions.ConnectParameters(true, true));
                    //try
                     //{
                        _adapter.ConnectToDeviceAsync(_device, new Plugin.BLE.Abstractions.ConnectParameters(true, true));
                     //}
                     //catch (Exception e)
                     //{
                     // System.Diagnostics.Debug.WriteLine(e.Message);
                     //}
                    await Task.Delay(2000);

        //try
                //{                 
                    IReadOnlyList<IService> services= _device.GetServicesAsync().Result; // Count == 0
                    //}
                //}
                //catch (Exception e)
                //{
                //  System.Diagnostics.Debug.WriteLine(e.Message);
                //}                       
            };

            await _adapter.StartScanningForDevicesAsync();
        }
    }`

Log:
11-25 12:58:33.287 D/BluetoothDevice( 3396): getName: name = 170 11-25 12:58:33.311 D/BluetoothManager( 3396): getConnectionState() 11-25 12:58:33.311 D/BluetoothManager( 3396): getConnectedDevices 11-25 12:58:33.357 D/BluetoothGatt( 3396): connect() - device: 00:16:A4:72:##:##, auto: true 11-25 12:58:33.357 D/BluetoothGatt( 3396): registerApp() 11-25 12:58:33.357 D/BluetoothGatt( 3396): registerApp() - UUID=d1668c3d-6793-####-80cd-e1b1cf98efe5 11-25 12:58:33.360 D/BluetoothGatt( 3396): onClientRegistered() - status=0 clientIf=7 11-25 12:58:34.690 D/BluetoothGatt( 3396): onClientConnectionState() - status=0 clientIf=7 device=00:16:A4:72:##:## Thread started: #8 Thread started: <Thread Pool> #9 Thread started: <Thread Pool> #10 Thread started: <Thread Pool> #11 Thread started: <Thread Pool> #12 11-25 12:58:53.319 D/BluetoothDevice( 3396): getName: name = 170 Thread started: <Thread Pool> #13 Thread started: <Thread Pool> #14 Thread started: <Thread Pool> #15 Thread started: <Thread Pool> #16 11-25 12:58:53.370 D/BluetoothGatt( 3396): discoverServices() - device: 00:16:A4:72:##:## 11-25 12:58:53.378 D/BluetoothGatt( 3396): onClientConnectionState() - status=19 clientIf=7 device=00:16:A4:72:##:## 11-25 12:58:53.392 D/BluetoothGatt( 3396): close() 11-25 12:58:53.392 D/BluetoothGatt( 3396): unregisterApp() - mClientIf=7 11-25 12:58:53.436 D/BluetoothGatt( 3396): onClientConnectionState() - status=0 clientIf=7 device=00:16:A4:72:##:## 11-25 12:58:53.437 W/BluetoothGatt( 3396): Unhandled exception in callback 11-25 12:58:53.437 W/BluetoothGatt( 3396): java.lang.NullPointerException: Attempt to invoke virtual method 'void android.bluetooth.BluetoothGattCallback.onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)' on a null object reference 11-25 12:58:53.437 W/BluetoothGatt( 3396): at android.bluetooth.BluetoothGatt$1.onClientConnectionState(BluetoothGatt.java:187) 11-25 12:58:53.437 W/BluetoothGatt( 3396): at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:70) 11-25 12:58:53.437 W/BluetoothGatt( 3396): at android.os.Binder.execTransact(Binder.java:570) 11-25 12:58:53.439 D/BluetoothGatt( 3396): onSearchComplete() = Device=00:16:A4:72:##:## Status=0 11-25 12:58:53.441 W/BluetoothGatt( 3396): Unhandled exception in callback 11-25 12:58:53.441 W/BluetoothGatt( 3396): java.lang.NullPointerException: Attempt to invoke virtual method 'void android.bluetooth.BluetoothGattCallback.onServicesDiscovered(android.bluetooth.BluetoothGatt, int)' on a null object reference 11-25 12:58:53.441 W/BluetoothGatt( 3396): at android.bluetooth.BluetoothGatt$1.onSearchComplete(BluetoothGatt.java:245) 11-25 12:58:53.441 W/BluetoothGatt( 3396): at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:103) 11-25 12:58:53.441 W/BluetoothGatt( 3396): at android.os.Binder.execTransact(Binder.java:570)
For a long time I try to solve a problem, maybe someone can tell me something
P.S. the BLE transmitter of the device with which I connect says there that they are connected to it and immediately disconnect

Tagged:

Best Answer

  • dmitry911dmitry911 ✭✭
    Accepted Answer

    I will describe how I solved my problem
    The code from the tutorial helped me a little. but after reading many articles, I drew up for myself a number of important aspects. Before connecting to the device, you need to stop scanning. A connection is best run in a UI stream. And finally, the ConnectToKnownDeviceAsync method works more stable for me than ConnectToDeviceAsync. An example of my piece of code with a connection
    ``
    public async Task Connect()
    {
    Device.BeginInvokeOnMainThread(async () =>
    {
    await _adapter.StopScanningForDevicesAsync();
    try
    {
    await _adapter.ConnectToKnownDeviceAsync(_deviceGuid);
    }
    catch (Exception e)
    {
    System.Diagnostics.Debug.WriteLine("BluetoothLeAdapterMobile.Connect ошибка подключения по Guid "
    + _deviceInfo.Name + ": " + e.Message);
    _connectQueue.Remove(_deviceInfo.Name);
    return;
    }

                _device = _adapter.ConnectedDevices.Where(x => x.Id == _deviceGuid)
                    .LastOrDefault();
                if (_deviceGuid == null)
                {
                    System.Diagnostics.Debug.WriteLine("BluetoothLeAdapterMobile.Connect"
                        + _deviceInfo.Name + "ошибка соединения BLE - _device был null");
                    ConnectFailed();
                    return;
                }
                await Initialize();
            });
        }
    

    ``

    ``
    private async Task Initialize()
    {
    try
    {
    _targetService = await _device.GetServiceAsync(Guid.Parse(_serviceGuid));

                var serv = await _targetService.GetCharacteristicsAsync();
                foreach(var ch in serv)
                {
                    System.Diagnostics.Debug.WriteLine(ch.Id);
                }
    
                _writeCharacteristic = await _targetService.GetCharacteristicAsync(Guid.Parse(_writeCharacteristicGuid));
                _readCharacteristic = await _targetService.GetCharacteristicAsync(Guid.Parse(_readCharacteristicGuid));
                _readCharacteristic.ValueUpdated += (o, args) =>
                {
                    DataReceived?.Invoke(args.Characteristic.Value);
                };
    
                await _readCharacteristic.StartUpdatesAsync();
                ConnectSucceed(); // event
            }
            catch(Exception e)
            {
                System.Diagnostics.Debug.WriteLine("BluetoothLeAdapterMobile.Connect " 
                    + _deviceInfo.Name + " ошибка инициализации: " + e.Message);
                await Disconnect();
            }
        }
    

    ``
    I use the Connect method at a higher level of abstraction in a loop with a cancellation token until I get ConnectSucceed and am pretty quickly successful, although not always the first time

Answers

  • dmitry911dmitry911 Member ✭✭

    constructor
    ` private IAdapter _adapter;
    private IBluetoothLE _bluetoothBLE;

        public BluetoothScannerMobile()
        {
            _bluetoothBLE = CrossBluetoothLE.Current;
            _adapter = CrossBluetoothLE.Current.Adapter;
        }`
    
  • JarvanJarvan Member, Xamarin Team Xamurai
    edited November 2019

    Here is a guide that demonstrates Integrate and use the BLE Plugin for Xamarin. Below is the code about BLE connection, try to test on your side.

    private async void btnConnect_Clicked(object sender, EventArgs e)
    {
        try
        {
            if (device != null)
            {
                await adapter.ConnectToDeviceAsync(device);
    
            }
            else
            {
                DisplayAlert("Notice", "No Device selected !", "OK");
            }
        }
        catch (DeviceConnectionException ex)
        {
            //Could not connect to the device
            DisplayAlert("Notice", ex.Message.ToString(), "OK");
        }
    }
    
    private async void btnKnowConnect_Clicked(object sender, EventArgs e)
    {
    
        try
        {
            await adapter.ConnectToKnownDeviceAsync(new Guid("guid"));
    
        }
        catch (DeviceConnectionException ex)
        {
            //Could not connect to the device
            DisplayAlert("Notice", ex.Message.ToString(), "OK");
        }
    }
    
  • dmitry911dmitry911 Member ✭✭

    @Jarvan My connection algorithm as a whole does not give up on the example in the tutorial

  • dmitry911dmitry911 Member ✭✭
    Accepted Answer

    I will describe how I solved my problem
    The code from the tutorial helped me a little. but after reading many articles, I drew up for myself a number of important aspects. Before connecting to the device, you need to stop scanning. A connection is best run in a UI stream. And finally, the ConnectToKnownDeviceAsync method works more stable for me than ConnectToDeviceAsync. An example of my piece of code with a connection
    ``
    public async Task Connect()
    {
    Device.BeginInvokeOnMainThread(async () =>
    {
    await _adapter.StopScanningForDevicesAsync();
    try
    {
    await _adapter.ConnectToKnownDeviceAsync(_deviceGuid);
    }
    catch (Exception e)
    {
    System.Diagnostics.Debug.WriteLine("BluetoothLeAdapterMobile.Connect ошибка подключения по Guid "
    + _deviceInfo.Name + ": " + e.Message);
    _connectQueue.Remove(_deviceInfo.Name);
    return;
    }

                _device = _adapter.ConnectedDevices.Where(x => x.Id == _deviceGuid)
                    .LastOrDefault();
                if (_deviceGuid == null)
                {
                    System.Diagnostics.Debug.WriteLine("BluetoothLeAdapterMobile.Connect"
                        + _deviceInfo.Name + "ошибка соединения BLE - _device был null");
                    ConnectFailed();
                    return;
                }
                await Initialize();
            });
        }
    

    ``

    ``
    private async Task Initialize()
    {
    try
    {
    _targetService = await _device.GetServiceAsync(Guid.Parse(_serviceGuid));

                var serv = await _targetService.GetCharacteristicsAsync();
                foreach(var ch in serv)
                {
                    System.Diagnostics.Debug.WriteLine(ch.Id);
                }
    
                _writeCharacteristic = await _targetService.GetCharacteristicAsync(Guid.Parse(_writeCharacteristicGuid));
                _readCharacteristic = await _targetService.GetCharacteristicAsync(Guid.Parse(_readCharacteristicGuid));
                _readCharacteristic.ValueUpdated += (o, args) =>
                {
                    DataReceived?.Invoke(args.Characteristic.Value);
                };
    
                await _readCharacteristic.StartUpdatesAsync();
                ConnectSucceed(); // event
            }
            catch(Exception e)
            {
                System.Diagnostics.Debug.WriteLine("BluetoothLeAdapterMobile.Connect " 
                    + _deviceInfo.Name + " ошибка инициализации: " + e.Message);
                await Disconnect();
            }
        }
    

    ``
    I use the Connect method at a higher level of abstraction in a loop with a cancellation token until I get ConnectSucceed and am pretty quickly successful, although not always the first time

Sign In or Register to comment.