How do I know when a UIWebView has exited full screen? - ios

for an iOS app I have a Youtube video which is loaded in using the following HTML/objc
NSString *embedHTML = #"\
<html><head>\
<style type=\"text/css\">\
body {\
background-color: transparent;\
color: white;\
}\
</style>\
</head><body style=\"margin:0\">\
<embed allowScriptAccess=\"always\" id=\"yt\" src=\"%#&enablejsapi=1&playerapiid=yt\" type=\"application/x-shockwave-flash\" \
width=\"262\" height=\"187\"></embed>\
</body></html>";
NSString *html = [NSString stringWithFormat:embedHTML, urlString];
[self.webView loadHTMLString:html baseURL:nil];
Which loads up and plays fine. The issue I'm having is that my app is strictly portrait view and you cannot rotate it while in the app. If you're watching the youtube video the webview does an override (or something like that) that allows the user to rotate for full screen which is fine however if they close / select "Done" on the video and it closes while in landscape the app is all of a sudden in landscape and is severely cut off. How do I prevent this from happening while still allowing landscape playback of video?

In your project settings (App Target > General > Deployment Info > Device Orientation), select Portrait, Landscape Left and Landscape Right.
In your root view controller, add:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
If everything gets loaded into this view controller, that should be all you have to do. If you find that some views are rotating when they shouldn't, add this same code to their view controllers.
The controller for the fullscreen video will use the supported orientations specified in the target settings, and so will allow rotation to landscape. When you close the video, the view will rotate back to portrait.

Related

Is it possible to play a YouTube video on iOS without revealing/adding a view, while still following YouTube's Terms of Service?

I have a UITableView full of thumbnails of YouTube videos, and when they tap on one I want to start playing the YouTube video full screen automatically without the user seeing a view being added or having to interact any further than tapping the thumbnail.
Basically, I don't want to see the YouTube video player with that red play icon at all.
I was planning to use youtube-ios-player-helper/YTPlayerView to accomplish this, and I understand it just employs a UIWebView but I can't seem to figure out how to get it to work.
If I create an instance variable on my class, set myself as the delegate and select a random video for watching:
let YouTubePlayer = YTPlayerView()
override func viewDidLoad() {
super.viewDidLoad()
YouTubePlayer.delegate = self
YouTubePlayer.loadWithVideoId("apKJikXWU2g")
...
}
and then when the delegate method gets called:
func playerViewDidBecomeReady(playerView: YTPlayerView!) {
YouTubePlayer.playVideo()
}
But most of the time it either crashes in my AppDelegate with this message:
Nov 5 23:34:44 rtcreporting[73827] : logging starts...
Nov 5 23:34:44 rtcreporting[73827] : setMessageLoggingBlock: called
Or it will work if I disable breakpoints but I get a ton of Auto Layout constraint complaint messages before the video plays, indicating something is angry on some level.
Is this because I'm using a UIView subclass without actually adding it to the view hierarchy?
How would I accomplish the behaviour of autoplaying a YouTube video after a certain event without revealing a kludgy intermediary view?
Here you go, you don't have to see the youtube logo.
Define youtube iFrame, You'll need to replace the '%#' part with your youtube Video ID later when you supply to a UIWebView
#define youtubeVideoPlayUrl
#"<html><head><style>body{margin:0px 0px 0px 0px;}</style></head> <body> <div id=\"player\"></div> <script> var tag = document.createElement('script'); tag.src = 'http://www.youtube.com/player_api'; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); var player; function onYouTubePlayerAPIReady() { player = new YT.Player('player', { width:'%f', height:'%f', videoId:'%#', events: { 'onReady': onPlayerReady } }); } function onPlayerReady(event) { event.target.playVideo(); } </script> </body> </html>"
Define a UIWebView object of name videoWebView to display the iFrame. You can set the height and width to be zero so it doesn't block your screen. It's like a hidden iFrame.
self.videoWebview = [UIWebView alloc] init];
I suggest you to use your own default Image and a play button on top of the image to avoid having to show 'Youtube' video logo. Once you've done that, use the following code to play the youtube video full screen
- (void)onPlayYouTubeVideo:(UIButton *)sender
{
NSString *youtubeVideoID = YOUR_YOUTUBE_VIDEO_ID;
NSString *html = [NSString stringWithFormat:youtubeVideoPlayUrl,
_videoWebView.frame.size.width, _videoWebView.frame.size.height, youtubeVideoID];
_videoWebView.mediaPlaybackRequiresUserAction = NO;
_videoWebView.delegate = self;
[_videoWebView loadHTMLString:html baseURL:[[NSBundle mainBundle] resourceURL]];
}
I'm using like this for a hotel booking app.
I've created a demo app for you.
Source code to load webView html taken from: http://iphoneincubator.com/blog/audio-video/how-to-play-youtube-videos-within-an-application
ViewController header file
#interface ViewController : UIViewController
#property (nonatomic, strong) UIWebView *webView;
#end
ViewController implementation file
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 300, 200)];
self.webView.layer.borderWidth = 1.0;
self.webView.layer.borderColor = [UIColor redColor].CGColor;
self.webView.backgroundColor = [UIColor blackColor];
self.webView.center = self.view.center;
[self.view addSubview:self.webView];
NSString* embedHTML = #"\
<html><head>\
<style type=\"text/css\">\
body {\
background-color: transparent;\
color: white;\
}\
</style>\
</head><body style=\"margin:0\">\
<embed id=\"yt\" src=\"%#\" type=\"application/x-shockwave-flash\" \
width=\"%0.0f\" height=\"%0.0f\"></embed>\
</body></html>";
NSURL *url = [NSURL URLWithString:#"https://www.youtube.com/watch?v=K14RnTVt194"];
NSString* html = [NSString stringWithFormat:embedHTML, url, self.webView.frame.size.width, self.webView.frame.size.height];
[self.webView loadHTMLString:html baseURL:nil];
}
You should see this:
When you press the play button it goes full screen.
You probably want to create a method that accepts a URL to the youtube video in your custom cell class.
Then in the cellForRowAtIndexPath: method of your View Controller, you can call your custom cell loadYouTubeVideoWithURL: method to load the Youtube video url from your data source.
The YouTube Helper Library is definitely a nice way to embed Youtube in your iOS application while following YouTube's Terms of Service.
Regarding the Auto Layout constraints log warnings,
Is this because I'm using a UIView subclass without actually adding it to the view hierarchy?
These errors have nothing to do with your implementation and are easily reproducible.
You can create an empty iOS 8 project, add a UIWebView in your interface and try to load a Youtube page.
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"YOUTUBE_URL"]]];
You'll get the same Auto Layout constraints log messages that you got when using the YouTube Helper Library.
If you take a closer look at the elements having Auto Layout constraints problems, you'll see AVAudioOnlyIndicatorView, AVUnsupportedContentIndicatorView, AVExternalPlaybackIndicatorView, etc. The constraints with warnings are not related to views you created but are related to Apple's internal views structure. It has nothing to do with the YouTube Helper Library or your implementation.
You should definitely file a report: https://bugreport.apple.com
These warnings won't get your app rejected or lessen your chance to get your app approved until the issue is fixed from Apple, especially if you can get the warnings using an empty project with a UIWebView loading any Youtube page.

YTPlayerView - Autorotation support to YTPlayerView

I am using YTPlayerView classes to play YouTube videos. Below is the code i am using to load video according to device screen size (large size for iPad and small size for iPhone). And it is working fine.
Problem --
When i change device mode to landscape, i want larger YTPlayerView then in portrait mode. For now video has same size for both screen modes.
- (BOOL)loadWithPlayerParams:(NSDictionary *)additionalPlayerParams {
NSDictionary *playerCallbacks = #{
#"onReady" : #"onReady",
#"onStateChange" : #"onStateChange",
#"onPlaybackQualityChange" : #"onPlaybackQualityChange",
#"onError" : #"onPlayerError"
};
NSMutableDictionary *playerParams = [[NSMutableDictionary alloc] init];
[playerParams addEntriesFromDictionary:additionalPlayerParams];
if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
{
[playerParams setValue:#"551px" forKey:#"height"];
[playerParams setValue:#"768px" forKey:#"width"];
}
else
{
[playerParams setValue:#"250px" forKey:#"height"];
[playerParams setValue:#"320px" forKey:#"width"];
}
-----
-----
}
I can not use this check to give larger size to view, because above code does not called in-between video play.
if([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscape)
Do you people have any idea how to fix this problem? Or if there is any other solution using JavaScript and css as html string to webView.
YTPlayerView actually uses webview to play the viedo, so you can only use css or javascript to change the size. There should be an html file named "YTPlayerView-iframe-player.html" in the Assets folder.
here is the css sample:
<style>
body { margin: 0; width:100%%; height:100%%; }
html { width:100%%; height:100%%; }
</style>
I have used YTPlayer in my story board and have put proper contraints on it as i'm using autolayouts in my project. It's working fine for me in both landscape and portrait mode.. I think the solution to your issue is autolayouts

iOS: How to disable or handle next and previous buttons in UIWebView HTML5 movie player

In my iOS Phonegap application, we are playing youtube video inside a UIWebView using a cordova plugin. Below is the code I am using to embed the youtube video in UIWebView. We are using iFrame tag to embed the video.
customWebView= [[UIWebView alloc]initWithFrame:CGRectMake(0, 0, 512, 374)];
customWebView.delegate=self;
customWebView.scrollView.bounces=NO;
[customWebView setOpaque:NO];
customWebView.backgroundColor = [UIColor clearColor];
[webViewBackground addSubview:customWebView];
NSString* embedHTML = #"<html><head>\
<style type=\"text/css\">\body {\background-color: #000000;\
color: white;}</style></head><body style=\"margin:0\">\
<iframe width=\"512\" height=\"374\" src=\"%#\" frameborder=\"0\" allowfullscreen></iframe></body></html>";
NSString* html = [NSString stringWithFormat:embedHTML, urlVideo];
[customWebView loadHTMLString:html baseURL:nil];
The video is playing perfectly fine. Both in normal mode and full screen mode. But in full screen mode, user can see the previous and next buttons. On click of next and previous button few times, the video is getting over and I can see only a black screen in webview.
Below are the screenshots.
Is there anyway we can disable the next and previous buttons in a iFrame video player? Or Is there any other way in which we can handle this?

Removing scrubber and timestamp from YouTube video embedded in UIWebView

I have a YouTubeView in an app I am making and I am trying to disable some of the video controls that are appearing, I have seen another App do it where it only displays the Play/Pause and Fullscreen icons. Some of the videos I am rendering are quite small (200x150) so the scrubber is useless and the time is actually overlapping itself.
The function I am using is:
- (YouTubeView *)initWithStringAsYouTubeId:(NSString *)idString frame:(CGRect)frame;
{
if (self = [super init])
{
self.frame = frame;
self.delegate = self;
// HTML to embed YouTube video
NSString *embedHTML = #"\
<html><head>\
<style type=\"text/css\">\
body {\
background-color: transparent;\
color: transparent;\
}\
</style>\
</head><body style=\"margin:0\">\
<embed id=\"yt\" src=\"http://www.youtube.com/v/%#\" type=\"application/x-shockwave-flash\" \
width=\"%0.0f\" height=\"%0.0f\"></embed>\
</body></html>";
// Populate HTML with the URL and requested frame size
NSLog(#"%f", frame.size.height);
NSString *html = [NSString stringWithFormat:embedHTML, idString, frame.size.width, (frame.size.height*-1.0f)];
// Load the html into the webview
[self loadHTMLString:html baseURL:nil];
}
return self;
}
It loads and plays fine but I just want to disable the scrubber and times, I have tried ?controls=0 with no luck.
Cheers,
Dean
To be able to hide the scrubber and other controls, remove your <embed> tag and replace it with its <iframe> equivalent, like this (I've set it up using the parameters/attributes from your example code):
<iframe id=\"yt\" type=\"text/html\" src=\"http://www.youtube.com/embed/%#?controls=0\" width=\"%0.0f\" height=\"%0.0f\" frameborder=\"0\"></iframe>
'controls=0' used with <iframe> will hide the controls for you.
In my brief experience with iOS embedded video, it seems like a solution to one problem often causes grief with something else that was previously working fine. Case in point: the above example hides the controls, but will overlay the video's title at the top-left of the UIWebView. The solution is to use this for your video's parameter list: '?controls=0&showinfo=0'
To see the scoop on the 'showinfo' parameter and others, check out the docs at: https://developers.google.com/youtube/player_parameters#Parameters Not everything in the parameter docs works in the iOS <iframe>, but play around with some of them and you might find something useful.
For what it's worth (and this might be obvious to expert web coders, which I am not), you don't have to assign the 'id' attribute to be 'yt', but most every example I've seen does this; 'yt' is no magic value, you can set the id to be whatever makes sense to you.
Is there a reason you don't use MPMoviePlayerController?
Using MPMoviePlayerController, you would simply create a UIView in your nib that is the size you want to player to be. Then alloc/init the player and set its frame to be the frame of the view. Using MPMoviePlayerController gives you access to a property to show/hide the controls. Additionally, you get all the great delegate methods telling you when video stops, if the users goes into or out of full screen, etc.

Text in UIWebView changes size or weight on device rotation

I have a UIWebView which at the moment displays a very simple HTML string. It looks fine in portrait but in landscape the text changes - the font looks heavier which is not what I want. See the image bellow:
The top line is what is shown in portrait and the bottom what is shown in landscape. The text is Chinese but the problem is the same with English.
Here is my code:
- (void)displayText
{
[self.myWebView loadHTMLString:#"<html style=\"-webkit-text-size-adjust: none; font-size-adjust:none; \"><head><meta name=\"viewport\" content=\"width=device-width; initial scale=1.0; maximum-scale=1.0;\"></head><body style=\"background-color:#FFFFFF; font-size:28px; color:#DDDDDD;\">你好。你好。你好。你好。你好。你好。你好。你好。</body></html> " baseURL:[NSURL URLWithString:#""]];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[self.myWebView reload];
}
Any ideas what I am doing wrong?
THANK YOU!
This CSS works for me:
-webkit-transform: translate3d(0,0,0);
I found the answer here:
UIWebView font is thinner in portrait than landscape
UPDATE:
One issue with the above CSS is there is some delay before text is rendered if the HTML is reloaded. I have found that setting the UIWebView's opaque property to FALSE works better:
self.myWebView.opaque = FALSE;
This seems like a bit of a hack. Hopefully there is a better solution.

Resources