I have an app that makes heavy use of video out. In a typical use-case, I'll have an iPad connected to an external monitor. I just want the external monitor on; the iPad display does not need to stay on.
The ideal case would be for someone to connect to an external monitor, then lock their iPad. But that pauses my app. (Currently, I'm calling setIdleTimerDisabled to keep the iPad from locking up and pausing my app.)
I'd like to give the user the option of locking the iPad, but still having my app running and sending images to video out. (Note: I'm not talking about keeping my app running when it's not in the foreground. I just want to keep it running while it's in the foreground, but the device is locked.)
Is this possible?
I would say no, it is not possible. Here's why:
The docs read:
Pressing the Sleep/Wake button is another type of interruption that causes your app to be deactivated temporarily. When the user presses this button, the system disables touch events, moves the app to the background but sets the value of the app’s applicationState property to UIApplicationStateInactive (as opposed to UIApplicationStateBackground), and finally locks the screen.
Something interesting to note in the docs above is that a bit further down under "What to do when an interruption occurs" Apple recommends that you stop doing certain tasks.
In response to this change, your app should do the following in its applicationWillResignActive: method:
Stop timers and other periodic tasks.
Stop any running metadata queries.
Do not initiate any new tasks.
Pause movie playback (except when playing back over AirPlay).
Enter into a pause state if your app is a game.
Throttle back OpenGL ES frame rates.
Suspend any dispatch queues or operation queues executing non-critical code. (You can continue processing network requests and other time-sensitive background tasks while inactive.)
This tells me that Apple doesn't want or expect your app to be doing much of anything in this state, other than preparing to be fully backgrounded.
On a related note here's a thread that shows how to determine whether you've hit the Sleep/Wake button or not:
Is it possible to distinguish between locking the device and sending an app to background?
Related
I have an ios app that takes audio from the phone microphone, performs some processing on the mic data in real time and sends the result to headphones
In Project -> Capabilities -> Background modes, I have selected Audio, AirPlay and Picture in Picture
I want the app to continue to read microphone data and send audio to headphones when the app is in background (user presses home button) and when the phone screen is locked using the lock button
All of this is happening, so I don't think there are any problems with the app permissions, but I have noticed that after the app is backgrounded, it suddenly gets killed, usually in less than a minute
I managed to catch an instance of the app getting killed in the background in the xcode console and the message was
Message from Debugger: terminated due to signal 9
Looking around in google indicates that this simply means that the app was destroyed by the OS using SIGKILL
Is there any way to find out why the app was killed? Is it just impossible to keep the app running in background for a long period? Before I enabled Audio, AirPlay and Picture in Picture background mode, the audio used to stop as soon as I pressed the home button or the screen lock button. I am assuming that since the audio keeps running when I press the home button now implies I am indeed able to run mic/speaker in the background if I have to, and there are music players as well as audio recorder apps that work in the background until the user specifically closes them.
How can I find out the exact reason why my app is getting closed automatically, and what can I do to keep it running in the background indefinitely until the user closes it?
After you installed your app through xcode, run it normally (not by run in xcode), Let it crash. Then connect the phone, go to xcode -> Window -> Devices and Simulators -> View Device Logs. Then find the most recent crash.
Your particular problems sounds to me like overuse of CPU. App in background cannot utilize more than 80% (IIRC) of device CPU for extended periods of time (around one minute) or it will be killed by the system. If that is your case you simply need to optimize your code to not hog the CPU.
Is there a universal time of iOS app suspension time (i.e when it goes out of background mode and terminates).
Background
The app is in the background and executing code. Most apps enter this
state briefly on their way to being suspended. However, an app that
requests extra execution time may remain in this state for a period of
time. In addition, an app being launched directly into the background
enters this state instead of the inactive state. For information about
how to execute code while in the background, see Background Execution.
Suspended
The app is in the background but is not executing code. The system
moves apps to this state automatically and does not notify them before
doing so. While suspended, an app remains in memory but does not
execute any code. When a low-memory condition occurs, the system may
purge suspended apps without notice to make more space for the
foreground app.
No, there is not any possibility to know about that, according to this:
Suspended: ...The system moves apps to this state automatically and does not notify them before doing so...
Link: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html
I have an iOS app that is communicating with a bluetooth peripheral. When you tap a button on the peripheral, the app should start recording, whether it's in background or foreground.
Furthermore, there will be multiple recordings, in order to send them quickly to the server. So the app will record in chunks and then send them to the Parse database that I set up.
The chunk recording and uploading parts are working fine, but I have problems while the whole process starts in background, due to the bluetooth notification. The code that starts the recording is executed, but the completion block of the upload process is not. Maybe the recording starts but never finishes because the system stops the execution, since the app is in background?
I added the audio background mode so the app will be able to record in background, and I also added the voip background mode, since I read it will enable background network activity (which is something that I need in this case).
Unfortunately this didn't work.
Any suggestions will be appreciated.
Is there a way to detect lock after the app has entered background? For example,
I have my app (A) open at the foreground
Then I bring another app (B) to the foreground
Then lock the screen
Is it possible for (A) to detect the lock?
The answer is "In theory yes, but usually not."
Apps actually have more states than active and background.
The states are:
Active
Background (still running, but another app is in the foreground)
Suspended (in memory, but not getting any CPU time)
Not running. (no longer running or in memory.)
When the user swaps apps, presses the home button, or locks their device, your app gets notified that it is going into the background, but it actually only runs in the background for a VERY short time. It transitions to suspended almost immediately. Once you're suspended, you can be terminated at any time without further notice.
If you need more time to finish a task when you get notified that you are being moved to the background, you can ask for it using the beginBackgroundTaskWithExpirationHandler call. However, as of this writing you get at most 3 minutes, and then your expiration handler fires and your app is suspended.
As a result of this, you don't actually get to run in the background for very long and it's likely that by the time the user locks the screen (or it locks automatically) you are already suspended and don't get notified.
Is it possible for (A) to detect the lock?
No, for two reasons:
You cannot detect, under any circumstances, that the screen has been locked. Even if your app is frontmost when the screen is locked, all you learn is that your app was backgrounded, without your being able to learn why.
In your scenario, by the time the screen is locked, your app isn't even running — it has been suspended. So it cannot "detect" anything.
I am trying to force my app to automatically enter the "Suspended" state programmatically, so I can do testing on Core Bluetooth restoration.
I have tried calling
[[UIApplication sharedApplication] performSelector:#selector(suspend)];
but this merely sends it into the background. Am I doing it wrong? Is there a better way? Or is it impossible?
I would like to remind everyone exactly what it means to have an app be suspended, as there is always confusion on the terminology:
(source: apple.com)
An app in the background will get indefinitely suspended if the system needs memory, but Core Bluetooth's restoration can send an app back into the background state temporarily.
I don't know how to do this programmatically, but what I do is to press the home button, then launch a number of heavyweight apps like Safari and graphics-intensive games. The memory pressure causes the system to terminate your app pretty quickly. Core Bluetooth should then initiate the restore process and re-launch your app when it detects activity from a peripheral you are connected to/have asked to connect to.