I have this website which plays videos, then my ios app shows this website on an UIWebview. My question is that when ios plays video from this website, which player does ios use? I want to know the answer to this question because I want to get pause notification from the player, so I want to know which kind of notification to use. Thanks
Definitely when iOS plays a video from a website page using native controller, it most probably seems to be a Native iOS player that we can show using MPMoviePlayViewController .
The reason seems to be the VOD or streaming video service must be following Apple's guideline for HLS.
Here is code to listen to StateChange notification
MPMoviePlaybackState
Constants describing the current playback state of the movie player.
enum {
MPMoviePlaybackStateStopped,
MPMoviePlaybackStatePlaying,
MPMoviePlaybackStatePaused,
MPMoviePlaybackStateInterrupted,
MPMoviePlaybackStateSeekingForward,
MPMoviePlaybackStateSeekingBackward
};
typedef NSInteger MPMoviePlaybackState;
Register for the MPMoviePlayerPlaybackStateDidChangeNotification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(MPMoviePlayerPlaybackStateDidChange:)
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:nil];
//Check in this function MPMoviePlaybackState
(void)MPMoviePlayerPlaybackStateDidChange:(NSNotification *)notification
{
if (player.playbackState == MPMoviePlaybackStatePlaying)
{ //playing
}
if (player.playbackState == MPMoviePlaybackStateStopped)
{ //stopped
}if (player.playbackState == MPMoviePlaybackStatePaused)
{ //paused
}if (player.playbackState == MPMoviePlaybackStateInterrupted)
{ //interrupted
}if (player.playbackState == MPMoviePlaybackStateSeekingForward)
{ //seeking forward
}if (player.playbackState == MPMoviePlaybackStateSeekingBackward)
{ //seeking backward
}
}
Remove notification by
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
Refer :MPMoviePlaybackState
Related
I am getting EXC_BAD_ACCESS crash that occurs in the AudioToolBox. How to handle interrupts properly?
Please have a look at crashlytics screenshot for more info.
My audio streaming player was crashing when I get a phone call/ faceTime. It was actually an older class with Non ARC. Simply Add an InterruptionNotification Observer for the streaming class, and if the streaming class is playing we need to pause the player instance while interrupt begins.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleInterruptionChangeToState:) name:#"ASAudioSessionInterruptionOccuredNotification" object:nil];
- (void)handleInterruptionChangeToState:(NSNotification *)notification {
AudioQueuePropertyID inInterruptionState = (AudioQueuePropertyID) [notification.object unsignedIntValue];
if (inInterruptionState == kAudioSessionBeginInterruption){
if ([self isPlaying]) {
[self pause];
pausedByInterruption = YES; //a global Bool variable
}
}
else if (inInterruptionState == kAudioSessionEndInterruption){
AudioSessionSetActive( true );
if ([self isPaused] && pausedByInterruption) {
[self pause]; // this is actually resume
pausedByInterruption = NO;
}
}
}
Hope it helps.
I'm having a some issues to get the current playing song information like (title, artist...) in the native iOS Music App.
This is the exact problem, my app is using a MPMusicPlayerController with iPodMusicPlayer this property is call myPlayer. When the user is controlling the music within my app I'm able to display the current song playing information in this way...
- (void)getTrackDescription {
// getting whats currently playing
self.nowPlayingItem = [myPlayer nowPlayingItem];
// song title currently playing
self.title = [self.nowPlayingItem valueForProperty:MPMediaItemPropertyTitle];
// if title is not fund Unknown will be displayed
if (title == (id)[NSNull null] || title.length == 0) {
title = #"Unknown";
}
// artist currently playing
self.artist = [self.nowPlayingItem valueForProperty:MPMediaItemPropertyArtist];
// if artist is not fund Unknown will be displayed
if (artist == (id)[NSNull null] || artist.length == 0) {
artist = #"Unknown";
}
//[self.currentlyPlaying setLineBreakMode:NSLineBreakByWordWrapping];
// displaying current artist and title song playing
[self.currentlyPlaying setText:[NSString stringWithFormat:#"%# - %#", artist, title]];
}
But, the problem comes when the user leave the app in the background or just use the Control Center to change the song.. My app still displays the previous song information and nothing gets update if the user continues using Control Center or the Music app itself.
I tried to solve the problem in this way...
- (void)viewDidLoad {
[super viewDidLoad];
if (self.myPlayer.playbackState == MPMusicPlaybackStatePlaying || self.myPlayer.playbackState == MPMusicPlaybackStateSeekingForward || self.myPlayer.playbackState == MPMusicPlaybackStateSeekingBackward){
// updating track name regardless the user uses app controllers or not
[self getTrackDescription];
}
}
I even tried commenting the if condition to see if I get the song information in that way but it was the same problem.
Well, I hope someone can help me out and explain what I'm doing wrong..
Thanks in advance...!
UPDATE
This what I have at the moment... My getTrackDescription logic is the same but the signature changed to this - (void)getTrackDescription:(id)notification
- (void)viewWillAppear:(BOOL)animated{
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:#selector(getTrackDescription:)
name:MPMusicPlayerControllerPlaybackStateDidChangeNotification
object:self.myPlayer];
[self.myPlayer beginGeneratingPlaybackNotifications];
}
-(void)viewWillDisappear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMusicPlayerControllerPlaybackStateDidChangeNotification
object:self.myPlayer];
[self.myPlayer endGeneratingPlaybackNotifications];
}
What you're going to want to do is add your view controller as an observer to the MPMusicPlayerControllerNowPlayingItemDidChangeNotification notification, which as it sounds, gets called every time the track changes in the music player. Don't forget to specify when the player should begin/end generating these notifications with the following methods.
[[MPMusicPlayerController iPodMusicPlayer] beginGeneratingPlaybackNotifications];
[[MPMusicPlayerController iPodMusicPlayer] endGeneratingPlaybackNotifications];
This is my complete answer to the problem..
1) I set these two methods.. and set an Observer MPMusicPlayerControllerNowPlayingItemDidChangeNotification which will take care of updating my song information regardless.. with getTrackDescription which still the same as my previous post..
- (void)viewWillAppear:(BOOL)animated{
// creating simple audio player
self.myPlayer = [MPMusicPlayerController iPodMusicPlayer];
// assing a playback queue containing all media items on the device
[self.myPlayer setQueueWithQuery:[MPMediaQuery songsQuery]];
self.notificationCenter = [NSNotificationCenter defaultCenter];
[self.notificationCenter addObserver:self
selector:#selector(getTrackDescription:)
name:MPMusicPlayerControllerNowPlayingItemDidChangeNotification
object:self.myPlayer];
[self.notificationCenter addObserver:self
selector:#selector(handle_PlayBackNotification:)
name:MPMusicPlayerControllerPlaybackStateDidChangeNotification
object:self.myPlayer];
[self.myPlayer beginGeneratingPlaybackNotifications];
}
-(void)viewWillDisappear:(BOOL)animated {
[self.notificationCenter removeObserver:self
name:MPMusicPlayerControllerNowPlayingItemDidChangeNotification
object:self.myPlayer];
[self.notificationCenter removeObserver:self
name:MPMusicPlayerControllerPlaybackStateDidChangeNotification
object:self.myPlayer];
[self.myPlayer endGeneratingPlaybackNotifications];
}
Then the magic will happen by itself.. it just basically what #0x7fffffff recommended me to do but I had to do some digging because I wasn't familiar with notifications at all..
So, just in case if you want to see how I toggle my play/pause button for the Observer MPMusicPlayerControllerPlaybackStateDidChangeNotification this is how I did it..
- (void)handle_PlayBackNotification:(id)notification{
if(myPlayer.playbackState == 1){
// sets the pause image in play button
[self.pauseBtn setBackgroundImage:[UIImage imageNamed:#"pauseBtn2.png"] forState:(UIControlStateNormal)];
} else {
// resets the image to normal play image
[self.pauseBtn setBackgroundImage: nil forState:(UIControlStateNormal)];
}
}
just in case this my getTrackDescription ...
- (void)getTrackDescription:(id)notification {
// getting whats currently playing
self.nowPlayingItem = self.myPlayer.nowPlayingItem;
// song title currently playing
self.title = [self.nowPlayingItem valueForProperty:MPMediaItemPropertyTitle];
// if title is not fund Unknown will be displayed
if (title == (id)[NSNull null] || title.length == 0) {
title = #"Unknown";
}
// artist currently playing
self.artist = [self.nowPlayingItem valueForProperty:MPMediaItemPropertyArtist];
// if artist is not fund Unknown will be displayed
if (artist == (id)[NSNull null] || artist.length == 0) {
artist = #"Unknown";
}
// displaying current artist and title song playing
[self.currentlyPlaying setText:[NSString stringWithFormat:#"%# - %#", artist, title]];
}
I am facing an issue with MPMoviePlayerController in iOS 7. When i single tap on the forward seek button the video stops and not allow to do anything like to play again full screen and slider change.
Here is my code.
remove the Observer for the MPMoviePlayerPlaybackDidFinishNotification
[[NSNotificationCenter defaultCenter] removeObserver:moviePlayerViewController name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayerViewController.moviePlayer];
and add New Notification MPMoviePlayerPlaybackDidFinishNotification
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(videoFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
Here is my custom method to handle the MPMoviePlayerPlaybackDidFinishNotification
-(void)videoFinished:(NSNotification*)aNotification{
MPMoviePlayerController *moviePlayer = [aNotification object];
NSLog(#"%f",moviePlayer.currentPlaybackTime);
int reason = [[[aNotification userInfo] valueForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey] intValue];
if (reason == MPMovieFinishReasonPlaybackEnded) {
}else if (reason == MPMovieFinishReasonUserExited) {
[self performSelector:#selector(dismiss:) withObject:aNotification afterDelay:0.5];
}else if (reason == MPMovieFinishReasonPlaybackError) {
}
}
I need to stop this strange behaviour on single click and continue to play.
Anyone know how to do this?
Thanks.
I think there are no any notifications or event are available on user
interaction with the standard player buttons, and i have to implement
own UI for the player controls. by this way we can then determine the
actions for a single touch, long touch, etc. Then, we can add whatever
functionality like increasing the play rate, or simply seeking to a
time.
This question already has answers here:
Play YouTube videos in iPhone app without using UIWebView?
(5 answers)
Closed 9 years ago.
I'm making this iPhone app that allows people to watch youtube videos and vimeo videos. I was wondering if there's a custom player I can incorporate into my app that will play the video from the youtube link or vimeo link. This has to be iOS 7 compatible as well. Thanks!
Possibly you are looking for AVFoundation.framework. Just add it to your project and you can use its AVPlayer component to allow a total customization of your interface. It would be something like this:
-(void)viewDidLoad {
//prepare player
self.videoPlayer = [AVPlayer playerWithURL:<# NSURL of your youtube video #>];
self.videoPlayer.actionAtItemEnd = AVPlayerActionAtItemEndPause;
//prepare player layer
self.videoPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.videoPlayer];
self.videoPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
self.videoPlayerLayer.frame = self.view.bounds;
[self.view.layer addSublayer:self.videoPlayerLayer];
//add player item status notofication handler
[self addObserver:self forKeyPath:#"videoPlayer.currentItem.status" options:NSKeyValueObservingOptionNew context:NULL];
//notification handler when player item completes playback
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playerItemDidReachEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.videoPlayer.currentItem];
}
//called when playback completes
-(void)playerItemDidReachEnd:(NSNotification *)notification {
[self.videoPlayer seekToTime:kCMTimeZero]; //rewind at the end of play
//other tasks
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:#"videoPlayer.currentItem.status"]) {
//NSLog(#"player status changed");
if (self.videoPlayer.currentItem.status == AVPlayerItemStatusReadyToPlay) {
//player is ready to play and you can enable your playback buttons here
}
}
}
And like normal VC you can add buttons or other items to invoke these methods for playback:
-(IBAction)play:(id)sender {
[self.videoPlayer play];
}
-(IBAction)pause:(id)sender {
[self.videoPlayer pause];
}
Make sure that you remove the observers previously added before you leave the VC or else those are gonna leak:
//remove observers
#try {
[self removeObserver:self forKeyPath:#"videoPlayer.currentItem.status" context:NULL];
}
#catch (NSException *exception) {}
#try {
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.videoPlayer.currentItem];
}
#catch (NSException *exception) {}
A detailed explanation from Apple is available here. Hope you would find it helpful.
1) Youtube uses flash which does not work with native mediaplayer.
2) Native media player either needs a file or it can live stream url which use HTTPLiveStreaming (it does not support RTSP).
In simple words they work on different protocol and can't talk to each other.
However, you can use third party API's to download youtube video and then play but this requires your user to wait until the entire file is downloaded.
I would recommend you to use webview. here is a good article which shows how to do so.
YoutubeHacks is an opensource tool for the same.
I am developing an audio streaming app with the old AudioStreamer from Matt and i am trying to make the interruption (when receive a call) by using :
- (void)MyAudioSessionInterruptionListener(void *inClientData, UInt32 inInterruptionState)
{
AudioStreamer *streamer = (AudioStreamer*)inClientData;
if (inInterruptionState == kAudioSessionBeginInterruption)
{
[streamer stop];
NSLog(#"kAudioSessionBeginInterruption");
}
else if (inInterruptionState == kAudioSessionEndInterruption)
{
[self playpause];
NSLog(#"kAudioSessionEndInterruption");
}
}
My problem is I am trying to call the function "playpause" with the [self playpause]; but I get an error playpause undeclared !
How can I declare playpause inside MyAudioSessionInterruptionListener ?
its not [self playPause] it should be [streamer playpause] assuming the AudioStreamer class is the class with the method...The listener method is a static C function outside your class, therefore you cant call a method on self, since self implies you are inside the instance of the class. If the class with the method is not the AudioStreamer then you are going to have to pass that class along as well in the inClientData argument in order to be able to get a hold of it..
Hope that helps
So after testing all posibility the best was using Notification.
Here the code :
void MyAudioSessionInterruptionListener(void *inClientData, UInt32 inInterruptionState)
{
if (inInterruptionState == kAudioSessionBeginInterruption) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"stopstreamer" object:nil];
NSLog(#"kAudioSessionBeginInterruption");
}
else if (inInterruptionState == kAudioSessionEndInterruption) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"TogglePlayPause" object:nil];
NSLog(#"kAudioSessionEndInterruption");
}
}