Got this debug info when debug a today extension app
"host connection < NSXPCConnection: 0x170113560 > connection from pid 53 invalidated"
does anyone know what this means? it shows almost every time when "widgetPerformUpdateWithCompletionHandler" called.
NSXPCConnection API is used to perform interprocess connection between Xcode client and your app on iPhone. So you do not need to worry about this one.
Link:
https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingXPCServices.html
So there may be 2 reasons that your widget is terminated.
You need to call completionHandler(NCUpdateResultNoData); right after your widgetPerformUpdateWithCompletionHandler has been called even when the response hasn't been returned.
Your app is terminated because of the automatic app termination. It terminates the widgets/apps for 2 reasons:
a. It terminates apps that are not being used and allowing the
reclamation of resources such as memory.
b. It terminates widgets that use too much memory.
Related
So, I have an app that runs an HKObserverQuery in the background. We take data from HealthKit and push it up to our server for further analysis.
When we do an app update, however, we usually see a spike in requests made to our server. It usually times from when the app becomes available in the store, and usually dies down a few days later.
My question is - when an app is updated, does it try to resume a particular state or something after the installation occurs? Our data fetch/upload process is called in applicationDidFinishLaunching, and my only hunch is that after the update occurs it tries to resume a state, thus invoking that function.
Any insight in to this would be real helpful. Thanks!
EDIT: my curiosity exists because I can't imagine all of our users opening the app after an update occurs, especially the auto-updaters. So my question revolves around if iOS attempts to load the app after installing an update to verify it, henceforth calling applicationDidFinishLaunching, but without bringing the app to the foreground.
I have implemented iOS App, In that if we get any unknown crash i want to show one message like "sorry some thing went wrong". Meanwhile the App did not close. It still open if we get crash. Its a requirement from client.
Short answer: This is not a good idea and should be avoided at all cost. Convince the person who provided that requirement that this should not be done.
Long answer: When your app crashes, this means something went horribly wrong. It got into a state where nothing can be guaranteed any longer and it is better (even for the app user) to quit the app right away. The reasons for a crash could be:
an unhandled error
you are trying to access some memory that you don't have access to
accessing memory that is already de-allocated, but your app code thinks it is still allocated to a specific object
and many many more reasons
For the first case you could setup unhandled error handlers across your app or globally; this is what crash reporting SDKs do. For the other reasons you need to set up signal handlers (or even Mach exception handlers) to get those. One rule in those cases is that at crash time you should NOT allocate new memory, simply because you have no guarantee that will work or would not overwrite memory used by other parts of your app which then could cause major corruption of the user's data, or deadlock the device which means the device owner has to restart it.
Not being allowed to allocate any memory at crash time means you can't use any Swift or Objective-C code, because allocating a new object WILL allocate new memory. And showing an alert will just do that as having the app continue to run will do as well. You can only use a subset of (async-safe) C methods at crash time!
So the end of the story is:
detecting a crash is hard
not causing possible damage to user data after a crash is even harder
guaranteeing the app will continue to run without causing damage to user data or being usable to the user at all without more problems is in the area of luck
If the operating system decides that your app should exit (crash) because of such an unsafe scenario, you as an app developer should not decide otherwise.
I have implemented restoration functionality for CoreBluetooth and it works fine, except one thing - after a week (+/- - not sure for 100%) in the background, without opening, app terminated and not restored anymore on any BLE-based events (tested few times).
I also add logging to all BLE related task, add analytic for capturing crashes, track restoring process/events in additional - and after checking this logs/info/reports - not found any exceptions or something that can terminate my app.
The question is - can someone explain me the reason why I got such behavior?
Bluetooth related issues can be really hard to identify. We came across several unexplainable bugs in the past. The only way to determine why BLE was no longer working or misbehaving was to look at the CoreBluetooth logs on the device.
In case you have not tried that already you can enable these logs via a configuration profile that you can download from the Apple Developer Pages (look for Bluetooth and follow the instructions).
As soon as you enable the logging you can download a complete log from the underlying BLE stack that will tell you what went wrong. They even tell you if you have misused the API in some way. Hope that helps.
From my experience with CoreBluetooth State Preservation and Restoration I have come to the conclusion that it does not work reliably. You can get it working sort of "ok", but you will never get it to reconnect reliably while using long running pending connections in the background.
I have reported several bugs regarding this, but the most serious one in my opinion is that If the bluetooth manager switches state while the app is terminated then all pending connections will be lost (since they are not remembered by the module or the iOS stack). Since bluetooth state switches will not cause your app to be relaunched then it simply means that at any point in time your pending connection can be lost and you will not know about it. This on its own effectively means that State Restoration is rather useless. You could say that this is not a bug, but rater a poor design choice…
Another one is that sometimes the framework gets ”stuck” in a bad state (possibly by an internal race-condition or similar). This can happen randomly, but you can pretty easily reproduce this by calling connectPeripheral immediately in the didFailToConnect or didDisconnect callback. When this happens the connectionState will be set to connecting while in fact it is not.
And so on…
/Anton
I am not sure how to best implement keeping our server informed that our iPhone application is currently running (even when in the background). There are a few different options but there is some concern as to what is allowed by the Apple approval process as well as what is the most reliable. The application does have the ability to play music in the background, if that factors into what is approved by Apple.
The first option, is to continually send some sort of heartbeat to the server at a set interval through a simple GET/POST; however, the concern is whether or not this is allowed as a background task. In a very roundabout way it can be argued that it is necessary for the playback but I'm not so sure whether or not that is acceptable. If the server does not hear from them in a set amount of time it will assume the app is no longer running.
The second option involves using a presence channel socket connection and have the server just handle when users enter and leave that channel. With this option the main concern is how reliable is a socket connection like this while an app is in the background. Similarly, whether or not this is allowed by Apple. In this case when the app dies, connection closes and server knows app is not running.
Third option can be used in tandem with either of the other options but to use some sort of APNS push to query the phone as to whether or not it has died and have it respond with some data to let us know; however, this seems somewhat counterintuitive as the push itself wakes the app up.
Any other suggestions or input are also welcome.
Not sure if this should be a comment or answer, but let me put my 2 cents here.
Firstly, Can you please elaborate your needs further, because in case you are playing an Audio in background with AVPlayer/AVPlayerItem you would hand over your content URL to iOS and it will make the calls as and when necessary to keep the playback running, you dont need to know about apps' state.
Let me assume, for whatever reasons you want to achieve what the question asks:
There are 3 states your app can be in when it is "Not Running"
i. Suspended State: your app is not killed but its not receiving any CPU time to execute your code.
ii. Killed by OS: Your app can be terminated by iOS to free up the memory or any other resources.
iii. Force Killed by User: If user swipes up your app from app switcher it gets force killed.
Now when your app is Not Running, you CAN NOT query it, but you can move it to Running State. You can achieve this transition by using following methods (Not exhaustive list, but mentions common ways)
i. Background Fetch : You can configure your app to be invoked periodically, so that it can synchronise with the server and updates its state.
ii. Push Notifications (APNS) : You can ping the app from server so that iOS invokes it for some short period of time (few seconds) to update its state.
iii. VOIP Pushes: If your App is VOIP app you can use PushKit to send Silent Pushes which will launch even the Force-Killed Apps, the above two methods does not transition the app to Running state if it was force killed by user
The above point can be helpful in devising overall strategy but does not answer the question, "How to keep syncing the RUNNING state"
i. When your app is Running(Forground/Background), you can do almost anything that is publicly documented, you can keep calling a URL every minute or every 5 seconds, you need to worry about UX on the device rather than approval process, (People will delete app if they see your app in top battery drainers in the settings section)
ii. For making an HTTP call while your app is in background, you can look at Background URL Session, which off loads the HTTP calls to another process so that the call completes even if app gets killed.
iii. For the socket based approach please refer this technical note. The main issue is that you do not/can not know when your app moves from Running to Not Running State.
iv. As you mentioned that your app uses background audio, it will be always be in Running state if the user plays an audio and puts app in background, in such case you can use Periodic Observer to do some Heartbeat call periodically when the content is being played out.
we have a BLE peripheral that connects to the phone every hour and passes some data. Here is how the process works:
Upon launch with key UIApplicationLaunchOptionsBluetoothCentralsKey in
application(didFinishLaunchingWithOptions launchOptions) app re-initializes CBCentralManager with ID that was passed to it.
Then it goes through the regular restoration cycle and reads data off the BLE peripheral.
Performs REST request to the service in the cloud.
Assuming that app has been launched at least once after phone reboot everything works well for a few days (if app isnt running or been forced out of memory, iOS properly starts it up again, assuming user didnt do forced close manually).
However every few days iOS stops waking up the app when there is an incoming request from BLE device. If user relaunches app everything works properly for a few days and then stops agains. Given the nature of our product, it's critical to have our app / peripheral working together in the most reliable way possible.
Theories as to why it might be happening:
(upon closer examination all of them were dismissed)
Users restart the phone and forget to relaunch the app.
We've added logging of the uptime and it showed that phone didnt restart in between app launches.
Memory warnings lead to app being booted out.
Once again, added logging, they showed that there was no applicationDidReceiveMemoryWarning
Bad connection leads to app running for longer period than 10s when uploading results and iOS terminates it and gets upset
We artificially delayed server response by 15s to test this and everything continues to work properly during testing.
Any ideas on what is happening and why iOS stops notifying app about incoming BLE connection?
One of the problems is that we cannot figure out how to reliably reproduce the issue So any suggestions there will be much appreciated as well!
Thank you!
UPDATE 1:
Here is how we initialize CBCentralManager:
self.centralManager = CBCentralManager(delegate: self, queue: nil, options: [
CBCentralManagerOptionRestoreIdentifierKey : MyCentralManagerID,
CBCentralManagerOptionShowPowerAlertKey : 0])
I saw some suggestions that queue parameter should not be nil. Given that I'm unable to reliably reproduce issue I'm hesitant to make that change until I can confidently observe its effects.
I wanna start by saying that I have been working with CoreBluetooth for a long time now and from what I have noticed CoreBluetooth State Preservation and Restoration does not work reliably at all. You can get it working sort of "ok", but you will never get it to reconnect reliably unless Apple fixes it some day.
There are so many bugs that causes this to not work properly, but I will give you one that I believe is causing your problems:
State restoration will only relaunch your app due to bluetooth related activity if the event originates from a peripheral accessory that you are communicating with, such as connect/disconnect events and characteristics notifications. For other events, most importantly general bluetooth state change events, your app will not be relaunched and notified of this. The reason why this is so bad is because all bluetooth state change events will cancel all pending or current connections, meaning that pending connections will be dropped and your application will not be notified of it. This effectively means that your application will still believe that the connections are still pending when in fact they are not. Since your application is terminated at this time, the only way for it to wake up again is by having the user manually launch it again (or alternatively “hack” other background modes for this purpose, which does not work very reliably either).
This thing happens if the user toggles Flight Mode, toggles Bluetooth, power cycles the iOS device, or any other undefined reasons that many cause state changes…
But this is only one bug. Many other exists as well, such as the XPC connection being interrupted at different times for no apparent reason. I have also noticed that the pending connection can go into “limbo” mode where the peripheral state gets set to Connecting, but in fact it will never connect unless you cycle the connection state.
Anyhow, I am sad to say it, but if you are developing an app that must rely on the peripheral being reconnected in the background then I would not recommend doing it. You will be frustrated. I could probably write an essay about all the bugs in Core Bluetooth that Apple does not want to fix. Even more strange is that you can pretty easily ruin the bluetooth connectivity globally on the device from one single app so that no app can use bluetooth until the device is rebooted. This is pretty bad since it goes against Apple's own Sandboxing principle.