user491880
user491880

Reputation: 4869

iPhone: Streaming music while application is in background

I have an app that streams music using AudioStreamer class by Matt Gallagher. This works fine as a background process except I want to be able to skip to the next song once the stream is finished. Unfortunately this part doesn't work. Initially I had a timer that was monitoring the stream but realized that when the app backgrounds this timer no longer runs. So I tried adding a delegate callback in the packet read function:

void ASReadStreamCallBack(CFReadStreamRef aStream, CFStreamEventType eventType, void* inClientInfo)
{
   AudioStreamer* streamer = (AudioStreamer *)inClientInfo;
   double percent = [streamer progress]/[streamer duration];
   if(percent>=0.98 || (percent>=0.95 && [streamer isIdle])){
     if([streamer.delegate respondsToSelector:@selector(didFinishPlayingStream:)] ){
         [streamer.delegate didFinishPlayingStream:streamer];
         streamer.delegate = nil;
     }
   }


   [streamer handleReadFromStream:aStream eventType:eventType];
}

This works fine when the app is in the foreground but no longer works when the app is backgrounding. The delegate method basically sends a request to get the stream URL for the next song, then once it has it creates a new AudioStreamer class

Upvotes: 2

Views: 1225

Answers (2)

tumtumtum
tumtumtum

Reputation: 1162

I've uploaded my AudioPlayer/streamer class inspired in part by Matt Gallagher's AudioStreamer to https://code.google.com/p/audjustable.

One of the cooler features is its support for gapless playback. This means the AudioQueue is never closed between gaps; keeping iOS from suspending your app.

You can implement AudioPlayerDelegate:didFinishBufferingSourceWithQueueItemId and AudioPlayerDelegate:didFinishPlayingQueueItemId to queue up the next track by calling AudioPlayer:queueDataSource.

Let me know if you need help using it.

Upvotes: 1

Pablo Formoso Estrada
Pablo Formoso Estrada

Reputation: 11

While the app is in background you can implemente the delegate to handle the different remote control states.

- (void)remoteControlReceivedWithEvent:(UIEvent *)receivedEvent { 
switch (receivedEvent.subtype) {
    case UIEventSubtypeRemoteControlTogglePlayPause:
        if (player.isPlaying) {
            [player pause];
        } else {
            [player start];
        }
        break;

    case UIEventSubtypeRemoteControlPreviousTrack:
        break;

    case UIEventSubtypeRemoteControlNextTrack:
        [self skipSong:nil];
        break;

    default:
        break;
} }

Something like this works for me.

Upvotes: 1

Related Questions