23

Hi I created a WebView app for my video site. The design of the site is a hybrid that loads for mobile users. Only videos compatible with mobile devices are loaded onto the hybrid. The players are from Vk, DailyMotion, YouTube, and QuickTime.

The videos only play on SDK 11 and higher but when I click on the player button to go full screen it only stops the video from playing while never launching into full screen mode.

(Webviewactivity.java)

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().requestFeature(Window.FEATURE_PROGRESS);
    setContentView(R.layout.main);

    parentView = (RelativeLayout) findViewById(R.id.parent_rl);

    webviewProgress = (ProgressBar) findViewById(R.id.webview_progress);

    webview = (WebView) findViewById(R.id.webview);
    webview.getSettings().setJavaScriptEnabled(true);
    webview.getSettings().setBuiltInZoomControls(true);
    webview.getSettings().setAllowFileAccess(true);
    webview.setWebViewClient(new MyWebViewClient());
    webview.getSettings().setPluginState(WebSettings.PluginState.ON);
    webview.loadUrl(URL);
    webviewProgress.setProgress(0);

    webview.setWebChromeClient(new MyWebChromeClient());
    webview.setDownloadListener(new DownloadListener() {
        public void onDownloadStart(String url, String userAgent,
                String contentDisposition, String mimetype,
                long contentLength) {
            mProgressDialog = new ProgressDialog(WebViewActivity.this);
            mProgressDialog.setMessage("Downloading...");
            mProgressDialog.setIndeterminate(false);
            mProgressDialog.setMax(100);
            mProgressDialog
                    .setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            DownloadFile downloadFile = new DownloadFile();
            downloadFile.execute(url);
        }
    });

    initSlider();

    initAdmob();
}

/**
 * When when file was chosen
 */
@Override
protected void onActivityResult(int requestCode, int resultCode,
        Intent intent) {
    if (requestCode == FILECHOOSER_RESULTCODE) {
        if (null == mUploadMessage)
            return;
        Uri result = intent == null || resultCode != RESULT_OK ? null
                : intent.getData();
        mUploadMessage.onReceiveValue(result);
        mUploadMessage = null;

(Main.xml)

android:id="@+id/parent_rl"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:keepScreenOn="true" >

<ProgressBar
    android:id="@+id/webview_progress"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:maxHeight="5dip"
    android:minHeight="5dip"
    android:progressDrawable="@drawable/blueprogress" />

<FrameLayout
    android:id="@+id/framelayout"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/webview_progress"
    android:orientation="vertical" >

    <WebView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/webview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

(Manifest.xml)

package="com.wCHfree"
android:versionCode="7"
android:versionName="1.1" >

<uses-sdk
    android:minSdkVersion="11"
    android:targetSdkVersion="17" />

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

<application
    android:icon="@drawable/ic_launcher_red"
    android:label="@string/app_name"
    android:theme="@android:style/Theme.Black" >
    <activity
        android:name="com.webview.splashScreen.SplashScreenActivity"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name="com.webview.splashScreen.WebViewActivity"
        android:configChanges="orientation|screenSize|screenLayout"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
    </activity>
    <activity
        android:name="com.google.ads.AdActivity"
        android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" />
BSMP
  • 4,596
  • 8
  • 33
  • 44
digiboomz
  • 325
  • 1
  • 3
  • 9

1 Answers1

77

You need to implement showCustomView & hideCustomView method of WebChromeClient, also You need android:hardwareAccelerated="true" in your AndroidManifest File. I am posting my sample project here. What i have done is kept one Framelayout(customContainer) in my main.xml, and adding view received in showCustomView here, and removing it in onHide. Also hiding/showing webview accordingly. Below code works perfectly on device.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.webview"
          android:versionCode="1"
          android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher"
            android:hardwareAccelerated="true">
        <activity android:name="MyActivity"
                  android:configChanges="orientation|keyboardHidden"
                  android:hardwareAccelerated="true"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
        >
    <WebView
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:id="@+id/webView"
            android:layout_gravity="center"
            />
    <FrameLayout
            android:id="@+id/customViewContainer"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:visibility="gone"
            />
</LinearLayout>

video_progress.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/progress_indicator"
              android:orientation="vertical"
              android:layout_centerInParent="true"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent">

    <ProgressBar android:id="@android:id/progress"
                 style="?android:attr/progressBarStyleLarge"
                 android:layout_gravity="center"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"/>

    <TextView android:paddingTop="5dip"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_gravity="center"
              android:text="loading"
              android:textSize="14sp"
              android:textColor="?android:attr/textColorPrimary"/>
</LinearLayout>

MyActivity.java

package com.example.webview;

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;

public class MyActivity extends Activity {
    private WebView webView;
    private FrameLayout customViewContainer;
    private WebChromeClient.CustomViewCallback customViewCallback;
    private View mCustomView;
    private myWebChromeClient mWebChromeClient;
    private myWebViewClient mWebViewClient;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        customViewContainer = (FrameLayout) findViewById(R.id.customViewContainer);
        webView = (WebView) findViewById(R.id.webView);

        mWebViewClient = new myWebViewClient();
        webView.setWebViewClient(mWebViewClient);

        mWebChromeClient = new myWebChromeClient();
        webView.setWebChromeClient(mWebChromeClient);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setAppCacheEnabled(true);
        webView.getSettings().setBuiltInZoomControls(true);
        webView.getSettings().setSaveFormData(true);
        webView.loadUrl("http://m.youtube.com");
    }

    public boolean inCustomView() {
        return (mCustomView != null);
    }

    public void hideCustomView() {
        mWebChromeClient.onHideCustomView();
    }

    @Override
    protected void onPause() {
        super.onPause();    //To change body of overridden methods use File | Settings | File Templates.
        webView.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();    //To change body of overridden methods use File | Settings | File Templates.
        webView.onResume();
    }

    @Override
    protected void onStop() {
        super.onStop();    //To change body of overridden methods use File | Settings | File Templates.
        if (inCustomView()) {
            hideCustomView();
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {

            if (inCustomView()) {
                hideCustomView();
                return true;
            }

            if ((mCustomView == null) && webView.canGoBack()) {
                webView.goBack();
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    class myWebChromeClient extends WebChromeClient {
        private Bitmap mDefaultVideoPoster;
        private View mVideoProgressView;

        @Override
        public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback) {
           onShowCustomView(view, callback);    //To change body of overridden methods use File | Settings | File Templates.
        }

        @Override
        public void onShowCustomView(View view,CustomViewCallback callback) {

            // if a view already exists then immediately terminate the new one
            if (mCustomView != null) {
                callback.onCustomViewHidden();
                return;
            }
            mCustomView = view;
            webView.setVisibility(View.GONE);
            customViewContainer.setVisibility(View.VISIBLE);
            customViewContainer.addView(view);
            customViewCallback = callback;
        }

        @Override
        public View getVideoLoadingProgressView() {

            if (mVideoProgressView == null) {
                LayoutInflater inflater = LayoutInflater.from(MyActivity.this);
                mVideoProgressView = inflater.inflate(R.layout.video_progress, null);
            }
            return mVideoProgressView;
        }

        @Override
        public void onHideCustomView() {
            super.onHideCustomView();    //To change body of overridden methods use File | Settings | File Templates.
            if (mCustomView == null)
                return;

            webView.setVisibility(View.VISIBLE);
            customViewContainer.setVisibility(View.GONE);

            // Hide the custom view.
            mCustomView.setVisibility(View.GONE);

            // Remove the custom view from its container.
            customViewContainer.removeView(mCustomView);
            customViewCallback.onCustomViewHidden();

            mCustomView = null;
        }
    }

    class myWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            return super.shouldOverrideUrlLoading(view, url);    //To change body of overridden methods use File | Settings | File Templates.
        }
    }

}

You can clone sample project from here..

Akhil
  • 6,667
  • 4
  • 31
  • 61
  • Thank you as well, that's a very authoritative answer. I will try it out, and if it's all good - the bounty is yours. – Andrew Weir Apr 25 '13 at 08:41
  • I must say this example project works better than my own. I have videos working on 2.3.3 that wouldn't work on that version with my own project. Not even sure how you did that part. – digiboomz Apr 26 '13 at 09:11
  • Thanks for the great work you have done, quite simple way to handle webview video playing – Muhammad Babar May 14 '13 at 07:41
  • Many, many thanks. Best solution to showing HTML5 video I have found (and I have found a few..) – Michel Nov 05 '13 at 15:28
  • @Akhil you are a rockstar – 2cupsOfTech Jun 13 '14 at 14:30
  • @Akhil Thanks for the answer. Btw is there any way to automatically become full-screen when started to play? – Eric Sep 16 '14 at 13:15
  • @Eric: that is something controlled by HTML5 video tag, i guess you need to check video tag specification for that.As far i know you can't force all videos to become full screen on play. – Akhil Sep 17 '14 at 06:27
  • @Akhil Thanks for the solution. It worked for me. But I also need to show/hide actionbar on tap of screen for full screen mode. I tried setting `ontouchlistener` to **webview** & **customeviewcontainer** but none of them gets called for full screen mode. can you help ? – AndyN Sep 09 '15 at 12:53
  • How do you handle change orientation? – Hong Zhou Jan 09 '16 at 15:45
  • There is a minor bug in this code. `mCustomView = null;` should be set before calling `customViewCallback.onCustomViewHidden();`, because this invocation in turn calls `onHideCustomView()` from the core `AwContentViewClient.exitFullscreen`. As a result, `onHideCustomView()` body is executed twice, because `mCustomView` is not yet `null`. The bug may affect some "state machine" logic in application code. – Stan Apr 18 '16 at 14:15
  • 1
    What is the Bitmap used for? it's not referenced anywhere else in this code – Cogwheel Jun 01 '16 at 00:02
  • Sometimes it hangs to show full screen . any work around? – Manikandan Selvanathan Jul 27 '16 at 06:15
  • If Any one facing the slowness issue. pleas usee following code. – Manikandan Selvanathan Jul 27 '16 at 08:52
  • @Stan what do you mean before? Then it always be null – user25 Aug 20 '16 at 10:14
  • Doesn't work (using it in fragment): `mWebChromeClient = new myWebChromeClient(); mWebView.setWebChromeClient(mWebChromeClient);` java.lang.NullPointerException – user25 Aug 20 '16 at 10:16
  • @user25, Move the mentioned line of code (nullifying `mCustomView`) one line up - before the call `onCustomViewHidden`. In other words, set `mCustomView` to null just after `removeView` from the container. – Stan Aug 20 '16 at 15:46
  • @user25, in a fragment, make sure you call `webView = (WebView) findViewById(R.id.webView);` properly, that is something like that `fragmentView.findViewById`. See [this answer](http://stackoverflow.com/questions/6495898/findviewbyid-in-fragment) for reference for example. – Stan Aug 20 '16 at 15:51
  • 2
    @Stan I don't have problem with getting link to webview `mWebView = (WebView) v.findViewById(R.id.webView);` in `onCreateView`. It's some other problem. Anyway I tried to convert another example code to use it in fragments http://inducesmile.com/android/how-to-play-youtube-video-inside-android-webview-using-video-url/ it works good but I cannot make part with `onBackPressed` method (cause fragments doesn't overrides it). So can't get out of fullscreen – user25 Aug 20 '16 at 16:15
  • same problem with me. Have you found any solution? @user25 – DàChún Jul 20 '17 at 19:13
  • @Akhil I have tride this solution for API 19 and lower it's not working there Do you have any solution for that? – Sushrita Oct 14 '17 at 12:45
  • I want to make my app to turn into full screen once the video loaded. I don't want the user to click on the button – Bala Saikrupa Puram Sep 23 '20 at 02:03