I was trying to keep the answer short. That’s why I said it’s “supposed to attempt pairing” :-)
Here’s the long version: the only way a peripheral can signal to initiate a pairing flow is by returning Insufficient Auth when an app tries to retrieve, read, or write a characteristic. If there’s an error or if the user taps on ‘Cancel’ on the pair dialog an error value is returned in the delegate.
For a read operation it would be in the didUpdateValueForCharacteristic delegate method. For a write in didWriteValueForDescriptor delegate. If the GATT descriptor is set up as protected then the error may also come back in didDiscoverDescriptorsForCharacteristic or in didUpdateNotificationStateForCharacteris after trying to set a characteristic for notification. An app should always check those error values and handle them properly.
My own experience has been that if iOS thinks it’s paired but the device isn’t it *may* put up the pairing dialog. That seems to vary depending on how far each side got in the key exchange process, whether they’re pairing or bonding, whether the pairing is set up for Just Works or MITM prevention,or sometimes even on the BLE module (TI vs. Nordic). But there’s no easy way to tell on the phone side what happened. I’ve found it best to try a few times on the app side then if it’s still returning an error signal the user and try to start with a clean slate.
The safest bet is if any of these methods return a non-nil error value then the app can choose to either try it again (which *might* force the pair dialog to pop up again) or the app could alert the user that the pairing has failed and they should take action.
Unfortunately, the user instructions have to be pretty generic if things didn’t work out. Along the lines of: “Connection failed, please restart your device and go to Bluetooth Settings and Forget device then try pairing again” — blech.
If someone has a better suggestion on how to handle pairing failures I’d be interested in hearing about it.
On August 24, 2016 at 6:05:29 PM, Roland King (email@hidden) wrote:
On 25 Aug 2016, at 07:32, Ramin Firoozye < email@hidden>
wrote:
AFAIK there’s no way to force the equivalent of a ‘Forget
Device’ from the app level. iOS is supposed to attempt pairing if a
characteristic in the GATT returns with an insufficient
authentication status. If the phone was paired and is now not
paired any more, you could try accessing a known characteristic in
the app and by doing so it returns insufficient auth and forces the
device and the phone to go through the pairing process again.
I don’t think that’s actually correct, not in my experience anyway.
If iOS thinks it’s already paired with a device I’ve only ever seen
it attempt to use the stored key, I’ve never made it re-pair no
matter what I send. Sending insufficient authentication just gets
it to try and encrypt the link again with the same stored key.
Similarly having the peripheral request encryption does the same
thing. I’ve found no solution other than to forget the device in
iOS.
On August 24, 2016 at 3:10:12 PM, Ben Levitt (email@hidden)
wrote:
Hello,
We have an app that talks (as a central) to a bluetooth peripheral
that we control. Our peripheral can only store pairing/bonding data
for the 2 most recently connected devices, so it's very possible
that a given iOS device that has previously paired (and thinks it
is still paired) to our peripheral, can try to connect, and be
denied access when the peripheral no longer has pairing data for
this iOS device.
At that point, is there any way for the iOS device to recognize
this problem, and clear this peripheral from its list of paired
devices? I hear rumors that this works in some apps. I don't know
of a way to do this programmatically. Am I missing something? Or is
there something we can set up differently on our peripheral so that
the iOS device will recognize this problem and re-request pairing
itself?
Thanks very much!
Ben
|