I didn't received any notifications for MPMoviePlayerController
. What am I doing wrong?
I use following logic.
I'm begining to play youtube video in UIWebView
. UIWebView
calls a standard MPMoviePlayerController
. I don't control MPMoviePlayerController
because I didn't instantiate MPMoviePlayerController
.
I run youtube's clip with autoplay (1 second delay):
[self performSelector:@selector(touchInView:) withObject:b afterDelay:1];
My code is:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loadStateDidChange:) name:MPMoviePlayerLoadStateDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackDidFinish:) name:MPMoviePlayerDidExitFullscreenNotification object:nil];
[self embedYouTube];
}
- (void)loadStateDidChange:(NSNotification*)notification
{
NSLog(@"________loadStateDidChange");
}
- (void)playbackDidFinish:(NSNotification*)notification
{
NSLog(@"________DidExitFullscreenNotification");
}
- (void)embedYouTube
{
CGRect frame = CGRectMake(25, 89, 161, 121);
NSString *urlString = [NSString stringWithString:@"http://www.youtube.com/watch?v=sh29Pm1Rrc0"];
NSString *embedHTML = @"<html><head>\
<body style=\"margin:0\">\
<embed id=\"yt\" src=\"%@\" type=\"application/x-shockwave-flash\" \
width=\"%0.0f\" height=\"%0.0f\"></embed>\
</body></html>";
NSString *html = [NSString stringWithFormat:embedHTML, urlString, frame.size.width, frame.size.height];
UIWebView *videoView = [[UIWebView alloc] initWithFrame:frame];
videoView.delegate = self;
for (id subview in videoView.subviews)
if ([[subview class] isSubclassOfClass: [UIScrollView class]])
((UIScrollView *)subview).bounces = NO;
[videoView loadHTMLString:html baseURL:nil];
[self.view addSubview:videoView];
[videoView release];
}
- (void)webViewDidFinishLoad:(UIWebView *)_webView
{
UIButton *b = [self findButtonInView:_webView];
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(touchInView:) object:b];
[self performSelector:@selector(touchInView:) withObject:b afterDelay:1];
}
- (UIButton *)findButtonInView:(UIView *)view
{
UIButton *button = nil;
if ([view isMemberOfClass:[UIButton class]]) {
return (UIButton *)view;
}
if (view.subviews && [view.subviews count] > 0)
{
for (UIView *subview in view.subviews)
{
button = [self findButtonInView:subview];
if (button) return button;
}
}
return button;
}
- (void)touchInView:(UIButton*)b
{
[b sendActionsForControlEvents:UIControlEventTouchUpInside];
}
UPDATE: I'm creating application that plays youtube's video. You can run playlist and you will see first video. When first video has ended, second video begins play automatically and so on.
I need to support ios 4.1 and above.
UPDATE2: @H2CO3 I'm trying to use your url-scheme, but it don't works. Delegate method didn't called on exit event. I added my html url to log. It is:
<html><head> <body style="margin:0">
<script>function endMovie()
{document.location.href="somefakeurlscheme://video-ended";}
</script> <embed id="yt" src="http://www.youtube.com/watch?v=sh29Pm1Rrc0"
onended="endMovie()" type="application/x-shockwave-flash"
width="161" height="121"></embed>
</body></html>
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if ([[[request URL] absoluteString] hasPrefix:@"somefakeurlscheme://video-ended"])
{
[self someMethodSupposedToDetectVideoEndedEvent];
return NO; // prevent really loading the URL
}
return YES; // else load the URL as desired
}
UPDATE3 @Till, I cann't caught UIMoviePlayerControllerDidExitFullscreenNotification, but I found MPAVControllerItemPlaybackDidEndNotification. MPAVControllerItemPlaybackDidEndNotification appears when playback video is ended.
But I don't understand how do I catch onDone notifications?
This works for me in iOS 6.1, it hides/removes other windows when the AVPlayerItemDidPlayToEndTimeNotification is received:
Based on the @H2CO3 answer but with the iframe API. It was the only way I could make it work.
This doesn't use any private API which makes it more future proof.
Here's the code to embed your Youtube video. Check the API for more ways to customise this.
And this is how you get notified that the video ended (UIWebViewDelegate method).
For iOS8 (Also I have an embedded video that is not a youtube video) the only solution I could get to work was to catch either one of
viewWill/DidLayoutSubviews
, and as an added bonus you don't need to change the HTML or use any private APIs :So basically:
In my case my web view is inside a
UITableViewCell
so I had to find a way to communicate between the cell and the view controller, and to also avoid using a BOOL flag I did this:in ViewDidLoad add the following code
The following methods are for showing the message/functions for respective process of entering/exiting to/from full screen
There are no documented notifications sent by the
UIWebView
embedded movie player.In fact, the closed implementation used within the
UIWebView
does differ from the publicMPMoviePlayerController
in many aspects (e.g. DRM).The most important classes used for playing video content within that
UIWebView
are calledMPAVController
andUIMoviePlayerController
. The latter one makes the player appear like theMPMoviePlayerController
fullscreen interface.In case you dare to risk a rejection by Apple, there are actually ways to still achieve what you are looking for.
NOTE This is not documented and is subject to break on each and every new iOS release. It does however work on iOS4.3, 5.0 and 5.01, 5.1 and 6.0 and it may work on other versions as well.
I am not able to test this solution on iOS 4.1 and 4.2, so that is up to you to do. I highly suspect that it will work.
Fullscreen State
If, for example you are intending to react upon the user tapping the DONE button, you may be able to do it this way:
UPDATE The old version of this answer recommended to use
UIMoviePlayerControllerDidExitFullscreenNotification
whereas this new version (updated for iOS6) recommends usingUIMoviePlayerControllerWillExitFullscreenNotification
.C-Language Level:
Objective-C Level:
I did draft both, C-Level and Objective-C-Level options because the best way to actually find out about all of this is to use C-Level (CoreFoundation) functions as shown at the end of my answer. If the sender of a notification does not use Objective-C (NSNotifications), you may actually not be able to trap them using the NSNotification-mechanics.
Playback State
For examining the playback state, look out for
"MPAVControllerPlaybackStateChangedNotification"
(as drafted above) and examine theuserInfo
which may look like this:Further Reverse Engineering
For reverse engineering and exploring all the notifications sent, use the following snippet.
In iOS 4.3+ you can use the
UIMoviePlayerControllerDidEnterFullscreenNotification
andUIMoviePlayerControllerDidExitFullscreenNotification
notifications: