WebView does not play youtube videos and interact with html5

I cannot get the WebView to play a youtube video.

I also cannot get it to interact with some html5 content (html5 example that it will not interact with: http://bluefiregames.com/temp/index.html where the buttons cannot be pressed (when using a normal browser all the buttons work except for the “exit game” button)).

Does anyone know of a workaround for this?

Jason

Can you post your code where you create your webView? I know for a certain that it plays YouTube videos.

Are you testing on a device?

You can also check out the Business App sample on our github repo. There is an example of webViews and YouTube videos. See: https://github.com/coronalabs/business-app-sample

Rob

I have tested it more and found that it is the specific device I was testing on.  The app does play youtube on other devices.  I guess there is a codec that is not installed.  Is there any way in Corona to include and use a codec to play youtube if the codec is not installed on the target device?

Thanks for your help.

Jason

Not really. User apps can’t update system level things.

Rob

I’m also having issues getting youtube videos to run on my devices.

I’ve tried running the Biz app sample and that works on my devices (iPad Mini 4) and the videos play on the embedded html page ok - I’ve even used my youtube playlist url in the Biz app and seen the videos I want to play up and running, however when I try the code in my app (which I lifted straight from the Biz app sample) I get the embedded page displaying but not the video.

Here’s my scene show code from my app

function scene:show( event ) local phase = event.phase local phase = event.phase local params = event.params local view = self.view if phase == "did" then local story = params.story local enclosures = story.enclosuers --utility.print\_r( story ) --[[-- do nothing when the podcast finishes playing. local function onComplete(event) return true end -- function to play the podcast. We get the URL to stream from the story.enclosures -- table. local function playPodcast() print("playPodcast", story.link) media.playVideo( story.link, media.RemoteSource, true, onComplete ) return true end --]] -- now we write out the story body, which likely has HTML code in it to a -- temporary file that we will load back in to our web view. local path = system.pathForFile( "story.html", system.TemporaryDirectory ) -- io.open opens a file at path. returns nil if no file found local fh, errStr = io.open( path, "w" ) -- -- Write out the required headers to make sure the content fits into our -- window and then dump the body. -- if fh then print( "Created file" ) fh:write("\<!doctype html\>\n\<html\>\n\<head\>\n\<meta charset=\"utf-8\"\>") fh:write("\<meta name=\"viewport\" content=\"width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;\"/\>\n") fh:write("\<style type=\"text/css\"\>\n html { -webkit-text-size-adjust: none; font-family: HelveticaNeue-Light, Helvetica, Droid-Sans, Arial, san-serif; font-size: 1.0em; } h1 {font-size:1.25em;} p {font-size:0.9em; } \</style\>") fh:write("\</head\>\n\<body\>\n") if story.title then fh:write("\<h1\>" .. story.title .. "\</h1\>\n") end -- print("LINK = ",story.link) if story.link then local videoID = story.link:sub(32, 42) -- print(videoID) local height = math.floor(display.contentWidth / 16 \* 9) fh:write([[\<iframe width="100%" height="]] .. height .. [[" src="http://www.youtube.com/embed/]] .. videoID .. [[?html5=1" frameborder="0" allowfullscreen\>\</iframe\>]]) end -- print("content\_encoded = ",story.content\_encoded) -- print("description = ",story.description) if story.content\_encoded then fh:write( story.content\_encoded) elseif story.description then fh:write(story.description) end fh:write( "\n\</body\>\n\</html\>\n" ) io.close( fh ) else print( "Create file failed!" ) end -- -- handler to deal with clicking on any anchor tags in the above HTML. -- local function webListener(event) -- print("showWebPopup callback - URL = ",event.url) local url = event.url if string.find(url, "http://www.youtube.com") then return true end if( string.find( url, "http:" ) ~= nil or string.find( url, "mailto:" ) ~= nil ) then print("url: ".. url) -- system.openURL(url) end return true end -- turn off the activity indicator and show the webview --native.setActivityIndicator( false ) -- local options = { hasBackground=false, baseUrl=system.TemporaryDirectory, urlRequest=listener } --local options = { hasBackground=true, urlRequest=listener } -- native.showWebPopup(0, 51 + 60 + 20 + 60, display.contentWidth, 220 + isTall, "story.html", options ) webView = native.newWebView(\_CX, \_CY, display.contentWidth, display.contentHeight - 150) -- webView.x = \_CX -- display.contentCenterX -- webView.y = 50 -- webView.anchorY = 0 webView:request("story.html", system.TemporaryDirectory) webView:addEventListener( "urlRequest", webListener ) -- add a button to see the full article in the web browser --[[local function viewWebPage(event) system.openURL( story.link ) end --]] -- local play\_button = display.newImageRect("images/view\_button.png", 300, 32) -- play\_button.x = display.contentCenterX -- play\_button.y = display.contentHeight - 80 -- sceneGroup:insert(play\_button) -- play\_button:addEventListener("tap", viewWebPage) end end

Any help would be much appreciated.

Also - is there any other way to play a video hosted on YouTube without having to go through an embedded webview?

Ok in the time honoured manner of “I’ve just posted a question on the forum and then the answer hit me like a tonne of bricks”, I realised the solution almost immediately.

The answer turned out to be iOS 9 App Transport Security - by default all external web access has to be https or else it get’s blocked (unless added to a whitelist in build.settings).

I copied this 

 NSAppTransportSecurity = { NSExceptionDomains = { ["coronalabs.com"] = { NSIncludesSubdomains = true, NSThirdPartyExceptionAllowsInsecureHTTPLoads = true }, ["youtube.com"] = { NSIncludesSubdomains = true, NSThirdPartyExceptionAllowsInsecureHTTPLoads = true }, ["google.com"] = { NSIncludesSubdomains = true, NSThirdPartyExceptionAllowsInsecureHTTPLoads = true }, }, },

From the biz app into my build.settings and I can now access the videos.

I’m leaving this here in case anyone else has the same problem.

Glad you solved it!

Can you post your code where you create your webView? I know for a certain that it plays YouTube videos.

Are you testing on a device?

You can also check out the Business App sample on our github repo. There is an example of webViews and YouTube videos. See: https://github.com/coronalabs/business-app-sample

Rob

I have tested it more and found that it is the specific device I was testing on.  The app does play youtube on other devices.  I guess there is a codec that is not installed.  Is there any way in Corona to include and use a codec to play youtube if the codec is not installed on the target device?

Thanks for your help.

Jason

Not really. User apps can’t update system level things.

Rob

I’m also having issues getting youtube videos to run on my devices.

I’ve tried running the Biz app sample and that works on my devices (iPad Mini 4) and the videos play on the embedded html page ok - I’ve even used my youtube playlist url in the Biz app and seen the videos I want to play up and running, however when I try the code in my app (which I lifted straight from the Biz app sample) I get the embedded page displaying but not the video.

Here’s my scene show code from my app

function scene:show( event ) local phase = event.phase local phase = event.phase local params = event.params local view = self.view if phase == "did" then local story = params.story local enclosures = story.enclosuers --utility.print\_r( story ) --[[-- do nothing when the podcast finishes playing. local function onComplete(event) return true end -- function to play the podcast. We get the URL to stream from the story.enclosures -- table. local function playPodcast() print("playPodcast", story.link) media.playVideo( story.link, media.RemoteSource, true, onComplete ) return true end --]] -- now we write out the story body, which likely has HTML code in it to a -- temporary file that we will load back in to our web view. local path = system.pathForFile( "story.html", system.TemporaryDirectory ) -- io.open opens a file at path. returns nil if no file found local fh, errStr = io.open( path, "w" ) -- -- Write out the required headers to make sure the content fits into our -- window and then dump the body. -- if fh then print( "Created file" ) fh:write("\<!doctype html\>\n\<html\>\n\<head\>\n\<meta charset=\"utf-8\"\>") fh:write("\<meta name=\"viewport\" content=\"width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;\"/\>\n") fh:write("\<style type=\"text/css\"\>\n html { -webkit-text-size-adjust: none; font-family: HelveticaNeue-Light, Helvetica, Droid-Sans, Arial, san-serif; font-size: 1.0em; } h1 {font-size:1.25em;} p {font-size:0.9em; } \</style\>") fh:write("\</head\>\n\<body\>\n") if story.title then fh:write("\<h1\>" .. story.title .. "\</h1\>\n") end -- print("LINK = ",story.link) if story.link then local videoID = story.link:sub(32, 42) -- print(videoID) local height = math.floor(display.contentWidth / 16 \* 9) fh:write([[\<iframe width="100%" height="]] .. height .. [[" src="http://www.youtube.com/embed/]] .. videoID .. [[?html5=1" frameborder="0" allowfullscreen\>\</iframe\>]]) end -- print("content\_encoded = ",story.content\_encoded) -- print("description = ",story.description) if story.content\_encoded then fh:write( story.content\_encoded) elseif story.description then fh:write(story.description) end fh:write( "\n\</body\>\n\</html\>\n" ) io.close( fh ) else print( "Create file failed!" ) end -- -- handler to deal with clicking on any anchor tags in the above HTML. -- local function webListener(event) -- print("showWebPopup callback - URL = ",event.url) local url = event.url if string.find(url, "http://www.youtube.com") then return true end if( string.find( url, "http:" ) ~= nil or string.find( url, "mailto:" ) ~= nil ) then print("url: ".. url) -- system.openURL(url) end return true end -- turn off the activity indicator and show the webview --native.setActivityIndicator( false ) -- local options = { hasBackground=false, baseUrl=system.TemporaryDirectory, urlRequest=listener } --local options = { hasBackground=true, urlRequest=listener } -- native.showWebPopup(0, 51 + 60 + 20 + 60, display.contentWidth, 220 + isTall, "story.html", options ) webView = native.newWebView(\_CX, \_CY, display.contentWidth, display.contentHeight - 150) -- webView.x = \_CX -- display.contentCenterX -- webView.y = 50 -- webView.anchorY = 0 webView:request("story.html", system.TemporaryDirectory) webView:addEventListener( "urlRequest", webListener ) -- add a button to see the full article in the web browser --[[local function viewWebPage(event) system.openURL( story.link ) end --]] -- local play\_button = display.newImageRect("images/view\_button.png", 300, 32) -- play\_button.x = display.contentCenterX -- play\_button.y = display.contentHeight - 80 -- sceneGroup:insert(play\_button) -- play\_button:addEventListener("tap", viewWebPage) end end

Any help would be much appreciated.

Also - is there any other way to play a video hosted on YouTube without having to go through an embedded webview?

Ok in the time honoured manner of “I’ve just posted a question on the forum and then the answer hit me like a tonne of bricks”, I realised the solution almost immediately.

The answer turned out to be iOS 9 App Transport Security - by default all external web access has to be https or else it get’s blocked (unless added to a whitelist in build.settings).

I copied this 

 NSAppTransportSecurity = { NSExceptionDomains = { ["coronalabs.com"] = { NSIncludesSubdomains = true, NSThirdPartyExceptionAllowsInsecureHTTPLoads = true }, ["youtube.com"] = { NSIncludesSubdomains = true, NSThirdPartyExceptionAllowsInsecureHTTPLoads = true }, ["google.com"] = { NSIncludesSubdomains = true, NSThirdPartyExceptionAllowsInsecureHTTPLoads = true }, }, },

From the biz app into my build.settings and I can now access the videos.

I’m leaving this here in case anyone else has the same problem.

Glad you solved it!