How to receive NSNotifications from UIWebView embedded YouTube video playback
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 public MPMoviePlayerController
in many aspects (e.g. DRM).
The most important classes used for playing video content within that UIWebView
are called MPAVController
and UIMoviePlayerController
. The latter one makes the player appear like the MPMoviePlayerController
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 using UIMoviePlayerControllerWillExitFullscreenNotification
.
C-Language Level:
void PlayerWillExitFullscreen (CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
//do something...
}
CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(),
NULL,
PlayerWillExitFullscreen,
CFSTR("UIMoviePlayerControllerWillExitFullscreenNotification"),
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
Objective-C Level:
- (void)playerWillExitFullscreen:(NSNotification *)notification
{
//do something...
}
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerWillExitFullscreen:)
name:@"UIMoviePlayerControllerWillExitFullscreenNotification"
object:nil];
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 the userInfo
which may look like this:
{
MPAVControllerNewStateParameter = 1;
MPAVControllerOldStateParameter = 2;
}
Further Reverse Engineering
For reverse engineering and exploring all the notifications sent, use the following snippet.
void MyCallBack (CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
NSLog(@"name: %@", name);
NSLog(@"userinfo: %@", userInfo);
}
CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(),
NULL,
MyCallBack,
NULL,
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
Media Callbacks with Embedded YouTube Videos on iOS
you can inject javascript into a UIWebView
(see http://iphoneincubator.com/blog/windows-views/how-to-inject-javascript-functions-into-a-uiwebview)... other interesting stuff about javascript and UIWebView
can be found here and here.
try using this together with this experimental youtube API (see http://code.google.com/apis/youtube/iframe_api_reference.html)... this should be able to get you what you want.
Another useful resource for this to make a callback from javascript to your code is here.
Allow UIInterfaceOrientationLandscape during UIWebView video playback
I figured it out. In my 2 methods:
-(void)youTubeStarted:(NSNotification *)notification{
// Entered Fullscreen code goes here..
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.fullScreenVideoIsPlaying = YES;
}
-(void)youTubeFinished:(NSNotification *)notification{
// Left fullscreen code goes here...
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.fullScreenVideoIsPlaying = NO;
//CODE BELOW FORCES APP BACK TO PORTRAIT ORIENTATION ONCE YOU LEAVE VIDEO.
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
//present/dismiss viewcontroller in order to activate rotating.
UIViewController *mVC = [[UIViewController alloc] init];
[self presentModalViewController:mVC animated:NO];
[self dismissModalViewControllerAnimated:NO];
}
I accessed my App delegate in the above methods by setting the BOOL property of my AppDelegate. Then I called the application method below in my AppDelegate.m:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
if (self.fullScreenVideoIsPlaying == YES) {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
else {
if(self.window.rootViewController){
UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
orientations = [presentedViewController supportedInterfaceOrientations];
}
return orientations;
}
}
The self.fullScreenVideoIsPlaying
is a BOOL
that I set as a property in my AppDelegate.h file.
I hope this helps others the 5 hours I lost figuring it out.
UIMoviePlayerControllerDidEnterFullscreenNotification doesn't work in iOS8
The implementation by markussvensson has some false alarms, since any UIWindowDidBecomeVisibleNotification is considered as a full screen video playback which is not true.
The implementation "AVPlayerItemBecameCurrentNotification" by Selvin can catch movie playback start, but cannot catch movie playback stop.
So I combined both implementations and it works as expected.
Add observer to both AVPlayerItemBecameCurrentNotification & UIWindowDidBecomeHiddenNotification;
When AVPlayerItemBecameCurrentNotification happens, set a flag;
When UIWindowDidBecomeHiddenNotification happens, check the flag to see if it is a "video stop playing event".
BTW, AVPlayerItemBecameCurrentNotification is undocumented and might be broken for the next iOS major release.
How to embed YouTube video on iOS and play it directly on UIWebView without full screen?
If anyone is still facing this problem, below is by far the best solution I have seen. Works like a charm.
self.webView = [[UIWebView alloc] initWithFrame:CGRectMake(10, 10,300, 200)];
[self.webView setAllowsInlineMediaPlayback:YES];
[self.webView setMediaPlaybackRequiresUserAction:NO];
[self.view addSubview:self.webView];
NSString* embedHTML = [NSString stringWithFormat:@"\
\
\
\
<script type='text/javascript'>\
function onYouTubeIframeAPIReady()\
{\
ytplayer=new YT.Player('playerId',{events:{onReady:onPlayerReady}})\
}\
function onPlayerReady(a)\
{ \
a.target.playVideo(); \
}\
</script>>
Source: https://code.google.com/p/gdata-issues/issues/detail?id=5204
Play YouTube videos with MPMoviePlayerController instead of UIWebView
The only way to have a youtube video play inside your own app is to create a UIWebView
with the embed tag from Youtube for the movie you want to play as the UIWebView's
content. UIWebView
will detect that the embedded object is a Youtube link, and the web view's content will be the youtube preview for the video. When your user clicks the preview, the video will be shown in an MPMoviePlayerController. This is the technique described at the link that Muxecoid provided (how to play youtube videos within an application), and this is (as far as I know of) the only way to have a youtube video play within an application. You can still have the Youtube application launch by passing the youtube URL to -[UIApplication openURL:]
, but of course this closes your own application which is often undesirable.
Unfortunately, there's no way to directly play a youtube video with MPMoviePlayerController
because youtube does not expose direct links to the video files.
Related Topics
Ios 6: How to Restrict Some Views to Portrait and Allow Others to Rotate
Ineligible Devices Section Appeared in Xcode 6.X.X
How to Share an Image on Instagram in Ios
Uinavigationbar Custom Back Button Without Title
Closure Cannot Implicitly Capture a Mutating Self Parameter
How to Display Image in iOS Push Notification
Swift Nsdateformatter Not Working
Correct Singleton Pattern Objective C (Ios)
Ld: File Not Found: Linker Command Failed with Exit Code 1
Warning :-Presenting View Controllers on Detached View Controllers Is Discouraged
Dismiss Keyboard by Touching Background of Uitableview
Uisplitviewcontroller in Portrait on Iphone Shows Detail Vc Instead of Master
Uicollectionview Inside a Uitableviewcell - Dynamic Height
Detecting Color of Iphone/Ipad/Ipod Touch
Background-Size: Cover Not Working on iOS
Changing Specific Text's Color Using Nsmutableattributedstring in Swift
Codesign Error: Provisioning Profile Cannot Be Found After Deleting Expired Profile