I'm trying to embed a Youtube video using a mixture of this technique, and this Youtube SDK blog post in a universal app. The iPhone version, using the same code, works fine.
On the iPad the video does embed, and it plays fine in it's embedded form, but as soon as you tap the full screen button the app crashes (buttons do not respond, the device does not rotate). The music from the Youtube video keeps playing.
There is no error message logged but the app does register as 'Paused' or hung in xCode. Every time it crashes com.apple.libdispatch-manager is on thread 2. Ask me questions and I'll give you more information about the error, but I'm not sure where to start.
I have tried:
changing the size of the UIWebView frame
the UIWebView is in a UIScrollView, but if I take it out of the scrollview and add it to the view the problem is identical.
changing the video
changing the html that I use in the UIWebView from this to this, with no result
changing the format of the youtube link from ?v=uniqueID to /v/uniqueID
checking the presenting view is the rootviewcontroller (it is, but the video is embedded in a modal, which is not the rootviewcontroller).
I am building for iOS 5.1, this doesn't happen if running on iOS6.
The View that the video is embedded in is modal, both on the phone and the iPad. There's no hackery or unusual things happening in the app.
There seems to be talk of Evernote's app having a similar problem, but I don't know if it is related or not.
For your reference, here is the YouTubeView subclass (which subclasses UIWebView):
- (YouTubeView *)initWithStringAsURL:(NSString *)urlString frame:(CGRect)frame;
{
if (self = [super init])
{
// Create webview with requested frame size
self = [[YouTubeView alloc] initWithFrame:frame];
// HTML to embed YouTube video
// NSString *youTubeVideoHTML = #"<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 *youTubeVideoHTML = #"<html><head><meta name = \"viewport\" content = \"initial-scale = 1.0, user-scalable = no, width = %0.0f\"/></head><body style=\"background:#FFF;margin-top:0px;margin-left:0px\"><div><object width=\"%0.0f\" height=\"%0.0f\"><param name=\"movie\" value=\"%#\"></param><param name=\"wmode\" value=\"transparent\"></param><embed src=\"%#\"type=\"application/x-shockwave-flash\" wmode=\"transparent\" width=\"%0.0f\" height=\"%0.0f\"></embed></object></div></body></html>";
// Populate HTML with the URL and requested frame size
// NSString *html = [NSString stringWithFormat:youTubeVideoHTML, urlString, frame.size.width, frame.size.height];
NSLog(#"html:\n %#", youTubeVideoHTML);
NSString *html = [NSString stringWithFormat:youTubeVideoHTML, frame.size.width, frame.size.width, frame.size.height, urlString, urlString, frame.size.width, frame.size.height];
NSLog(#"html:\n %#", html);
// Load the html into the webview
[self loadHTMLString:html baseURL:nil];
}
return self;
}
Modal view on iOS 5.0 and iOS 5.1 is the problem that causes crash on full screen video, AFAIK. They just changed hierarchy of views in that version of iOS (parentViewController and presentingViewController) and that is the aftermath. I asked about it long time ago here and one more same question is here and still no one knows what to do.
First of all, they fixed it in 6.0, I guess, that's good.
For 5.1 we changed design a little and avoided modal view. Do it, if it is possible in your situation.
Related
I had tried to play video using vlckit for mac os x,
using below code but , i am unable to see video, after compiling i am having black screen but no video is playing.
here a.mp4 is my video inside main bundle , i had cheacked that videos path is correct.
let me know what is the issue why i am not able to see video on screen.
// Set up a videoView by hand. You can also do that in the nib file
videoView = [[VLCVideoView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)];
[self.view addSubview:videoView];
[videoView setAutoresizingMask: NSViewHeightSizable|NSViewWidthSizable];
// Init the player object
player = [[VLCMediaPlayer alloc] initWithVideoView:videoView];
[player setMedia:[VLCMedia mediaWithPath:#"/Users/gurpalrajput/Desktop/demoVlc Player/demoVlc Player/a.mp4"]];
[player play];
That path looks wrong; for a resource inside a macOS application I would expect something like /path/to/Application.app/Contents/Resources/a.mp4. You're not on iOS anymore... ;)
Generally you want to resolve paths to resources inside the application bundle programmatically; for the movie that would be:
NSString* path = [NSBundle.mainBundle pathForResource:#"a" ofType:#"mp4"];
I am experiencing an issue when using the iPad Camera in iOS 8. I've seen some older questions and a thread on the Apple Developer Forums from during the beta but still haven't find a solution.
There seems to be two parts to this issue.
1) The camera itself rotates when the device orientation rotates, eg the world is on its side
2) When opening the camera in Landscape, the overlay does not appear. When opened in Portrait it is fine.
It is an app using iOS7 as the Base SDK, problem only occurs when running the app on a device that has been upgraded to iOS8. The app is not using storyboards, it is using nibs.
I'm hoping to push out a fix for this with Xcode 5.1.1 before moving onto the iOS8 specific fixes and using it as a Base SDK in the next version.
Here is my code to bring up the camera:
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] == YES) {
// Create Camera
imagePicker = [[UIImagePickerController alloc] init];
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.delegate = self;
imagePicker.showsCameraControls = NO;
// Set up custom controls view
[[NSBundle mainBundle] loadNibNamed:#"OverlayView" owner:self options:nil];
self.overlayView.frame = imagePicker.cameraOverlayView.frame;
imagePicker.cameraOverlayView = self.overlayView;
self.overlayView = nil;
// Show Camera
[self presentViewController:imagePicker animated:NO completion:nil];
[imagePicker release];
}
I have also tried
And the Layout of the Toolbar (sitting at the bottom) of the OverlayView:
If I change that to sit "at the top" it appears in both portrait and landscape! So it must have to do with the view/window/something size, though it's strange how its behaviour would change when the layout has stayed the same.
I have tried it with both showsCameraControls = YES and hashing out the OverlayView block, and problem #1 persists so it's not to do with the overlay at app.
I'm hoping someone has found an answer to this, it seems like quite a common problem.
Please let me know if you need any further details.
Edit 1: Fixed the Overlay (Issue #2)
It wasn't applying the orientation to the OverlayView, fixed it like this:
// Grab the window frame and adjust it for orientation - from http://stackoverflow.com/a/15707997/520902
UIView *rootView = [[[UIApplication sharedApplication] keyWindow]
rootViewController].view;
CGRect originalFrame = [[UIScreen mainScreen] bounds];
CGRect screenFrame = [rootView convertRect:originalFrame fromView:nil];
...
self.overlayView.frame = imagePicker.cameraOverlayView.frame;
I suspect that it's related to the camera not realising it's orientated too, will keep searching for a fix for Problem #1.
Edit 2: Update on Issue #1
Looks like the camera rotating might be an Apple issue. On iOS8 if you open up the Contacts app, edit a contact and choose 'Take Photo', the exact same issue occurs - in a default Apple app!
I still can't find a fix so I am just destroying and recreating the imagePicker on each orientation change for now, it's ugly but will suffice until Apple release a fix or a better solution pops up.
Apple fixed this problem in iOS 8.1.
In iOS5 i want to load Youtube movies, and i done it with:
- (void)embedYouTube:(NSString *)urlString frame:(CGRect)frame {
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>";
NSString *html = [NSString stringWithFormat:embedHTML, urlString, frame.size.width, frame.size.height];
videoView = [[UIWebView alloc] initWithFrame:frame];
[videoView loadHTMLString:html baseURL:nil];
[self.view addSubview:videoView];
}
calling by:
[self embedYouTube:#"http://www.youtube.com/v/PqtUSSdf8b4" frame:CGRectMake(0, 0, self.view.frame.size.width, 100)];
And i have standard Youtube frame with "done" button. When i hit done button i'm redirect to my root VC. why? how can i get to my VC (the one when i'm calling it) ?
And more important - how to catch "done button" event ?
EDIT:
I have MainVC and DetailVC. MainVC calls DetailVC as a ModalViewController. From there I call this embedYouTube method. When i'm hitting done on this screen:
i'm returning to MainVC not DetailVC. Why? How to catch this event?
EDIT:
And iOS 6 displays only black background - nothing. Why?
The fullscreen video player will dismiss when you tap the done button, this is encapsulated into that full screen player which the system automatically presents as part of this youtube/flash safari embed trick. You shouldn't try to do anything when this is used.
About iOS 6 - iOS 6 no longer supports this way of embedding YouTube videos in your application (source)
As of iOS 6, embedded YouTube URLs in the form of
http://www.youtube.com/watch?v=oHg5SJYRHA0 will no longer work. These
URLs are for viewing the video on the YouTube site, not for embedding
in web pages. Instead, the format that should be used is described
here: https://developers.google.com/youtube/player_parameters.
The behavior of "DONE" button by default is that it dismisses all the modal view controllers, as you are presenting the DetailVC modally, so its also dismissed, you need to change the presenting method of DetailVC. Try simply by pushViewController.
I'm developing on iOS SDK 4.3.
I have an horizontally-scrolling paged gallery that can display images or videos from a remote feed. For the paged views I'm using the publicly available ATPagingView: pages are reused similarly to TableViewCells. But for the videos I'm using a single MPMoviePlayerController, whose .view property I assign to the several pages as a subview (I know, I know...):
moviePlayerController = [[MPMoviePlayerController alloc] init];
moviePlayerController.repeatMode = MPMovieRepeatModeNone;
moviePlayerController.controlStyle = MPMovieControlStyleEmbedded;
moviePlayerController.shouldAutoplay = false;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(movieLoadStateChangeAction:) name:MPMoviePlayerLoadStateDidChangeNotification object:nil];
You can see I've registered for MoviePlayer event LoadState notifications.
When a new page goes onscreen, I start loading a video if needed:
- (void)currentPageDidChangeInPagingView:(ATPagingView *)pagingView
{
if (pagingView.currentPageIndex < 0)
return;
NSLog(#"currentPageDidChangeInPagingView");
GalleryPageView *currentPage = (GalleryPageView *)[pagingView viewForPageAtIndex:pagingView.currentPageIndex];
if (![currentPage.gestureRecognizers count]) {
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(resetZoom)];
recognizer.numberOfTapsRequired = 2;
[currentPage.zoomView addGestureRecognizer:recognizer];
recognizer.delegate = self;
[recognizer release];
}
moviePlayButton.hidden = YES;
[activityView stopAnimating];
FeedItem *feedItem = (FeedItem *)[dataRoot objectAtIndex:pagingView.currentPageIndex];
if (feedItem.contentType == FeedContentTypeMovie) {
moviePlayerController.contentURL = [NSURL URLWithString:feedItem.movieUrl];
[moviePlayerController prepareToPlay];
[activityView startAnimating];
}
Now, IFF the first page contains a video, even after I call moviePlayerController.prepareToPlay, it doesn't load: no loadState event is fired. Following pages instead work as expected.
I've tried to pre-load a fixed video on MPlayerController initialization, but in that case the fixed video is correctly loaded (MPMovieLoadState == 3), while video on first page causes a change to MPMovieLoadStateUnknown.
The movie URL is correct.
When I scroll back from page 2 to page 1, first video is loaded (MPMovieLoadState == 3), but it doesn't show.
What do you suggest investigating? Is the shared-view architecture so horrible? It works for the following pages, after all. Is there any known weird behavior by prepareToPlay? For example, is it possible MPC gets angry if the view is "mistreated" by anyone, and then it refuses to load stuff? How else would you explain MPMovieLoadStateUnknown? I'm pretty sure there is no other ghost instance of MPC messing around (I've read it could be a problem).
Thank you and sorry for the long post.
I had to end up using AVPlayer because of something very similar to this in my code.
I had the same problem. In iOS7 this does not happen, but in iOS 6 loadState is 3, which is not contemplated in:
enum {
MPMovieLoadStateUnknown = 0,
MPMovieLoadStatePlayable = 1 << 0,
MPMovieLoadStatePlaythroughOK = 1 << 1, // Playback will be automatically started in this state when shouldAutoplay is YES
MPMovieLoadStateStalled = 1 << 2, // Playback will be automatically paused in this state, if started
};
typedef NSInteger MPMovieLoadState;
I had autoplay set to NO and use prepareToPlay waiting for the notifications to play, so when MPMoviePlayerLoadStateDidChangeNotification is received, before playing, I check the loadState like this:
if (self.moviePlayerC.loadState & MPMovieLoadStatePlayable || self.moviePlayerC.loadState & MPMovieLoadStatePlaythroughOK)
Maybe in iOS6 loadState is a bitWise value that can contains several states at the same time.
I'm a newbie to iPhone development and just started on developing an application that contains a UITableView where each cell consisting of youtube video thumbnails in the form of webviews. For embedding YouTube Player on iPhone, I have used the follwing piece of code.
- (void)embedYouTube:(NSString*)url frame:(CGRect)frame {
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>";
NSString* html = [NSString stringWithFormat:embedHTML, url, frame.size.width, frame.size.height];
if(videoView == nil) {
videoView = [[UIWebView alloc] initWithFrame:frame];
[self.view addSubview:videoView];
}
[videoView loadHTMLString:html baseURL:nil];
}
Now that I can see the thumbnail on the tableviewcell and once I tap on the thumbnail, YouTube player opens and play the movie.
My thumbnail occupies only a small portion of the cell and the rest of the area of the cell contains some text descriptions. My problem is that I must tap exactly on the thumbnail for the movie to play. If I tap somewhere else on the cell then it wouldn't play because my thumbnail doesn't extend all over the cell.
Isn't there a way to make the movie to play in didSelectRowAtIndexPath? I have seen some chaps suggest using Javascript but nobody seem to have an idea on the correct way of using it for this problem.
Highly appreciate it if anybody can help.
I suggest you to take a look at YouTube APIs and try to figure it out what is your real problem. but another good link is How To Play YouTube Videos Within an Application. Hope I'm helping you.
It's maybe not the best solution but It works:
//get your UIWebview in tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
//...
videoView.mediaPlaybackRequiresUserAction = NO;
[videoView loadHTMLString:[self generateHtmlEmbedYouTube] baseURL:nil];
From the Documentation
mediaPlaybackRequiresUserAction:
A Boolean value that determines
whether HTML5 videos can play
automatically or require the user to
start playing them.
The onely problem with this solution is that you have to reload your UIWebView.