Watch Connectivity: Transfer user info when phone not nearby - ios

I am trying to transfer data from Apple Watch to iOS. I use transferUserInfo to do so. It is very likely that, when I call that method, the phone is not nearby (and therefore not reachable).
As far as I understood the documentation, the user info should be queued and delivered to the phone by Watch Connectivity when the phone becomes reachable again. This does not seem to be true for me, instead my session delegate's session(didFinish:error:) gets called with a Transfer timed out. error.
This is bad since that means the watch app and iOS app need to be active at the same time in order for iOS to receive the latest info. Is this expected behaviour, and is there any way to fix this?
I know that application context might have the behaviour I need, but the message size for application context is pretty limited, which might be an issue for me if the iOS app is not opened for a while (I am transferring workouts, so they might accumulate on the watch).

Related

Reliable periodic URL fetch from iOS app

We have been looking for a reliable way to periodically get data from a URL from an iOS app, regardless of the state of execution of the app on the device (foreground, background, suspended or terminated/force-quit).
We have gone through all the questions on this topic that are on this site, and their answers, as well as all the relevant iOS documentation from Apple and blog posts we can find on the subject. But, we have not yet found a solution that will work.
Here is what has been considered/implemented:
Background fetch - This is our current implementation. It works at the whim of the OS as far as the frequency and timing of the fetch goes, and only when the app is not "terminated" or "force-quit" by the user. This has been found to be totally unreliable, as the users themselves don't understand the quirks of iOS, and force-quit the app, yet expecting it to function even after that. The app deals with financial information, and thus can result in loss of potential financial gains to the users if the fetches are not performed on a schedule.
Change notifications from the server - this is not an option, as we neither store nor wish to store certain information on a server, for privacy reasons. Therefore, we cannot use this.
Silent notifications from the server to trigger fetch - again, this won't work if the app has been force-quit, as the notifications are not delivered to the app in that state.
PushKit - this is what apps like WhatsApp or Vonage would use to fire the app regardless of its state of execution. However, this is only available to VoIP apps, and we don't fall into that category. Can this still be used by non-VoIP apps? If so, we could settle for this but only as a last resort, as the preferred option is to have it all done from the app without involving a server to generate "empty" push notifications, simply for the purpose of triggering a URL download.
Given the nature of the app and the potential for the user to benefit financially, it seems rather harsh that iOS would not allow a simple operation such as a periodic download of a URL. So, hoping that someone knows how to overcome this challenge.
As an aside, the exact same functionality on Android works like a charm, regardless of the app's state of execution.

Is it possible to interact with ios devices even though app killed?

Is it possible to create an app where the message is automatically sent from one device to another when both the devices are in the same geo-location in predefined range or in the wireless points like Bluetooth?
I think there must be some way to do this. Please let me know if you have any idea about the same.
In peer-peer connection, It is not possible. When the user terminates the app everything goes with it.
But if you connect it with server, you could try to implement the behavior you are looking for with a push notification with content available, which gives you some time awake to download content in the background.

How to check whether force quit has disabled notifications

I am working on an app that, among other things, provides alarms in emergencies. Users can toggle a setting to have alarms be put through even if their iPhone is muted, but this service has another hurdle to leap: when the app has been force quit, it cannot receive (content-available) notifications until the app is relaunched by the user.
There is a geofencing event in place which buys me some processing time even if the app has been force quit, and in that time, I would like to check if such a block is in place, and if so, request the user to open their app again, and not aggressively force-quit in the future. (Many people still think it's just a way to keep things clean, even though it actually costs you battery life to not just leave apps in the background)
SO THE CORE OF THE PROBLEM: I need an (API call? Something else?) that will tell me whether the app is in such a 'force quit, cannot receive notifications' state, assuming that I do have processing time to do this check.
Anything is welcome, I have not been able to find proper Apple documentation on the notifications block.
Thank you very much.
While there is no API I am aware of to find state after, you can infer the state just before the application is terminated, and record that.
Code
applicationDidEnterBackground
will be called when an app has received a terminate signal.
More Info
This question describes what lifecycle functions to use, and

Obtaining Wifi connectivity notification while in background

Is it possible to get notifications about Wifi connectivity state while an iOS app is running in the background? It is looking like a no, but I am also curious if this could be checked during a background fetch routine.
You have limited options to get processor time while in background and as far as I know there is no direct option to be notified on the WiFi status. Here you can find the modes of background execution: apple docs
I have tried with VOIP support to keep a stream opened while the app was in background. Everything worked ok and I was getting connectivity errors when the connection was lost, also I was able to try to reconnect from time to time until the connection was back on.
The only problem is that Apple will not approve the app unless your app provides a VOIP functionality (although the first two versions of the app were approved and only on the third one it got rejected because of flagging VOIP but not actually providing it).
I hope this helps.

Trying to retrieve previously paired bluetooth device in IOS app will not respond with failure if device is off

Sorry for the long title, but we are having a pretty interesting issue with using corebluetooth for ios. We are issuing a call to retrievePeripherals in CBCentralManager and are able to find the previously paired device.
This happens though regardless if the device is on or off though. I can't find anything in apple's documentation as to why it's able to find the device when it is off though and it isn't showing up in Settings -> Bluetooth -> Devices. I'm suspecting that Apple is caching this information but can't find any documentation to confirm this. Also, when the device is off and we issue the connect call, the program continues to execute as normal but the delegate for didFailToConnect never gets called. When the device is turned on, it will connect immediately.
Is there a way to pass a timeout parameter when trying to connect to a device? If not, what would the best solution be to handling reconnecting to a previously used device for an application (we're storing the last connected device within the app).
Two points you need to know about retrievePeripherals: and connectPeripheral:
1.) retrievePeripherals: attempts to retrieve the CBPeripheral object associated with the uuid you supply. Even if the ble device is off (or on the other side of the country) retrievePeripherals: will still return an instance of CBPeripheral that you can call connectPeripheral: on. This is done intentionally so that you can issue a call to a peripheral that is not even around and still automatically connect to it when it comes back into range. It basically creates a marker inside the system bluetooth so that when the device is actually seen, it will know it should connect to it.
2.)connectPeripheral: will not time out unless the communication channel is broken with the actual device. If the iOS device has not seen the device, it will not fail and should not time out (unless some error occurs inside the system bluetooth).
And as for the timeout parameter, there is no documented way inside the CoreBluetooth framework. You can create your own implementation for it, however I believe you'd be better off keeping a list of which peripheral uuid's you've actually called connectPeripheral: on and then just pop them from the list when they connect. If you no longer want to connect to a peripheral in the list call cancelPeripheral: on that UUID, call connectPeripheral: on the other, and swap entries. Good to go.

Resources