diff --git a/plugin.xml b/plugin.xml
index 011d8c009..506c5ef3e 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -48,6 +48,8 @@
+
+
diff --git a/src/android/InAppBrowser.java b/src/android/InAppBrowser.java
index b3e0e6126..58069505d 100644
--- a/src/android/InAppBrowser.java
+++ b/src/android/InAppBrowser.java
@@ -18,15 +18,18 @@ Licensed to the Apache Software Foundation (ASF) under one
*/
package org.apache.cordova.inappbrowser;
+import android.app.Activity;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Parcelable;
import android.provider.Browser;
+import android.os.Handler;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
@@ -97,6 +100,7 @@ public class InAppBrowser extends CordovaPlugin {
private static final String EXIT_EVENT = "exit";
private static final String LOCATION = "location";
private static final String ZOOM = "zoom";
+ private static final String FULL_SCREEN = "fullscreen";
private static final String HIDDEN = "hidden";
private static final String LOAD_START_EVENT = "loadstart";
private static final String LOAD_STOP_EVENT = "loadstop";
@@ -134,6 +138,7 @@ public class InAppBrowser extends CordovaPlugin {
private boolean clearSessionCache = false;
private boolean hadwareBackButton = true;
private boolean mediaPlaybackRequiresUserGesture = false;
+ private boolean fullScreenFeature = false;
private boolean shouldPauseInAppBrowser = false;
private boolean useWideViewPort = true;
private ValueCallback mUploadCallback;
@@ -670,6 +675,10 @@ public String showWebPage(final String url, HashMap features) {
if (mediaPlayback != null) {
mediaPlaybackRequiresUserGesture = mediaPlayback.equals("yes") ? true : false;
}
+ String fullScreen = features.get(FULL_SCREEN);
+ if (fullScreen != null) {
+ fullScreenFeature = fullScreen.equals("yes") ? true : false;
+ }
String cache = features.get(CLEAR_ALL_CACHE);
if (cache != null) {
clearAllCache = cache.equals("yes") ? true : false;
@@ -727,6 +736,9 @@ public String showWebPage(final String url, HashMap features) {
// Create dialog in new thread
Runnable runnable = new Runnable() {
+
+ private boolean inFullScreen = false;
+
/**
* Convert our DIP units to Pixels
*
@@ -740,6 +752,38 @@ private int dpToPixels(int dipValue) {
return value;
}
+
+ private void enableFullScreen(Activity activity, Window window) {
+ inFullScreen = true;
+ WindowManager.LayoutParams attrs = window.getAttributes();
+ attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
+ attrs.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+ window.setAttributes(attrs);
+ if (android.os.Build.VERSION.SDK_INT >= 14)
+ {
+ //noinspection all
+ int flags = View.SYSTEM_UI_FLAG_LOW_PROFILE;
+ if (android.os.Build.VERSION.SDK_INT >= 16)
+ {
+ flags = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE;
+ }
+ window.getDecorView().setSystemUiVisibility(flags);
+ }
+
+ }
+
+ private void disableFullScreen(Activity activity, Window window) {
+ inFullScreen = false;
+ WindowManager.LayoutParams attrs = window.getAttributes();
+ attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
+ attrs.flags &= ~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+ window.setAttributes(attrs);
+ if (android.os.Build.VERSION.SDK_INT >= 14)
+ {
+ //noinspection all
+ window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
+ }
+ }
private View createCloseButton(int id) {
View _close;
@@ -798,8 +842,30 @@ public void run() {
};
// Let's create the main dialog
- dialog = new InAppBrowserDialog(cordova.getActivity(), android.R.style.Theme_NoTitleBar);
+ dialog = new InAppBrowserDialog(cordova.getActivity(), android.R.style.Theme_NoTitleBar_Fullscreen);
dialog.getWindow().getAttributes().windowAnimations = android.R.style.Animation_Dialog;
+
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
+ final View decor = dialog.getWindow().getDecorView();
+ decor.setOnSystemUiVisibilityChangeListener (new View.OnSystemUiVisibilityChangeListener() {
+ public void onSystemUiVisibilityChange(int visibility) {
+ new Handler().postDelayed(new Runnable() {
+ public void run(){
+ if (inFullScreen)
+ {
+ decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE);
+ }
+ }
+ }, 3000);
+ }
+ });
+ }
+
+ if (fullScreenFeature)
+ {
+ enableFullScreen(cordova.getActivity(), dialog.getWindow());
+ }
+
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
if (fullscreen) {
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
@@ -808,8 +874,12 @@ public void run() {
dialog.setInAppBroswer(getInAppBrowser());
// Main container layout
- LinearLayout main = new LinearLayout(cordova.getActivity());
- main.setOrientation(LinearLayout.VERTICAL);
+ RelativeLayout main = new RelativeLayout(cordova.getActivity());
+ RelativeLayout fullScreenMain = new RelativeLayout(cordova.getActivity());
+ fullScreenMain.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+ LinearLayout browserMain = new LinearLayout(cordova.getActivity());
+ browserMain.setOrientation(LinearLayout.VERTICAL);
+ browserMain.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
// Toolbar layout
RelativeLayout toolbar = new RelativeLayout(cordova.getActivity());
@@ -937,11 +1007,11 @@ public boolean onKey(View v, int keyCode, KeyEvent event) {
// WebView
- inAppWebView = new WebView(cordova.getActivity());
+ inAppWebView = new VideoEnabledWebView(cordova.getActivity());
inAppWebView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
inAppWebView.setId(Integer.valueOf(6));
// File Chooser Implemented ChromeClient
- inAppWebView.setWebChromeClient(new InAppChromeClient(thatWebView) {
+ InAppChromeClient inAppChromeClient = new InAppChromeClient(thatWebView, browserMain, fullScreenMain) {
// For Android 5.0+
public boolean onShowFileChooser (WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams)
{
@@ -982,7 +1052,33 @@ public void openFileChooser(ValueCallback uploadMsg, String acceptType)
cordova.startActivityForResult(InAppBrowser.this, Intent.createChooser(content, "Select File"), FILECHOOSER_REQUESTCODE);
}
+ };
+
+ inAppChromeClient.setOnToggledFullscreen(new VideoEnabledWebChromeClient.ToggledFullscreenCallback() {
+ @Override
+ public void toggledFullscreen(boolean fullscreen)
+ {
+ // Your code to handle the full-screen change, for example showing and hiding the title bar. Example:
+
+ Activity activity = cordova.getActivity();
+ Window window = dialog.getWindow();
+ if (fullscreen)
+ {
+ enableFullScreen(activity, window);
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
+ }
+ else
+ {
+ if (!fullScreenFeature)
+ {
+ disableFullScreen(activity, window);
+ }
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
+ }
+ }
});
+ inAppWebView.setWebChromeClient(inAppChromeClient);
+
currentClient = new InAppBrowserClient(thatWebView, edittext, beforeload);
inAppWebView.setWebViewClient(currentClient);
WebSettings settings = inAppWebView.getSettings();
@@ -1060,13 +1156,13 @@ public void postMessage(String data) {
// Don't add the toolbar if its been disabled
if (getShowLocationBar()) {
// Add our toolbar to our main view/layout
- main.addView(toolbar);
+ browserMain.addView(toolbar);
}
// Add our webview to our main view/layout
RelativeLayout webViewLayout = new RelativeLayout(cordova.getActivity());
webViewLayout.addView(inAppWebView);
- main.addView(webViewLayout);
+ browserMain.addView(webViewLayout);
// Don't add the footer unless it's been enabled
if (showFooter) {
@@ -1078,6 +1174,9 @@ public void postMessage(String data) {
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.MATCH_PARENT;
+ main.addView(browserMain);
+ main.addView(fullScreenMain);
+
if (dialog != null) {
dialog.setContentView(main);
dialog.show();
diff --git a/src/android/InAppChromeClient.java b/src/android/InAppChromeClient.java
index fe5dd3495..45e5e7699 100644
--- a/src/android/InAppChromeClient.java
+++ b/src/android/InAppChromeClient.java
@@ -24,6 +24,8 @@ Licensed to the Apache Software Foundation (ASF) under one
import org.json.JSONArray;
import org.json.JSONException;
+import android.view.View;
+import android.view.ViewGroup;
import android.webkit.JsPromptResult;
import android.webkit.WebChromeClient;
import android.webkit.WebStorage;
@@ -31,14 +33,14 @@ Licensed to the Apache Software Foundation (ASF) under one
import android.webkit.WebViewClient;
import android.webkit.GeolocationPermissions.Callback;
-public class InAppChromeClient extends WebChromeClient {
+public class InAppChromeClient extends VideoEnabledWebChromeClient {
private CordovaWebView webView;
private String LOG_TAG = "InAppChromeClient";
private long MAX_QUOTA = 100 * 1024 * 1024;
- public InAppChromeClient(CordovaWebView webView) {
- super();
+ public InAppChromeClient(CordovaWebView webView, View activityNonVideoView, ViewGroup activityVideoView) {
+ super(activityNonVideoView, activityVideoView);
this.webView = webView;
}
/**
diff --git a/src/android/VideoEnabledWebChromeClient.java b/src/android/VideoEnabledWebChromeClient.java
new file mode 100644
index 000000000..89dcea340
--- /dev/null
+++ b/src/android/VideoEnabledWebChromeClient.java
@@ -0,0 +1,294 @@
+package org.apache.cordova.inappbrowser;
+
+import android.media.MediaPlayer;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.WebChromeClient;
+import android.widget.FrameLayout;
+
+/**
+ * This class serves as a WebChromeClient to be set to a WebView, allowing it to play video.
+ * Video will play differently depending on target API level (in-line, fullscreen, or both).
+ *
+ * It has been tested with the following video classes:
+ * - android.widget.VideoView (typically API level <11)
+ * - android.webkit.HTML5VideoFullScreen$VideoSurfaceView/VideoTextureView (typically API level 11-18)
+ * - com.android.org.chromium.content.browser.ContentVideoView$VideoSurfaceView (typically API level 19+)
+ *
+ * Important notes:
+ * - For API level 11+, android:hardwareAccelerated="true" must be set in the application manifest.
+ * - The invoking activity must call VideoEnabledWebChromeClient's onBackPressed() inside of its own onBackPressed().
+ * - Tested in Android API levels 8-19. Only tested on http://m.youtube.com.
+ *
+ * @author Cristian Perez (http://cpr.name)
+ *
+ */
+public class VideoEnabledWebChromeClient extends WebChromeClient implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener
+{
+ public interface ToggledFullscreenCallback
+ {
+ public void toggledFullscreen(boolean fullscreen);
+ }
+
+ private View activityNonVideoView;
+ private ViewGroup activityVideoView;
+ private View loadingView;
+ private VideoEnabledWebView webView;
+
+ private boolean isVideoFullscreen; // Indicates if the video is being displayed using a custom view (typically full-screen)
+ private FrameLayout videoViewContainer;
+ private CustomViewCallback videoViewCallback;
+
+ private ToggledFullscreenCallback toggledFullscreenCallback;
+
+ /**
+ * Never use this constructor alone.
+ * This constructor allows this class to be defined as an inline inner class in which the user can override methods
+ */
+ @SuppressWarnings("unused")
+ public VideoEnabledWebChromeClient()
+ {
+ }
+
+ /**
+ * Builds a video enabled WebChromeClient.
+ * @param activityNonVideoView A View in the activity's layout that contains every other view that should be hidden when the video goes full-screen.
+ * @param activityVideoView A ViewGroup in the activity's layout that will display the video. Typically you would like this to fill the whole layout.
+ */
+ @SuppressWarnings("unused")
+ public VideoEnabledWebChromeClient(View activityNonVideoView, ViewGroup activityVideoView)
+ {
+ this.activityNonVideoView = activityNonVideoView;
+ this.activityVideoView = activityVideoView;
+ this.loadingView = null;
+ this.webView = null;
+ this.isVideoFullscreen = false;
+ }
+
+ /**
+ * Builds a video enabled WebChromeClient.
+ * @param activityNonVideoView A View in the activity's layout that contains every other view that should be hidden when the video goes full-screen.
+ * @param activityVideoView A ViewGroup in the activity's layout that will display the video. Typically you would like this to fill the whole layout.
+ * @param loadingView A View to be shown while the video is loading (typically only used in API level <11). Must be already inflated and not attached to a parent view.
+ */
+ @SuppressWarnings("unused")
+ public VideoEnabledWebChromeClient(View activityNonVideoView, ViewGroup activityVideoView, View loadingView)
+ {
+ this.activityNonVideoView = activityNonVideoView;
+ this.activityVideoView = activityVideoView;
+ this.loadingView = loadingView;
+ this.webView = null;
+ this.isVideoFullscreen = false;
+ }
+
+ /**
+ * Builds a video enabled WebChromeClient.
+ * @param activityNonVideoView A View in the activity's layout that contains every other view that should be hidden when the video goes full-screen.
+ * @param activityVideoView A ViewGroup in the activity's layout that will display the video. Typically you would like this to fill the whole layout.
+ * @param loadingView A View to be shown while the video is loading (typically only used in API level <11). Must be already inflated and not attached to a parent view.
+ * @param webView The owner VideoEnabledWebView. Passing it will enable the VideoEnabledWebChromeClient to detect the HTML5 video ended event and exit full-screen.
+ * Note: The web page must only contain one video tag in order for the HTML5 video ended event to work. This could be improved if needed (see Javascript code).
+ */
+ @SuppressWarnings("unused")
+ public VideoEnabledWebChromeClient(View activityNonVideoView, ViewGroup activityVideoView, View loadingView, VideoEnabledWebView webView)
+ {
+ this.activityNonVideoView = activityNonVideoView;
+ this.activityVideoView = activityVideoView;
+ this.loadingView = loadingView;
+ this.webView = webView;
+ this.isVideoFullscreen = false;
+ }
+
+ /**
+ * Indicates if the video is being displayed using a custom view (typically full-screen)
+ * @return true it the video is being displayed using a custom view (typically full-screen)
+ */
+ public boolean isVideoFullscreen()
+ {
+ return isVideoFullscreen;
+ }
+
+ /**
+ * Set a callback that will be fired when the video starts or finishes displaying using a custom view (typically full-screen)
+ * @param callback A VideoEnabledWebChromeClient.ToggledFullscreenCallback callback
+ */
+ @SuppressWarnings("unused")
+ public void setOnToggledFullscreen(ToggledFullscreenCallback callback)
+ {
+ this.toggledFullscreenCallback = callback;
+ }
+
+ @Override
+ public void onShowCustomView(View view, CustomViewCallback callback)
+ {
+ if (view instanceof FrameLayout)
+ {
+ // A video wants to be shown
+ FrameLayout frameLayout = (FrameLayout) view;
+ View focusedChild = frameLayout.getFocusedChild();
+
+ // Save video related variables
+ this.isVideoFullscreen = true;
+ this.videoViewContainer = frameLayout;
+ this.videoViewCallback = callback;
+
+ // Hide the non-video view, add the video view, and show it
+ if (activityNonVideoView != null)
+ {
+ activityNonVideoView.setVisibility(View.INVISIBLE);
+ }
+
+ if (activityVideoView != null)
+ {
+ activityVideoView.addView(videoViewContainer, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ activityVideoView.setVisibility(View.VISIBLE);
+ }
+
+ if (focusedChild instanceof android.widget.VideoView)
+ {
+ // android.widget.VideoView (typically API level <11)
+ android.widget.VideoView videoView = (android.widget.VideoView) focusedChild;
+
+ // Handle all the required events
+ videoView.setOnPreparedListener(this);
+ videoView.setOnCompletionListener(this);
+ videoView.setOnErrorListener(this);
+ }
+ else
+ {
+ // Other classes, including:
+ // - android.webkit.HTML5VideoFullScreen$VideoSurfaceView, which inherits from android.view.SurfaceView (typically API level 11-18)
+ // - android.webkit.HTML5VideoFullScreen$VideoTextureView, which inherits from android.view.TextureView (typically API level 11-18)
+ // - com.android.org.chromium.content.browser.ContentVideoView$VideoSurfaceView, which inherits from android.view.SurfaceView (typically API level 19+)
+
+ // Handle HTML5 video ended event only if the class is a SurfaceView
+ // Test case: TextureView of Sony Xperia T API level 16 doesn't work fullscreen when loading the javascript below
+ if (webView != null && webView.getSettings().getJavaScriptEnabled() && focusedChild instanceof SurfaceView)
+ {
+ // Run javascript code that detects the video end and notifies the Javascript interface
+ String js = "javascript:";
+ js += "var _ytrp_html5_video_last;";
+ js += "var _ytrp_html5_video = document.getElementsByTagName('video')[0];";
+ js += "if (_ytrp_html5_video != undefined && _ytrp_html5_video != _ytrp_html5_video_last) {";
+ {
+ js += "_ytrp_html5_video_last = _ytrp_html5_video;";
+ js += "function _ytrp_html5_video_ended() {";
+ {
+ js += "_VideoEnabledWebView.notifyVideoEnd();"; // Must match Javascript interface name and method of VideoEnableWebView
+ }
+ js += "}";
+ js += "_ytrp_html5_video.addEventListener('ended', _ytrp_html5_video_ended);";
+ }
+ js += "}";
+ webView.loadUrl(js);
+ }
+ }
+
+ // Notify full-screen change
+ if (toggledFullscreenCallback != null)
+ {
+ toggledFullscreenCallback.toggledFullscreen(true);
+ }
+ }
+ }
+
+ @Override @SuppressWarnings("deprecation")
+ public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback) // Available in API level 14+, deprecated in API level 18+
+ {
+ onShowCustomView(view, callback);
+ }
+
+ @Override
+ public void onHideCustomView()
+ {
+ // This method should be manually called on video end in all cases because it's not always called automatically.
+ // This method must be manually called on back key press (from this class' onBackPressed() method).
+
+ if (isVideoFullscreen)
+ {
+ // Hide the video view, remove it, and show the non-video view
+ if (activityVideoView != null)
+ {
+ activityVideoView.setVisibility(View.INVISIBLE);
+ activityVideoView.removeView(videoViewContainer);
+ }
+
+ if (activityNonVideoView != null) {
+ activityNonVideoView.setVisibility(View.VISIBLE);
+ }
+
+ // Call back (only in API level <19, because in API level 19+ with chromium webview it crashes)
+ if (videoViewCallback != null && !videoViewCallback.getClass().getName().contains(".chromium."))
+ {
+ videoViewCallback.onCustomViewHidden();
+ }
+
+ // Reset video related variables
+ isVideoFullscreen = false;
+ videoViewContainer = null;
+ videoViewCallback = null;
+
+ // Notify full-screen change
+ if (toggledFullscreenCallback != null)
+ {
+ toggledFullscreenCallback.toggledFullscreen(false);
+ }
+ }
+ }
+
+ @Override
+ public View getVideoLoadingProgressView() // Video will start loading
+ {
+ if (loadingView != null)
+ {
+ loadingView.setVisibility(View.VISIBLE);
+ return loadingView;
+ }
+ else
+ {
+ return super.getVideoLoadingProgressView();
+ }
+ }
+
+ @Override
+ public void onPrepared(MediaPlayer mp) // Video will start playing, only called in the case of android.widget.VideoView (typically API level <11)
+ {
+ if (loadingView != null)
+ {
+ loadingView.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public void onCompletion(MediaPlayer mp) // Video finished playing, only called in the case of android.widget.VideoView (typically API level <11)
+ {
+ onHideCustomView();
+ }
+
+ @Override
+ public boolean onError(MediaPlayer mp, int what, int extra) // Error while playing video, only called in the case of android.widget.VideoView (typically API level <11)
+ {
+ return false; // By returning false, onCompletion() will be called
+ }
+
+ /**
+ * Notifies the class that the back key has been pressed by the user.
+ * This must be called from the Activity's onBackPressed(), and if it returns false, the activity itself should handle it. Otherwise don't do anything.
+ * @return Returns true if the event was handled, and false if was not (video view is not visible)
+ */
+ @SuppressWarnings("unused")
+ public boolean onBackPressed()
+ {
+ if (isVideoFullscreen)
+ {
+ onHideCustomView();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+}
diff --git a/src/android/VideoEnabledWebView.java b/src/android/VideoEnabledWebView.java
new file mode 100644
index 000000000..600750a24
--- /dev/null
+++ b/src/android/VideoEnabledWebView.java
@@ -0,0 +1,139 @@
+package org.apache.cordova.inappbrowser;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.webkit.WebChromeClient;
+import android.webkit.WebView;
+
+import java.util.Map;
+
+/**
+ * This class serves as a WebView to be used in conjunction with a VideoEnabledWebChromeClient.
+ * It makes possible:
+ * - To detect the HTML5 video ended event so that the VideoEnabledWebChromeClient can exit full-screen.
+ *
+ * Important notes:
+ * - Javascript is enabled by default and must not be disabled with getSettings().setJavaScriptEnabled(false).
+ * - setWebChromeClient() must be called before any loadData(), loadDataWithBaseURL() or loadUrl() method.
+ *
+ * @author Cristian Perez (http://cpr.name)
+ *
+ */
+public class VideoEnabledWebView extends WebView
+{
+ public class JavascriptInterface
+ {
+ @android.webkit.JavascriptInterface @SuppressWarnings("unused")
+ public void notifyVideoEnd() // Must match Javascript interface method of VideoEnabledWebChromeClient
+ {
+ Log.d("___", "GOT IT");
+ // This code is not executed in the UI thread, so we must force that to happen
+ new Handler(Looper.getMainLooper()).post(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ if (videoEnabledWebChromeClient != null)
+ {
+ videoEnabledWebChromeClient.onHideCustomView();
+ }
+ }
+ });
+ }
+ }
+
+ private VideoEnabledWebChromeClient videoEnabledWebChromeClient;
+ private boolean addedJavascriptInterface;
+
+ @SuppressWarnings("unused")
+ public VideoEnabledWebView(Context context)
+ {
+ super(context);
+ addedJavascriptInterface = false;
+ }
+
+ @SuppressWarnings("unused")
+ public VideoEnabledWebView(Context context, AttributeSet attrs)
+ {
+ super(context, attrs);
+ addedJavascriptInterface = false;
+ }
+
+ @SuppressWarnings("unused")
+ public VideoEnabledWebView(Context context, AttributeSet attrs, int defStyle)
+ {
+ super(context, attrs, defStyle);
+ addedJavascriptInterface = false;
+ }
+
+ /**
+ * Indicates if the video is being displayed using a custom view (typically full-screen)
+ * @return true it the video is being displayed using a custom view (typically full-screen)
+ */
+ @SuppressWarnings("unused")
+ public boolean isVideoFullscreen()
+ {
+ return videoEnabledWebChromeClient != null && videoEnabledWebChromeClient.isVideoFullscreen();
+ }
+
+ /**
+ * Pass only a VideoEnabledWebChromeClient instance.
+ */
+ @Override @SuppressLint("SetJavaScriptEnabled")
+ public void setWebChromeClient(WebChromeClient client)
+ {
+ getSettings().setJavaScriptEnabled(true);
+
+ if (client instanceof VideoEnabledWebChromeClient)
+ {
+ this.videoEnabledWebChromeClient = (VideoEnabledWebChromeClient) client;
+ }
+
+ super.setWebChromeClient(client);
+ }
+
+ @Override
+ public void loadData(String data, String mimeType, String encoding)
+ {
+ addJavascriptInterface();
+ super.loadData(data, mimeType, encoding);
+ }
+
+ @Override
+ public void loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl)
+ {
+ addJavascriptInterface();
+ super.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
+ }
+
+ @Override
+ public void loadUrl(String url)
+ {
+ addJavascriptInterface();
+ super.loadUrl(url);
+ }
+
+ @Override
+ public void loadUrl(String url, Map additionalHttpHeaders)
+ {
+ addJavascriptInterface();
+ super.loadUrl(url, additionalHttpHeaders);
+ }
+
+ private void addJavascriptInterface()
+ {
+ if (!addedJavascriptInterface)
+ {
+ // Add javascript interface to be called when the video ends (must be done before page load)
+ //noinspection all
+ addJavascriptInterface(new JavascriptInterface(), "_VideoEnabledWebView"); // Must match Javascript interface name of VideoEnabledWebChromeClient
+
+ addedJavascriptInterface = true;
+ }
+ }
+
+}