8

I'm developing an iPhone app that plays audio in the background. I want the audio to keep playing if the user locks the screen, but pause if they decide to switch to another app (by pressing the home button).

On iOS 4 there was no problem because the app would go into the inactive state when the screen was locked and only be moved to the background if the home button was pressed. On iOS 5 when the screen is locked the app is now also moved into the background, so it seems it is no longer possible to tell the difference between the two states. Is there a solution to this problem?

Stuart Fisher
  • 201
  • 3
  • 8
  • This is an annoying issue because any google search returns the ios5 notification center. Ideally we could find a list of all of the system notifications we have the ability to register for and hope something pops up – Rich86man Dec 10 '11 at 18:06
  • The OS will take care of that for you as long as you configure your audio session accordingly, or so it seems (I'm not an audio programmer). If you search for "screen lock" in the docs, you'll find information that should help you in the Audio Session Programming Guide (Audio Session Cookbook). – Bored Astronaut Dec 13 '11 at 15:39
  • possible duplicate of [Is it possible to distinguish between locking the device and sending an app to background?](http://stackoverflow.com/questions/7754317/is-it-possible-to-distinguish-between-locking-the-device-and-sending-an-app-to-b) – Pang Dec 28 '13 at 03:31

4 Answers4

14

You can distinguish these two cases by checking the applicationState property of UIApplication. It will be set to UIApplicationStateInactive for an application that did enter background because of the lock screen, and to UIApplicationStateBackground otherwise.

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    UIApplicationState state = [application applicationState];
    if (state == UIApplicationStateInactive) {
        NSLog(@"Sent to background by locking screen");
    } else if (state == UIApplicationStateBackground) {
        NSLog(@"Sent to background by home button/switching to other app");
    } 
}
Tammo Freese
  • 10,514
  • 2
  • 35
  • 44
5

Loooking for UIApplicationState when applicationDidEnterBackground is fired has worked nicely. Sadly, this has been changed now.

When I compile my app with XCode5 to support all iOS7 stuff (but still build target is set to 5.0), locking screen gives now state UIApplicationStateBackground, when earlier I did get UIApplicationStateInactive.

I asked this from Apple support and they confirmed, this is how it will work from now on. So, there is no way to detect if user pressed Home or Screen lock. This is sad since I had really good use case for detecting it.

PS. My app that has been built with XCode 4 still works old way also when run on iOS7.

user1478430
  • 59
  • 1
  • 2
4

I have found a better way to do this thing.

Differentiate between screen lock and home button press on iOS7

This can help you both on iOS5 & iOS6 & iOS7 device :).But it don't work at iOS Simulator.

You can get [[UIApplication sharedApplication] applicationState] to judge whether it is lock screen or home button with UIApplicationStateInactive and UIApplicationStateBackground before iOS7.

But these became the same state UIApplicationStateBackground on iOS7, and you can judge it through screen brightness.

The screen brightness should be 0 when in lock screen state; otherwise, it is home button state.

You can put the code snippet in - (void)applicationDidEnterBackground:(UIApplication *)application

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    UIApplicationState state = [[UIApplication sharedApplication] applicationState];
    if (state == UIApplicationStateInactive) {
        NSLog(@"Sent to background by locking screen");
    } else if (state == UIApplicationStateBackground) {
        CGFloat screenBrightness = [[UIScreen mainScreen] brightness];
        NSLog(@"Screen brightness: %f", screenBrightness);
        if (screenBrightness > 0.0) {
            NSLog(@"Sent to background by home button/switching to other app");
        } else {
            NSLog(@"Sent to background by locking screen");
        }
    }
}

Community
  • 1
  • 1
wqq
  • 239
  • 1
  • 6
  • Will this work on iOS5 too, if so, I'd suggest editing that into your answer. Also, can you explain a bit about what the code is doing in an edit to your post? The best Stack Overflow answers provide explanation as well as show code. If you can do that, I will be able to remove this downvote as edited posts are eligible for vote changes. As for the dup post, I suspect it may get merged into this one and will work itself out since a few people flagged it. Hope this helps, and welcome to Stack Overflow! :) – jamesmortensen Nov 05 '13 at 02:48
  • @jmort253 I have change it, it maybe some mistake on my English. – wqq Nov 05 '13 at 03:06
  • This did not work for me. Where are you putting this code snippet? Which device are you using? – Khaled Barazi Nov 10 '13 at 14:34
  • @Spectravideo328 I have update the answer.I have test this code on iPhone5 with iOS7 and iPod Touch with iOS6. But it don't work on iOS simulator with iOS7, sorry I have not mention that before. – wqq Nov 11 '13 at 17:55
1

There is a way to get this behaviour, but it comes with a caveat. You have to set the audio background mode in your Info.plist and disable multitasking for your app.

Set the Audio Session Category to AVAudioSessionCategoryPlayback:

[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: &error];

In your Info.plist file, add the key "Required background modes" and add the item "App plays audio". Then add the key "Application does not run in background" and set it to "yes" enter image description here

Now the lock screen will put your app in the audio background mode (audio keeps running) while pressing the home button will terminate your app (and silence the audio). When the user returns to your app from another app it will launch again. So if your app doesn't take too long to load and you can return to the previous state after relaunch, this might be a viable solution.

I have tested it with iOS 4.3 and iOS 5.0.1 (on a device).

Dorian Roy
  • 3,094
  • 2
  • 31
  • 51
  • 2
    Unfortunately, this configuration now contravenes Apple's validation routines. When I went to validate my app I got the following issue: "If the value of UIApplicationExitsOnSuspend is Yes, your app must not specify any values in the UIBackgroundModes key. If your app uses background services, thevalue of UIApplicationExitsOnSuspend must be No. For more information, refer to the Information Property List Key Reference." – adamcohenrose Jan 15 '12 at 13:26
  • Too bad. It was a bit of a hack anyway – Dorian Roy Jan 16 '12 at 14:21