dotnet-bluetooth-le: MainThread: Android Exception: GATT Write Characteristic Failed

Intermittent issue, after BT connection is complete, I attempt to write to a characteristic on the remote device, and in some instances (approx 50% of the time), an exception is thrown.

Steps to reproduce

  1. Scan for available BT devices
  2. Connect to device
  3. GetServiceAsync for a specific characteristic
  4. Assign event handler for ValueUpdated event for that characteristic
  5. If characteristic CanUpdate is true, StartUpdatesAsync
  6. Attempt to write data to that characteristic using WriteAsync

Expected behavior

Data is successfully written to the characteristic. In this case, this is the method of transparent data communication between the app and the BT device.

Actual behavior

An exception occurs in approximately 50% of connections

Crashlog

[mono] Unhandled Exception: [mono] Plugin.BLE.Abstractions.Exceptions.CharacteristicReadException: Gatt write characteristic FAILED. [mono] at Plugin.BLE.Android.Characteristic.InternalWrite (System.Byte[] data) [0x0004a] in C:\Users\Adrian\Documents\GitHub\xamarin-bluetooth-le\Source\Plugin.BLE.Android\Characteristic.cs:99 [mono] at Plugin.BLE.Android.Characteristic+<>c__DisplayClass19_0.<WriteNativeAsync>b__0 () [0x00000] in C:\Users\Adrian\Documents\GitHub\xamarin-bluetooth-le\Source\Plugin.BLE.Android\Characteristic.cs:75 [mono] at Plugin.BLE.Abstractions.Utils.TaskBuilder+<FromEvent>d__13[TReturn,TEventHandler,TRejectHandler].MoveNext () [0x000b3] in C:\Users\Adrian\Documents\GitHub\xamarin-bluetooth-le\Source\Plugin.BLE.Abstractions\Utils\TaskBuilder.cs:50 [mono] --- End of stack trace from previous location where exception was thrown --- [mono] at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143 [mono] at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00047] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:187 [mono] at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:156 [mono] at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:128 [mono] at System.Runtime.CompilerServices.TaskAwaiter1[TResult].GetResult () [0x00000] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:357 [mono] at Plugin.BLE.Android.Characteristic+<WriteNativeAsync>d__19.MoveNext () [0x00097] in C:\Users\Adrian\Documents\GitHub\xamarin-bluetooth-le\Source\Plugin.BLE.Android\Characteristic.cs:74 [mono] — End of stack trace from previous location where exception was thrown — [mono] at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143 [mono] at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00047] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:187 [mono] at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:156 [mono] at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:128 [mono] at System.Runtime.CompilerServices.TaskAwaiter1[TResult].GetResult () [0x00000] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:357 [mono] at Plugin.BLE.Abstractions.CharacteristicBase+<WriteAsync>d__31.MoveNext () [0x0006c] in C:\Users\Adrian\Documents\GitHub\xamarin-bluetooth-le\Source\Plugin.BLE.Abstractions\CharacteristicBase.cs:91 [mono] --- End of stack trace from previous location where exception was thrown --- [mono] at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionse [mono-rt] [ERROR] FATAL UNHANDLED EXCEPTION: Plugin.BLE.Abstractions.Exceptions.CharacteristicReadException: Gatt write characteristic FAILED. [mono-rt] at Plugin.BLE.Android.Characteristic.InternalWrite (System.Byte[] data) [0x0004a] in C:\Users\Adrian\Documents\GitHub\xamarin-bluetooth-le\Source\Plugin.BLE.Android\Characteristic.cs:99 [mono-rt] at Plugin.BLE.Android.Characteristic+<>c__DisplayClass19_0.<WriteNativeAsync>b__0 () [0x00000] in C:\Users\Adrian\Documents\GitHub\xamarin-bluetooth-le\Source\Plugin.BLE.Android\Characteristic.cs:75 [mono-rt] at Plugin.BLE.Abstractions.Utils.TaskBuilder+<FromEvent>d__13[TReturn,TEventHandler,TRejectHandler].MoveNext () [0x000b3] in C:\Users\Adrian\Documents\GitHub\xamarin-bluetooth-le\Source\Plugin.BLE.Abstractions\Utils\TaskBuilder.cs:50 [mono-rt] — End of stack trace from previous location where exception was thrown — [mono-rt] at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143 [mono-rt] at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00047] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:187 [mono-rt] at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:156 [mono-rt] at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:128 [mono-rt] at System.Runtime.CompilerServices.TaskAwaiter1[TResult].GetResult () [0x00000] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:357 [mono-rt] at Plugin.BLE.Android.Characteristic+<WriteNativeAsync>d__19.MoveNext () [0x00097] in C:\Users\Adrian\Documents\GitHub\xamarin-bluetooth-le\Source\Plugin.BLE.Android\Characteristic.cs:74 [mono-rt] --- End of stack trace from previous location where exception was thrown --- [mono-rt] at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143 [mono-rt] at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00047] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:187 [mono-rt] at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:156 [mono-rt] at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:128 [mono-rt] at System.Runtime.CompilerServices.TaskAwaiter1[TResult].GetResult () [0x00000] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:357 [mono-rt] at Plugin.BLE.Abstractions.CharacteristicBase+<WriteAsync>d__31.MoveNext () [0x0006c] in C:\Users\Adrian\Documents\GitHub\xamarin-bluetooth-le\Source\Plugin.BLE.Abstractions\CharacteristicBase.cs:91 [mono-rt] — End of stack trace from previous location where exception was thrown — [mono-rt] at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/exceptionserv

Configuration

Version of the Plugin: 1.2.1

Platform: Android 7.1.1

Device: Google Pixel

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 15

Most upvoted comments

If any method which calls Device.BeginInvokeOnMainThread(async() => { await SendData(data);}); gets called again (like on appear) you will get the threading issue and subsequently the error. You should make sure that your code always completes a ble task before invokeing the next.

I was thinking of introducing a helper class, a serial queue which could be used to guarantee that async tasks called by using it are executed serially. I could also implement the main thread logic in there. This might help developers avoid this limitation.

I will add this as a hint in the readme