September 30, 2015

How to play Youtube Video using Webview in Xamarin android

In Brief: In this post let us see the implementation steps for Youtube video streaming in Android Xamarin.


In my previous post shared my thought about How to implement sliding menu in Xamarin android and in iOS, Best Practice and issues with ListView in Android XamarinHow to avoid ImageBitmap OutOfMemoryException and Rounded corner Image in android Xamarin,Drawing path between two location in xamarin android.

In Detail: 
This implementation is not by using the native Youtube player. Here i made use of the HTML to embed the Youtube player in webview. Eventhough it doesn't show all the option as in native player but useful to show some quick intro/small video etc. 
Streaming youtube video is alway the better option instead of storing the video inside a project. As it increases the App size.

In steps:
1. Create a new single screen android application.Open the layout file add the following.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#ffdedede">
    <LinearLayout
        android:id="@+id/lyTopContainer"
        android:layout_above="@+id/lyWebViewContainer"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginBottom="15dp"
        android:gravity="center"
        android:minWidth="25px"
        android:minHeight="25px"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:background="#ffaaaaaa">
        <TextView
            android:id="@+id/txtTitleIntro"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="@string/txtTitleIntro"
            android:textSize="18dp"
            android:layout_gravity="center"
            android:gravity="center"
            android:textStyle="normal"
            android:typeface="normal"
            android:textColor="#FFFFFF" />
    </LinearLayout>
    <LinearLayout
        android:id="@+id/lyWebViewContainer"
        android:layout_width="match_parent"
        android:layout_height="210dp"
        android:gravity="center"
        android:minWidth="25px"
        android:minHeight="25px"
        android:background="#ffaaaaaa"
        android:layout_margin="12dp"
        android:layout_centerInParent="true">
        <WebView
            android:id="@+id/videoView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:layout_gravity="center"
            android:background="#ffaaaaaa"
            android:fitsSystemWindows="true"
            android:drawingCacheQuality="auto"
            android:scrollbars="none" />
    </LinearLayout>
    <LinearLayout
        android:id="@+id/lyBottomContainer"
        android:layout_below="@+id/lyWebViewContainer"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:minWidth="25px"
        android:minHeight="25px"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:background="#ffaaaaaa">
        <TextView
            android:id="@+id/txtSkipVideo"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="@string/txtSkipVideo"
            android:textSize="16dp"
            android:layout_gravity="center"
            android:gravity="center"
            android:textStyle="normal"
            android:typeface="normal"
            android:textColor="#FFFFFF" />
    </LinearLayout>
</RelativeLayout>   
Strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">VideoDemo</string> 
    <string name="btnPlay">Play</string>
    <string name="txtTitleIntro">>> Quick Video Intro on Topic <<</string>
    <string name="txtSkipVideo">Skip Video,Proceed to chapter >></string>
</resources>

2.Edit the ActivityClass
2.1. Select the video URL from Youtube. Here you can copy paste the url from youtube and that takes the following format,
https://www.youtube.com/watch?v=videoId
It should be converted to below format,before passing to the html tag. RegExpPattern is used to extract the videoId from url.check this in below code.
http://youtube.com/embed/videoId
2.2. Embeded the HTML code to display the youtube video player. Set the iframe tag with youtue video url and the required height and width. Here i have consider the height and width according to the screen dimension.
using System;
using Android.App;
using Android.Widget;
using Android.Webkit; 
using Android.OS;
using System.Text.RegularExpressions;


namespace PlayVideo
{
    [Activity (Label = "YouTubeVideoPlayer", MainLauncher = true)]
    public class YouTubeVideoActivity : Activity
    { 
        int intDisplayWidth;
        int intDisplayHeight;
        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);    
            Window.RequestFeature ( Android.Views.WindowFeatures.NoTitle );
            SetContentView (Resource.Layout.Main); 
            var metrics = Resources.DisplayMetrics;
            //fix video screen height and width
            intDisplayWidth = (FnConvertPixelsToDp(metrics.WidthPixels)+200);
            intDisplayHeight = (FnConvertPixelsToDp(metrics.HeightPixels))/(2);
            FnPlayInWebView ();  
        }
        void FnPlayInWebView()
        {  
            
                string strUrl="https://www.youtube.com/watch?v=rOUAWzxVwX0"; 
    
                string id = FnGetVideoID(strUrl);

                if (!string.IsNullOrEmpty(id))
                { 
                    strUrl= string.Format("http://youtube.com/embed/{0}",id);
                }
                else
                {
                    Toast.MakeText(this,"Video url is not in correct format",ToastLength.Long).Show();
                    return;
                }

                string html=@"<html><body><iframe width=""videoWidth"" height=""videoHeight"" src=""strUrl""></iframe></body></html>"; 
                var myWebView = ( WebView ) FindViewById ( Resource.Id.videoView );  
                var settings=myWebView.Settings; 
                settings.JavaScriptEnabled=true;
                settings.UseWideViewPort=true;  
                settings.LoadWithOverviewMode=true;
                settings.JavaScriptCanOpenWindowsAutomatically=true; 
                settings.DomStorageEnabled=true;
                settings.SetRenderPriority(WebSettings.RenderPriority.High); 
                settings.BuiltInZoomControls = false; 
            
                settings.JavaScriptCanOpenWindowsAutomatically=true;
                myWebView.SetWebChromeClient(new WebChromeClient());
                settings.AllowFileAccess = true;
                settings.SetPluginState(WebSettings.PluginState.On);  
                string strYouTubeURL = html.Replace ( "videoWidth" , intDisplayWidth.ToString () ).Replace ( "videoHeight" , intDisplayHeight.ToString () ).Replace("strUrl",strUrl); 

                myWebView.LoadDataWithBaseURL(null,strYouTubeURL,"text/html","UTF-8",null); 
         
        }
        int FnConvertPixelsToDp(float pixelValue)
        {
            var dp = (int) ((pixelValue)/Resources.DisplayMetrics.Density);
            return dp;
        }
        static string FnGetVideoID(string strVideoURL)
        {
            const string regExpPattern = @"youtu(?:\.be|be\.com)/(?:.*v(?:/|=)|(?:.*/)?)([a-zA-Z0-9-_]+)";
            //for Vimeo: vimeo\.com/(?:.*#|.*/videos/)?([0-9]+)
            var regEx = new Regex (regExpPattern);
            var match= regEx.Match (strVideoURL);
            return match.Success ? match.Groups [1].Value : null;
        }

    }
}
3. Open manifest file and Enable the INTERNET permission and set hardwareAccelerated to true.
 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="PlayVideo">
    <application android:label="PlayVideo" android:icon="@drawable/icon" android:hardwareAccelerated="true">
    </application>
 
    <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="19" />
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>

4. Now on run the code it should play the video. 
If it is not playing video in Webview,double check the youtube video url format as mentioned in the step 2.1.
If it is only showing the thumbnail image of the video but not playing, then it is related to the hardwareAccelerated,might be missing ornotin the proper side.check step 3.

Screen Recording:


Final touch: 
This html video player does provide the options like Play,Pause,seek bar,volume etc. and also plenty of Web-view settings options, combination of these brings the youtube player to more customized look.

[Dec/11/2016]Update: For any blank screen error or video load error check step 3/4. Updated complete code base at GitHub: https://github.com/suchithm/YouTubePlayerXamarinAndroid

8 comments:

  1. I kindly request with my blog readers not to comment any spam or irrelevant link which is off topic.
    Thank you

    ReplyDelete
  2. Hello Suchith. Thank you for putting this up.
    I have a question - would this work in X.Forms?
    I am hoping to do something like this in C# and Forms. I am a extremely xaml-illiterate.

    ReplyDelete
  3. When I play the video, the app closes automatically

    ReplyDelete
  4. This doesn't seem to work anymore. Get an error "Can't play this video" on both my emulator and my Galaxy S5

    ReplyDelete
  5. I was trying the same thing I was facing the problem of screen coming as blank.

    Even I tried with the same code what you have given Still its not working.Facing the same problem the screen is coming blank..

    I have given internet permission etc..

    would you please help me on this

    ReplyDelete
    Replies
    1. Hi Vinod, I rechecked it works without any issues. I think you are missing hardwareAccelerated property in manifest. It will show you the blank screen if you miss this tag. check step 3 code.

      Delete
  6. Explore the code @ https://github.com/suchithm/YouTubePlayerXamarinAndroid

    ReplyDelete
  7. Even the property "hardwareAccelerated=true" that also I have added..I dont understand whats the problem...

    Even the Iframe is coming properly but with the blank screen..Please help me I am stuck on this totally..

    ReplyDelete