iOS Question [SOLVED] YouTube embedded

JackKirk

Well-Known Member
Licensed User
Longtime User
Last edited:

JackKirk

Well-Known Member
Licensed User
Longtime User
As a crude substitute I was just using:
B4X:
App.OpenURL("https://www.youtube.com/watch?v=" & wrk_str)
where wrk_str is the YouTube VideoID.

Using:
B4X:
    Private UI_webview As WebView
...
...
UI_webview.Initialize("")
Page1.RootPanel.AddView(UI_webview, 0, 0, Page1.RootPanel.Width, Page1.RootPanel.Height)
 
UI_webview.LoadUrl("https://www.youtube.com/watch?v=" & wrk_str)
seems to be better - for some reason the video now automatically goes full size when playing is manually started and it doesn't go jumping off to all sorts of other videos when it finishes.

It would be near perfect from my perspective if:
(1) Playing of YouTube video automatically started when webview was launched - any suggestions as to how to force this?
(2) The webview didn't prevent detection of gestures by:
https://www.b4x.com/android/forum/t...-uigesturerecognizer.52836/page-2#post-500176
while a video was playing - any suggestions?

BTW, the webview does not have the "small link" you referred to in:
https://www.b4x.com/android/forum/threads/return-to-app-after-openurl.79361/#post-502537
this would be a reasonable substitute for (2) imo.
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
Longtime User
A bit of progress...

Googling, I have found that I can get the video to:

(1) appear full screen at start (but still requiring manual starting)
(2) not go off on a tedious "related videos" amble

if I use:

B4X:
UI_webview.LoadUrl("https://www.youtube.com/embed/" & wrk_str & "?rel=0")

There is also supposed to be autoplay options along the line:
B4X:
UI_webview.LoadUrl("https://www.youtube.com/embed/" & wrk_str & "?rel=0&autoplay=1")
...
...
UI_webview.LoadUrl("https://www.youtube.com/embed/" & wrk_str & "?rel=0&autoplay=1")

But I can't get this to work - is the "browser" associated with webview somehow stopping autoplay - if so is there a fix.

Thanks in anticipation...
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
Longtime User
Didn't fix it, I tried putting it before and after LoadUrl, my code is currently:
B4X:
'Set up webview
UI_webview.Initialize("")
Page1.RootPanel.AddView(UI_webview, 0, 0, Page1.RootPanel.Width, Page1.RootPanel.Height)
  
Private no As NativeObject = UI_webview
no.RunMethod("setMediaPlaybackRequiresUserAction:", Array(False))
  
'Fly to YouTube website
UI_webview.LoadUrl("https://www.youtube.com/embed/" & wrk_str & "?rel=0&autoplay=1")
I also tried various permutations around ?rel=0&autoplay=1

Any help appreciated...
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
This code works:
B4X:
Private Sub Application_Start (Nav As NavigationController)
   'SetDebugAutoFlushLogs(True) 'Uncomment if program crashes before all logs are printed.
   NavControl = Nav
   Page1.Initialize("Page1")
   Page1.Title = "Page 1"
   Page1.RootPanel.LoadLayout("1")
   NavControl.ShowPage(Page1)
   Dim videoId As String = "cgxWP4Wu77s"
   Dim no As NativeObject = WebView1
   no.RunMethod("setMediaPlaybackRequiresUserAction:", Array(False))
   WebView1.LoadHtml($"<!DOCTYPE html><html>
   <head>
   <style>body{margin:0px 0px 0px 0px;}</style></head>
    <body> <div id="player"></div>
    <script> var tag = document.createElement('script');
    tag.src = "https://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:'${100%x}', height:'${100%y}', videoId:'${videoId}', events: { 'onReady': onPlayerReady, } }); }
    function onPlayerReady(event) { event.target.playVideo(); }
    </script> </body> </html>"$)
End Sub

Based on this answer: http://stackoverflow.com/questions/15717754/how-to-autoplay-a-youtube-video-in-a-uiwebview
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
Longtime User
SUCCESS!!!

Erel, thanks for your persistence.

I have tidied up the HTML and added a bit of extra sauce, my final code is (as it would be run from a sub other than Page1.Resize):
B4X:
    Private videoId As String

    'Get YouTube VideoId from ...
    videoId = ...

    'Set up webview
    UI_webview.Initialize("")
    Page1.RootPanel.AddView(UI_webview, 0, 0, Page1.RootPanel.Width, Page1.RootPanel.Height)
    Private no As NativeObject = UI_webview
    no.RunMethod("setMediaPlaybackRequiresUserAction:", Array(False))

    'Fly to YouTube website
    UI_webview.LoadHtml( _
        $"<!DOCTYPE html>
          <html>
              <head>
                  <style>body{margin:0px 0px 0px 0px;}</style>
              </head>
              <body>
                  <div id="player"></div>
                  <script> var tag = document.createElement('script');
                           tag.src = "https://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:'${Page1.RootPanel.Width}',
                                       height:'${Page1.RootPanel.Height}',
                                       videoId:'${videoId}',
                                       playerVars: { 'rel' : 0 },
                                       events:
                                       {
                                           'onReady': onPlayerReady,
                                       }
                                   });
                               }
                           function onPlayerReady(event)
                               {
                                   event.target.playVideo();
                               }
                  </script>
              </body>
          </html>"$)

The extra sauce is the statement:

playerVars: { 'rel' : 0 },

which forces the player not to go off on a tedious "related videos" ramble after the video completes.

BTW, while Googling to try and work out the exact syntax of the playerVars statement I found this:

https://developers.google.com/youtube/iframe_api_reference

which is the Google documentation for what we are playing around with. It has the following:
Mobile Considerations
Autoplay and Scripted Playback
The HTML5 <video> element, in certain mobile browsers (such as Chrome and Safari), only allows playback to take place if it's initiated by a user interaction (such as tapping on the player). Here's an excerpt from Apple's documentation:
"Warning: To prevent unsolicited downloads over cellular networks at the user’s expense, embedded media cannot be played automatically in Safari on iOS — the user always initiates playback."
Due to this restriction, functions and parameters such as autoplay, playVideo(), loadVideoById() won't work in all mobile environments.
which probably explains why we couldn't get the earlier autoplay attempts to work.

Thanks again...
 
Last edited:
Upvote 0
Top