After the App is killed by the user, if there is a way to resume the previous BLE connection after ibeacon waking up?
In my iPhone application, I could manage to wake up the app using iBeacon after the App is killed by the user. I could trigger local notifications during the wake-up period, but when it comes to BLE related tasks not there is no response at all. No scan callback no connect callback.
Edit:
The BLE background is enabled.
It scans for a peripheral with the identifier that is previously bonded with iPhone. The identifier is store in Userdefaults.
For pending connection, when the App is killed, it will call the disconnect callback. No pending connection I guess.
I haven't config the BLE state restoration yet.
Thanks Paulw11 and Prakash Shaiva
After exploring more documents online, here is the answer:
In my case, I want to wake up the App after being killed by users. And build a connection with a previously bonded BLE device.
First thing I learn
When iOS App is waken up by ibeacon, it will not call willRestoreState callback. In other word, App cannot restore connection from state restoration support. But we could attempt to build new connection instead.\
willRestoreState callback calls when your App is killed by iOS system.
Conditions for Bluetooth State Restoration to relaunch your app
See answer from Apple
Second thing I learn
In order to build new connection during the wake up period, an array of service UUIDs that you're instersted in need to be added to func scanForPeripherals(withServices serviceUUIDs: [CBUUID]?, options: [String : Any]? = nil), otherwise the random scan will be stopped by iOS itself.
Related
Maybe someone ever solve the problem with stable connection to server when application is in background? I need to transfer audio data from server to client app.
I know about all hacks for iOS how to keep alive application, but I need legal methods to solve this problem. Maybe you have any idea?
I found that I can send VoIP push to device that will wakeup my app and then establish tcp connect to my server but this socket will be keep alive about 30 seconds (as I see in log, every 3 seconds fires timer in iOS app that send data to server) this is not enough for me.
Maybe this project https://github.com/SmallSharpToolsOpenSource/Speakerbox will be helpful for someone.
And this video https://www.youtube.com/watch?v=lXJ1LDjL4Os
And official answer from Apple tech support:
PushKit is how voip apps can
reliable receive silent notifications, while CallKit is basically a UI
framework voip apps can use to notify the user about calls. Note that there
is NOT any direct connection within the APIs- for example, a voip app can
generate a local notification (instead of using CallKit) or simply do nothing
and “ignore” the notification entirely. Similarly, a voip app could “fake” a
call at anytime by simply telling CallKit that there was an incoming call (our
sample code for CallKit did exactly this).
Anything your app could previously have done when
it received voip socket traffic, it could also do when it received a PushKit
notification.
Standard voip apps
actually operate in two COMPETELY unrelated “modes”:
1) While waiting for an incoming call, the app is suspended until “something”
(PushKit OR a voip socket) wakes the app to tell it about the call.
2) Once a call has started, the app has an active audio session and is relying
an the standard “background audio” behavior of iOS, just like a wide variety
of other audio apps (for example, any streaming music app).
As per apple documents apps running in background cannot receive callbacks except for apps which are location based, VOIP, Newstand, Music player or APNS enabled.
How to receive the connection status callbacks in that case?
The app is making use of AVAudioSession instance as:
try! AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord, with:AVAudioSessionCategoryOptions.allowBluetooth)
And listens to notifications as:
NotificationCenter.default.addObserver(self,selector:#selector(handleRouteChange), name: .AVAudioSessionRouteChange,object: AVAudioSession.sharedInstance())
This is called in the launch of the application.
You can use the bluetooth-central background mode. According to Background modes documentation
(...) new data arriving from the peripheral causes the system to wake up the app so that it can process the data. The system also wakes up the app to process accessory connection and disconnection notifications.
As you know, after some period of inactivity, a Bluetooth device will disconnect from an iPhone. The user will then have to go back to Settings in order to reconnect the device.
1 - Is it possible for an iOS app (when it enters foreground) to force the reconnection to a paired Bluetooth device, without any user input?
2 - Is it possible to force the reconnection to a paired Bluetooth device, but during an app wake-up state from an iBeacon signal (matching UUID)?
Yes, you can use CoreBluetooth APIs to connect to a Bluetooth LE device without user input. It doesn't have to be "paired" in the same way as a Bluetooth Classic device. To do this, the Bluetooth LE device should expose a GATT Service UUID that the mobile app can recognize, and when it discovers this Service UUID, it can simply connect programatically.
When you use CoreLocation APIs to wake up your app based on iBeacon detections, the app is launched into the background temporarily. You can send a local notification to the user to try to get the user to tap on it and bring the app to the foreground, but if the user does not, app background rules still apply.
Bringing together #1 and #2, you should understand the rules Apple places on using CoreBluetooth in the background. See Apple's docs for The bluetooth-central Background Execution Mode. It would be possible to make a connection in the background if you get the proper app permissions.
I have the task.
My iOS app must send heartbeat messages to the server once for every 10 minutes.
iOS app must do this always when the app is not killed (i.e. terminated i.e. removed from task manager) despite the screen is locked, the app in the background.
I'm trying to do this using "background location". But if I use CLLocationUpdate in its' usual mode - I get my battery drained.
Could you help me?
You are out of luck, this is not possible on iOS. Yes you can use the location manager, but if I set a my desk for an hour your app will not get a location update.
Also it is misusing the background location mode and might get your app rejected.
An option can be to use silent push notification, you server will send a silent push to the device where the device will respond to it in the background.
Read more about
application:didReceiveRemoteNotification:fetchCompletionHandler: and the Local and Remote Notification Programming Guide.
What I want to do is to notify user from background that something happened. On iOS device this is done using UILocalNotification. I also have an app on pebble watch to which I send a notification and user can interact with it.
The issue is that starting with iOS 8 pebble also shows all notifications from Notification Center, this way the notification gets duplicated.
To make things worse, pebble actually creates two different connections: (1)a simple Bluetooth link for normal communication and (2) a BluetoothLE for ANCS service: this means that the watch can be "connected" but no connection for ANCS services is established.
Is there a way to determine this, so that I don't send the notification manually if pebble already receives it from ANCS services?
p.s. I do check if the device has BLE (using CBCentralManager), so this partially solves the issue - I send manually the notification for the devices that don't support BLE at all.