0

I am using AVAudioPlayer and NSFileHandle to do audio streaming. The basic idea is that I save the streaming audio data to the device with file system and then use AVAudioPlayer to playback the file just saved. AVAudioPlayer can still play that file even the streaming is in progress.

I have a UIButton to start streaming/downloading. When the downloaded data is accumulated to a specific amount of Bytes, AVAudioPlayer will play (the "play" method of AVAudioPlayer is triggered) automatically. My question is: I tap the button to start streaming/downloading, then press iPhone's home button very soon to make my app go to background. The download keeps working in the background but the "play" method of AVAudioPlayer returns "NO" which means the "play" method doesn't play the audio.

I added AVAudioSession related code to my audio player's init method:

- (id) initWithURL:(NSString *) downloadedMusicURL
{
    if ((self = [super init]))
    {       
        [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

        CFURLRef url = CFURLCreateWithFileSystemPath (NULL, (CFStringRef)downloadedMusicURL, kCFURLPOSIXPathStyle, FALSE);

        audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:CFBridgingRelease(url) error:nil];

        AVAudioSession *session = [AVAudioSession sharedInstance];
        [session setActive:YES error:nil];
        [session setCategory:AVAudioSessionCategoryPlayback error:nil];
    }

    return self;
}

Also in the info.plist I added an item "App plays audio" for the Key "Required background modes". However, the "play" still doesn't get called properly in the background. What else did I miss? Thanks a lot in advance.

Yashesh
  • 1,799
  • 1
  • 11
  • 29
stspb
  • 193
  • 2
  • 12

4 Answers4

2

Your app cannot start playing audio in the background. And this makes sense. Think what the device would be like if an app that the user is not actively using could suddenly start producing sound! Remember, to the user, sending an app to the background is the naive equivalent of quitting that app. Your app must not rise like a zombie from the dead and start making noise!

The background audio setting allows your app that was producing audio while in the foreground to continue to do so when it then goes into the the background. It then can continue being in charge of the audio (if it receives remote events) until some other app produces sound; after that, your app is once again out of the running until it is brought to the foreground and produces sound.

So you'll need to start playing some sound before your app goes into the background, if you want this to work.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Hi! Matt I think this make sense but can we not produce audio in background only? – iEinstein May 15 '13 at 15:46
  • This cannot be true. Music apps (Spotify, Pandora) can be backgrounded and continue to play songs even after the song that was playing when the app was backgrounded ends. – jmstone617 Aug 08 '13 at 16:13
  • @jmstone No, not if they weren't playing at the time they were backgrounded. Read carefully what I said. It is accurate. – matt Aug 08 '13 at 23:23
  • 2
    You cannot START audio from the background, but if an app is playing a song and it is backgrounded, and the song ends, the next song should be able to play. – jmstone617 Aug 09 '13 at 04:15
  • @jmstone Correct, and that's what I said. – matt Aug 09 '13 at 16:34
1
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

UIBackgroundTaskIdentifier newTaskId = UIBackgroundTaskInvalid;
newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];

/* And in info.Plist file Required background modes : App PLAYS Audio */

Amit Bhavsar
  • 1,273
  • 12
  • 23
0

Please use this code in - (void)applicationDidEnterBackground:(UIApplication *)application

UIApplication *app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask = 0;

bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
[app endBackgroundTask:bgTask]; 
}];
AudioSessionSetActive(false);

and use this code in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

AudioSessionInitialize (NULL,NULL,NULL,NULL);
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty (kAudioSessionProperty_AudioCategory,sizeof (sessionCategory),&sessionCategory);
AudioSessionSetActive(true);

hope this helps.

Dinesh Raja
  • 8,501
  • 5
  • 42
  • 81
iEinstein
  • 2,100
  • 1
  • 21
  • 32
  • This is if you want to complete a lengthy task and will only allow up to 10 min. extra time after your is backgrounded to complete your task. – rckoenes May 15 '13 at 11:58
  • I have lengthy task according to my project so i used this – iEinstein May 15 '13 at 12:00
  • I did add the above code but it still doesn't work. Matt's comment above makes sense though. – stspb May 15 '13 at 15:24
0

Faced this very problem. Let me suggest you to use AVAudioSessionCategoryOptionMixWithOthers with -setCategory:withOptions:error:. Also, probably it makes sense to activate the session after you set the category, not before.

Grigory Entin
  • 1,617
  • 18
  • 20