I'm trying to get an app running indefinitely.. I'm developing an internal app, so apple approval doesnt matter.
I've tried a few different things, including simulating a voip app using this tutorial..
http://www.raywenderlich.com/29948/backgrounding-for-ios
Eventually I ran into this code snippet online
[application beginBackgroundTaskWithExpirationHandler:^{}];
I place this in beginBackgroundTaskWithExpirationHandler and then call a slow-looping function inside of my app delegate in application:didFinishLaunchingWithOptions
-(void)caller{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
NSTimeInterval timeRemaining = [UIApplication sharedApplication].backgroundTimeRemaining;
NSLog(#"%f", timeRemaining);
[self caller];
});
}
this logs background time remaining every 3 seconds. it does this when i exit my app.. i see a countdown from 180 (3 minutes) to eventually 0
then it just keeps logging 0 indefinitely. I would figure if background time reaches zero, then my process wouldnt execute.
Anyone have any idea whats going on here?
If you use beginBackgroundTaskWithExpirationHandler and start the app from Xcode, that will alter the behavior of this UIBackgroundTaskIdentifier (Xcode will keep the app alive). If you see the log messages showing up in Xcode's debugging console, that means the app was started on the device via Xcode.
Now that the app is installed on the device, stop it (either by hitting the "stop" button in Xcode or by manually terminating the app via Springboard on the device). Once you've confirmed the app isn't running, you can now run it again by tapping the app icon on the device itself. It should start, not linked to Xcode in any way.
Even though the app is now not running via Xcode, though, you can still monitor the progress of what you logged, by going to Xcode's "Device Organizer", and open up the actual device's console. I suspect you'll see the background task expire, like you expected it to.
Related
I'm attempting to automate a hard close and relaunch of an iOS application while retaining state in the simulator.
Googling tells me to add a button to my app to call exit(0), but that's resetting app state despite a number of threads saying it doesn't (although Apple said it's unreliable for this a long time ago).
Another thread said to use abort, but that's akin to throwing an exception and definitely not the right thing.
Performing the [automated] manual steps (double click the Home button and swipe the app up to death) disconnects the debugger so another option failed.
The correct procedure for testing state restoration is: click the Home button on the simulator once so that the app backgrounds and saves state. Now, back in Xcode, stop and relaunch.
You can simulate a click on the Home button like that
XCUIDevice.shared.press(.home)
And then call this function to launch your app with
XCUIApplication().launch()
According to the launch() documentation, it should terminate your app and relaunch it :
* Launches the application synchronously. On return the application ready to handle events. If the
* application is already running, the existing instance will be terminated to ensure a clean state
* for the launched instance.
*
* Any failure in the launch sequence will be reported as a test failure and the test will be halted
* at that point.
I'm building an iOS app for iOS 8 & 9 and I am facing the problem that when the app goes to background the system is terminating it after just 2 or 3 minutes.
My testing is easy:
I kill all running apps from my iPhone.
I restart my iPhone (to ensure no other apps are taking memory).
I launch my app.
I do nothing inside my app.
I press the "Home" button, moving my app to background.
I wait doing nothing else for 2 or 3 minutes.
I open my app again and surprise, the system has terminated it and now it is restarting as a new launch.
Some comments:
The app does not use CoreLocation in background neither any other service.
I've profiled the app, trying to understand if it is consuming too much memory. When moving to background, it consumes around 25Mb of RAM memory. I'm attaching a screenshot below.
This behavior has been tested on iPhone 5, 5s, 6, 6+.
In iPhone 6s and 6s+ seems to take a bit more time to happen, but still happens.
My question is: Do you know why would this be happening? anything I might not be considering or just forgetting?
I don't want to force my app to run in background by using CoreLocation or something similar. And I'm ok if the system kills my app eventually. What I don't want is that everytime I move my app to background the system terminates it.
Any hint or help will be appreciated.
Thanks,
All applications are automatically killed by the system
According the Apple documentation:
App Termination
Apps must be prepared for termination to happen at any time and should not >wait to save user data or perform other critical tasks. System-initiated >termination is a normal part of an app’s life cycle. The system usually >terminates apps so that it can reclaim memory and make room for other apps >being launched by the user, but the system may also terminate apps that >are misbehaving or not responding to events in a timely manner.
Suspended apps receive no notification when they are terminated; the >system kills the process and reclaims the corresponding memory. If an app >is currently running in the background and not suspended, the system calls >the applicationWillTerminate: of its app delegate prior to termination. >The system does not call this method when the device reboots.
In addition to the system terminating your app, the user can terminate >your app explicitly using the multitasking UI. User-initiated termination >has the same effect as terminating a suspended app. The app’s process is >killed and no notification is sent to the app.
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html#//apple_ref/doc/uid/TP40007072-CH2-SW1
You can track position but you will certainly see a blue status bar to indicate that an application use GPS tracking.
Maybe you can try to "wake up" your app in background with silent notification...
If it is not necessary to keep your app alive, trust the system...
Some error in inside your code. Please select debug Navigator before run your app... Now you can able to find your error..
Or too much memory also it will terminated..
Apps which are running in the background drain battery life faster, It gives you a bad perception of the device, instead of the app, because the average consumer has no idea that it's an app draining battery.
Thus iOS won't allow your app to run in the background, more than a few seconds. But there are some exception, an app can request extension to this by declaring that its starting a Background Task.
for more info you can check below links:
http://blog.dkaminsky.info/2013/01/27/keep-your-ios-app-running-in-background-forever/
http://www.speirs.org/blog/2012/1/2/misconceptions-about-ios-multitasking.html
When I launch my app from Xcode with Background Fetch mode, it works. But it should stop when I call callback handler, or after 30 seconds.
But it does not! When I click Pause, I may see my main thread does not do anything.
Is it some xcode-specific issue, or do I misunderstand something about background fetch?
Apps running under the Xcode debugger are not subject to the same background execution time limitations as a released app.
For example, if you looped, logging UIApplication property backgroundTimeRemaining on a released app, your app would be terminated when this value reached zero. Under the debugger your app would continue indefinitely, reporting a zero value.
I'm trying to debug an issue with my iPhone app that seems to be getting terminated while running on the device (it never happens in the simulator). The app is for iOS 8 only.
Once app enters the background (via the user hitting the home button) I start Significant-Change Location service. When a location updates happens while the app is suspended the system should put the app in the background where I then send an update to my server with the location. That operation is wrapped in a proper beginBackgroundTaskWithExpirationHandler to allow me the time needed to make the network call.
It appears though my app is getting terminated by the system because sometimes when I resume the app from the suspended state it is no longer in the view last seen when minimizing but is back at the root controller as if starting from a fresh launch. It does not appear to be due to a crash as I do not see it in the crash log nor is New Relic reporting such. The app is suspended though, not terminated, probably because it is getting launched again into the background from a location update.
The question is, is there a way to know that my app was indeed terminated by the system, and if so, for what reason(memory, exceeding background execution time, etc.) and at what time. Is there a log kept somewhere containing this information?
I'm under the impression I can not use applicationWillTerminate because the docs say this is not called when an app is suspend.
You may check in Devices page. (Shortcut is Command + Shift + 2)
How can one test the scenario of Application Launch in background for handling Background NSURLSession's event?
Flow:
Application starts a upload/download task using Background URL
session.
User hits home button. App is in suspended or in background
state.
OS decides to Exit the application. I know, one can exit the app by double-tapping home button and swipe-up the particular app. But in that case OS will never re-launch the app in background for event handling.
Upload/download task needs some event handling. OS re-lauches App in background.
So the question is how do I make OS exit the app like it may normally do after some-time. The purpose is to test the code for this scenario. I tried using UIApplicationExitsOnSuspend but it does not work since then App can not be launched in Background.
It's not a perfect solution, but I was able to manually test the launch of an app due to a Background URLSession on a physical device as follows:
Connect device for debugging via USB
Disable Internet connectivity on device (i.e. disable WiFi/Cellular)
Start the app via Xcode
Issue a request using background URLSession. The request shouldn't fail, it will just be waiting around for an Internet connection until it times out, so use a reasonably long timeout to make testing easier.
Kill the app via Xcode (press stop button)
View the device logs via Windows > Devices and Simulators
Enable Internet connectivity on the device again without starting the app
The requests from the background URLSession should then complete and in the device logs (from step 6.) you should see any NSLog statements issued as a result of the app being launched via the application(_:handleEventsForBackgroundURLSession:completionHandler:) app delegate method.
They key point is that killing the app via Xcode, as opposed to killing it using device itself, does not prevent the app from being relaunched for background event handling.
A possible alternative to killing the app manually via Xcode might be to intentionally crash the app in code - this might be more suitable for automated testing.
You could write an app that has a button that allocates and intentionally leaks chunks of memory. If you get this thing to allocate enough RAM, the OS will start killing other apps to get their RAM back.
Hopefully this would exhibit the behavior you need.