retrieveConnectedPeripheralsWithServices and retrievePeripheralsWithIdentifiers return an empty array - ios

I have two apps running one on OSX and one on iOS. A bluetooth connection is established between them using the CoreBluetooth framework, and support for background capabilities for the iOS app has been added. This is working perfectly fine, and communication with the iOS app in the background still works even after a while in the background.
However, when the iOS device goes out of range, I have to use retrievePeripheralsWithIdentifiers to re-connect when the device is back in range since the app is in the Background and therefore I cannot scan for it as its UUID would not be advertised (as mentioned in Core Bluetooth Background Processing for iOS Apps). I tried using retrieveConnectedPeripheralsWithServices with the iOS app in the foreground to figure what the problem is, but the function is always returning an empty array, although the connection is already established. For the former case, I am passing my custom service CBUUID object as specified in the documentation:
let connectedPeripherals = centralManager!.retrieveConnectedPeripheralsWithServices([CBUUID(string: "109F17E4-EF68-43FC-957D-502BB0EFCF46")])
Trying to get the peripheral to re-connect to the OSX app while it's in the background, using
let peripherals = centralManager!.retrievePeripheralsWithIdentifiers([NSUUID(UUIDString: "109F17E4-EF68-43FC-957D-502BB0EFCF46")!])
as per the documentation also yields an empty array. Also to mention that I tried this function with the iOS app in the foreground but also to no avail.
Any idea what could possibly be going wrong here?

Related

How to deliver a BLE message to an iOS app that isn’t running?

I am working on a device that sends a message/signal to an iOS app via BLE. It currently works fine if the app is running in the foreground or background; however, I need the device to deliver this signal to the app when it isn’t running so it can process it, in essence, “waking it up.”
A device that seems to be doing this well is Tile (used to keep track of keys, etc.). The Tile can signal the phone even when the Tile app isn’t running, making the Tile app come up and sound an alarm. My use case isn’t the same, but I need to achieve the same behavior.
Does anyone have any pointers as to how to achieve this? The OS needs to launch/wake the app upon receiving this BLE message/signal from my device.

didDiscoverPeripheral: not working sometimes on background

Happens both on iOS 12 & iOS 13.
I have Bluetooth-central correctly added on my Info.plist
I'm specifying a list of service UUIDs
What I am seeing:
If I interact with our BLE device on the foreground, I can still scan for it on background, even hours and days later, as long as I don't turn off Bluetooth or restart the iOS device.
If I have never interacted with it while the app is open, or If I restart the device, or turn off Bluetooth on the device, then when scanning in the background, didDiscoverPeripheral: never gets called, until I open the app, which triggers didDiscoverPeripheral: instantly.
If I use retrievePeripheralsWithIdentifiers: and iOs can return the object "cached" then I can skip the scan and connect directly, which works perfectly. But sometimes retrievePeripheralsWithIdentifiers: doesn't return the object so I can't always relay on that (And forces the user to interact with our device on the foreground first)
So, after quite a bit of back and forth between me and our firmware team, we found the reason behind our problems.
Turns out, apps on background when scanning won't read the advertisement extended packet. The problem was, the service UUID we were using to filter the scan for our devices was only being sent on that advertisement extended packet.
For this reason, when the app was scanning a new device, it would not find anything with that service UUID, but once it had found it with the app open, it would cache it internally with its services, and from that point it would work even while on background (because it already knows what services that device has).
The fix was to include that service UUID on the first advertisement packet.

Connect to a backgrounded iOS app acting as a peripheral from a macOS app

I have an iOS and macOS app that make heavy use of Core Bluetooth. The core functionality of the app involves having a central device (CBCentralManager) connect to a peripheral device (CBPeripheralManager), retrieve some data, then disconnect. Either device, whether macOS or iOS can act as either a central or peripheral depending on who needs the data.
At first I thought there was an issue with my code, but after testing the app with two iOS devices, one is able to connect and extract data from the peripheral device even when the peripheral device is locked and the app is in the background. Now according to the docs concerning background advertising on iOS under "The bluetooth-peripheral Background Execution Mode" this is kind of expected:
...they can be discovered only by an iOS device that is explicitly scanning for them.
Is there any way to have a macOS app discover peripherals even when they're backgrounded? I'm sure the code I've written is correct because it's the same across iOS and macOS.
Update 1
I believe that this might be possible just unsure how to approach the issue. Using Apple's Bluetooth Explorer on macOS, I am able to find the desired device AND I'm able to see and read data for my custom service.
This finding is validated from logs from my iOS device about the read requests which are from my peripheralManager(CBPeripheralManager, didReceiveRead: CBATTRequest).

iOS CoreBluetooth - Peripheral connect to Central within range

I have a basic BLE App that I am running with Objective-C. I am using PeripheralManager and running my iPhone8 as a peripheral with serivces, characteristics added.
What I would like to do is connect to a central device that I know by Device ID or when it comes within range.
I have written a BLE App for Android that does this now. All I have to do is trigger the device.connectGatt() when onConnectionStateChange() is connected. This is in the BluetoothGattServerCallback() eventHandler.
What is the equivant for this in iOS? Keep in mind I that this is at connected state, not when the central has subscribed for services. This seems obvious in BluetoothGatt on Android but not see anything obvious in iOS PeriphalManager.
Anyone done anything similar? Seems to be a basic question, please help.
In CoreBluetooth it is the central that makes the connection.
If you know the device-specific identifier for a peripheral (ie, you have previously discovered it on this central device) then you can attempt to retrieve a CBPeripheral instance from the central and then issue a connect. This will complete when the device comes into range. If you allow background mode then this connect can be completed when your app is in the background.

Communicating with a Bluetooth Classic device in iOS when the app is in the background?

I'm working on iOS development for a bluetooth peripheral. We want the (already paired) device to connect when a button is pressed on it, and this will cause the app to execute some code. Is it possible for the app to detect that the device is connected, even while in the background?
Also, is it possible for the app to bring itself into the foreground when this is detected? Would I need to be a member of the MFi program to do either of these things?
You will be able to detect that the device is connected in the background using Bluetooth 2.0, however you must include the App communicates with an accessory string under Required Background Modes in the app's plist.
So yes, the first part of your question is doable. However when you say: "We want the (already paired) device to connect when a button is pressed on it", it is important to note that this functionality must be built into the device's firmware. The app can always be searching for it, but the device will not be able to communicate with the phone until it connects. Therefore, the button must wake up the device and signal that it now wants to connect.
For the third part of your question, you will not be able to bring the app into the foreground without the user opening the app.
Btw, CoreBluetooth is the Bluetooth Low Energy framework for iOS. It is completely different from Bluetooth 2.0.
as ttarules told you iphone can't connect automaticly to a paired device.
I don't know what kind of bluetooth receiver have you in your device but generally you can set up a method of "AUTOCALL" that automatically call a paired device (in this case an iPhone).
When you (your iPhone) come around the device it automatically establish a connection!
If you set all the parameters correctly in the bluetooth module you can make sure that the iPhone shows a message like this: "YourDevice would like access to YourApplication" when the connection is established.
this way helps the user to use your application and you can run the code you mentioned above when the app start.

Resources