I am writing a music playing app which performs a task between each song. I need to do this even when the app is in the background, so I need to know when a song has completed. At the moment I am using AVPlayer which sends notifications even when the app is in the background, but is unable to play songs from the user's iCloud. MPMediaPlayerController can play iCloud songs but doesn't send notifications when the app is in the background (which is essential to my app).
So, does anyone know either
Any clever ways of having AVPlayer play iCloud songs, or
Having my app recognise when a song playing via MPMusicPlayerController has completed when the app is in the background?
Have you tried using NSNotification Center and one of these two observers?
MPMusicPlayerControllerPlaybackStateDidChangeNotification or MPMusicPlayerControllerNowPlayingItemDidChangeNotification.
Also, you need to use beginGeneratingPlaybackNotifications() on your instance of MPMusicPlayerController.applicationMusicPlayer() or MPMusicPlayerController.systemMusicPlayer()
To build on #Kim's answer. You can use the NSNotificationCenter and add ObserverEvents. I use the MPMusicPlayerController class for my application, and I've registered the application to use the NSNotificationCenter properties so I can call certain methods during differing events.
For instance, while using the SystemMusicPlayer property if you exit and terminate the application process, the music keeps playing. If the user wanted to stop the music when they exityou could call this:
-(void) registerMediaPlayerNotifications {
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:#selector(stopMusicWhenApplicationQuits)
name:UIApplicationWillTerminateNotification
object:[UIApplication sharedApplication]];
[musicPlayer beginGeneratingPlaybackNotifications];
}
Where you see the #selector that is the method that will be fired when the application receives the UIApplicationWillTerminateNotification event. Which in the musicPlayer you can say
[self.musicPlayer stop];
So for the question you have, you can still use the MediaPlayer framework, use the MPMusicPlayerController class and call various methods during different application runtime stages using the NSNotificationCenter properties.
Hope this helps, let me know if you have any further questions.
Related
I have a simple IOS app that uses a webView to load various infomraiton
Most information is HTML, but the URL passed to the webView may be an audio file. When this happens IOS launches a mediaplayer which is fine.
I've got a timer that is started in the webViewDidStartLoad method and invalidated in the webViewDidFinishLoad method. This timer causes clicking sounds to be played. It seems that when an audio file is launched, the webViewDidFinishLoad method isn't triggered until you close the mediaplayer.
How can I stop the timer before the mediaplayer starts so the user doesn't hear the progress clicks?
I'm not sure if the webview is launching MPMoviePlayerController instance when the audio url is encountered.
If it is, then you can register to MPMoviePlayerController notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playbackStateChanged) name:MPMoviePlayerContentPreloadDidFinishNotification object:nil];
The selector will be called when the audio data is loaded.
I am currently using an AVAudioPlayer to play looped music in the background of my app. However, when siri is opened in my application it turns it off. I am farly experienced with objective c but I cant seem to get this to work. Is there any way I can tell when a user opens siri so that I can start the AVAudioPlayer again after it stops. Please help!
P.S I have attempted continuously playing the audio but then siri wont work.
You can use AVAudioPlayerDelegate's audioPlayerEndInterruption:withOptions:
- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player withOptions:(NSUInteger)flags {
[player play];
}
For anyone else coming to this, the endInterruption delegate isn't getting called from me when my app gets interrupted by Siri. I had to make the app resume playing when it becomes active again (using a notification).
I make a iOS program to use the AVAudioPlayer to play music on the background. But I don't know how to shut down the music after a certain time.
I try to use the UILocalNotification to stop music in the method:
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notification
But the way only effectly after the user recieved the Notification and click to shut down!
How can I stop the music automatically after a certain time?
If you use AVPlayer instead of AVAudioPlayer you can achieve this using addBoundaryTimeObserverForTimes:queue:usingBlock:
I have tried this with AVQueuePlayer (which is a subclass of AVPlayer) and it worked.
Try something like this:
id observer = [avPlayer addBoundaryTimeObserverForTimes:[NSArray arrayWithObject:[NSValue valueWithCMTime:CMTimeMake(60, 1)]] queue:NULL usingBlock:^{
[avPlayer pause];
}];
And somewhere later:
[avPlayer removeTimeObserver:observer];
I would love to be proved wrong, but I believe that what you're asking to do might be impossible. My impression is that if the user actually clicks the Home button to send your app into the background, it can't function as a "sleep timer", because you can't run a timer. Apple's own apps can do this sort of thing, but they have special privileges.
For example, look at this app:
https://itunes.apple.com/us/app/music-sleep-timer/id320583424?mt=8
Look at how he says, "Remember to keep this app in the foreground!" Clearly that's because once the app is background, the timer stops working.
You might be better off advising the user to resort to the countdown timer in Apple's Clock app. It can shut down your music and put the device to sleep.
I am developing an iPhone application which plays the video using MPMoviePlayerController. When I switch to background(device with multi-tasking support), the video play is paused and when I bring my app to foreground video play is resumed.
But, when I switch to foreground I do not want my video to be resumed. I tried to pause the MPMoviePlayerController in the method applicationWillEnterForeground. But, I think they resume implicitely after call to applicationWillEnterForeground. Is there any notification methods that corresponds to applicationDidEnterForeground OR applicationWillEnterBackground?
Although as you know UIApplicationDidEnterForegroundNotification and UIApplicationWillEnterBackgroundNotification do not exist, there are functions that correspond to the same thing.
They are,
UIApplicationDidBecomeActive:
and
UIApplicationWillResignActive:
Check out the UIApplication Class Reference here: https://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIApplication_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006728
In the notifications section of that document, you'll find the notifications posted to the Notification center. Your class can register to receive these notifications and handle the video playback state appropriately.
Hope this is the answer you were looking for.
I am wondering how to most efficiently play a series of video with MPMoviePlayerViewController?
For example, I would like to play in a series the following:
Video1.mp4
Video2.mp4
Video3.mp4
and so on...
Any suggestions appreciated.
Use NSNotificationCenter to monitor for the MPMoviePlayerPlaybackDidFinishNotification notification. Then, set up the player with the next item you wish to play.
You can register for the notification MPMoviePlayerPlaybackDidFinishNotification with [NSNotificationCenter defaultCenter]. Once you receive that notification, just load the next video and start playback.
Have a look at the respective class documentations for additional details.