27 December 2021 Reading time: 5 min

The story of a bug – native lands: away and back

Rafał Dubel

In the Flutter world, it not infrequent for us to use functionalities which implementation is strictly dependent on the platform on which it runs. There are many examples, such as the hero of today’s story – Blue Tooth, in the wide world known under the nickname of Bluetooth. This gentleman, or rather this technology does not have to be introduced to anyone. At this point it is important to emphasize only the fact that, we used this technology in one of the projects to connect to the physical device.

So much for the introduction. As my favorite chess Youtuber says – “coffee, tea in hand” and off we go. Note – the story contains elements of fantasy and despite numerous descriptions of battles – no programmer, nor keyboard suffered.

A Long, long time ago, and it should be noted that in the world of technology this means about a few months, a notable knight came to us with a request to create an application which, with the help of the Blue Tooth, would be able to configure certain hardware. It doesn’t matter if it’s a piece of armor or a set of ultra-modern glasses. Since we are experienced in the treatment of Damascus Dart code, we decided to use Flutter.

We fired up the project’s magic furnace and started adding commits every now and then. Hardening of the application was going smoothly and every minute we were proudly watching how well new features were working.

And then one day, out of the blue, the Android app runs smoothly, but on iOS it crashes. How is this possible? After all, Flutter works the same way everywhere! What kind of magic is this? No sorcery, just ancient, somewhat forgotten in the world of Flutter, native magic – such that works differently depending on the platform.

Quite a few adepts of the Flutter Guild would be horrified to hear the words of some spell or curse:

1. The characteristic 44A78CE3-E653-4827-8AAD-8A08268056BA of the service 0EF881BC-6EC4-11EA-BC55-0242AC130003 of the peripheral 57FD66C2-0FE4-78CA-D719-F13AC93CECF7 is not writable 

But not us. We have been practicing this magic long enough to fearlessly rise to the challenge and slay a dragon… or a bug, to the delight of the crowd… or a customer.

A council of elders gathered and quickly devised a plan. We would send an emissary to the land of github to seek the tongue, in the region known as flutter_reactive_blue. We began our search. We selected from the contents of our spell the part we thought was most relevant. In our case it was: “is not writable”. Taking advantage of github we look for the phrase in question. And here it was, in one of the books we found a mention of our spell. I quickly opened it and we saw that it was written in Swift. Here we were a little glad, that it wasn’t the ancient language Objective-C, although even with that we would cope with ease. We returned to the book. On the last page, at the very bottom of it we found the contents of the spell:

1. case .notWritable(let qualifiedCharacteristic):
2. return "The characteristic \(qualifiedCharacteristic.id) of the service \(qualifiedCharacteristic.serviceID) of the peripheral \(qualifiedCharacteristic.peripheralID) is not writable"
3. }

All that remained was to find the location of it, that is of the a spell, invocation. We quickly found two invocations in the same book:

1. guard characteristic.properties.contains(.write)
2. else { throw Failure.notWritable(qualifiedCharacteristic) }
1. guard characteristic.properties.contains(.writeWithoutResponse) 2. else { throw Failure.notWritable(qualifiedCharacteristic) }

We already knew what to look for, now the time was to use the compiling vehicle. We fired up Xcode. We found the two calls in the code and inserted breakpoints. We added a strand from the unicorn’s mane and ran the compilation. With a flash of a lightning (such an association – there is a storm outside the window just now 😉 ) we moved to the place where Dragon-Bug was found. We clicked … and there it was. The code was stopping exactly where we expected it to.

With the flight of another lightning we jumped over the next lines of code and here it was. The second call we found earlier turned out to be a hit. We could see that the Swift guard detected and thwarted all attempts to misuse the device’s peripherals.

1. guard characteristic.properties.contains(.writeWithoutResponse)
2. else { throw Failure.notWritable(qualifiedCharacteristic) }

Well, it doesn’t work – we know where, but we don’t know why. We could see that there was some characteristic that did not have the right properties. So let’s check what properties this characteristic has! What appeared before our eyes was a value that did not explain much.

Let’s make sure what we expect by checking the value of .writeWithoutResponse. In the huge book we call documentation we can see a mention:

1. static var writeWithoutResponse: CBCharacteristicProperties { get }

Let’s make sure what we expect by checking the value of .writeWithoutResponse. In the huge book we call documentation we see a mention:

1. CBCharacteristicPropertyWriteWithoutResponse = 0x04

We know that the characteristic we are using has the value of 4. Let’s find out what characteristic has the value of 10. Let no one be surprised by the fact that there is no such characteristic that would have the value of 10. Already as a young adept of magic, in the mage’s guild, we learn about bits and bit masks. Using this knowledge we can write the value of 10 as 00001010. The individual bits, set to 1, correspond to the numbers 2 and 8 – which gives a total of 10. On Merlin’s beard! we have it and let’s say it loudly: None of the available device characteristics has a value of 4, which corresponds to the characteristic we are using. So let’s see what characteristics are hidden under the values 2 and 8.

1. CBCharacteristicPropertyRead = 0x02
2CBCharacteristicPropertyWrite = 0x08

Guided by experience and aided by the result of a K20 dice roll, we select for further testing:

1. CBCharacteristicPropertyWrite = 0x08

It works!

We are having a little feast. One would like to write that there was no end to the dancing. Unfortunately, scouts report that on the eastern borders someone has started attacking our queries on the overseas servers. We mount our horses, it’s time to move on.

More inspiring knowledge

Main base

Konarskiego 18C
44-100 Gliwice

Contact us


VAT EU: PL6312680249
+48 725 733 380

Privacy Policy
© Copyright 2021 by appvinio.