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