diff --git a/plugin.xml b/plugin.xml
index d061c700e..3fc2867b7 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -49,6 +49,8 @@
+
+
diff --git a/src/android/InAppBrowser.java b/src/android/InAppBrowser.java
index 9a9fc7a8f..01010a231 100644
--- a/src/android/InAppBrowser.java
+++ b/src/android/InAppBrowser.java
@@ -6,9 +6,7 @@ Licensed to the Apache Software Foundation (ASF) under one
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
-
http://www.apache.org/licenses/LICENSE-2.0
-
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -18,12 +16,14 @@ 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.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.pm.ActivityInfo;
import android.os.Parcelable;
import android.provider.Browser;
import android.content.res.Resources;
@@ -34,6 +34,7 @@ Licensed to the Apache Software Foundation (ASF) under one
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
import android.text.InputType;
import android.util.TypedValue;
import android.view.Gravity;
@@ -132,8 +133,10 @@ public class InAppBrowser extends CordovaPlugin {
private boolean mediaPlaybackRequiresUserGesture = false;
private boolean shouldPauseInAppBrowser = false;
private boolean useWideViewPort = true;
- private ValueCallback mUploadCallback;
+ private ValueCallback mUploadCallback;
+ private ValueCallback mUploadCallbackLollipop;
private final static int FILECHOOSER_REQUESTCODE = 1;
+ private final static int FILECHOOSER_REQUESTCODE_LOLLIPOP = 2;
private String closeButtonCaption = "";
private String closeButtonColor = "";
private boolean leftToRight = false;
@@ -264,10 +267,7 @@ else if (action.equals("loadAfterBeforeload")) {
@Override
public void run() {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O) {
- currentClient.waitForBeforeload = false;
inAppWebView.setWebViewClient(currentClient);
- } else {
- ((InAppBrowserClient)inAppWebView.getWebViewClient()).waitForBeforeload = false;
}
inAppWebView.loadUrl(url);
}
@@ -716,6 +716,8 @@ 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
*
@@ -773,6 +775,38 @@ public void onClick(View v) {
return _close;
}
+ 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);
+ }
+ }
+
@SuppressLint("NewApi")
public void run() {
@@ -785,6 +819,19 @@ public void run() {
dialog = new InAppBrowserDialog(cordova.getActivity(), android.R.style.Theme_NoTitleBar);
dialog.getWindow().getAttributes().windowAnimations = android.R.style.Animation_Dialog;
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ 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 (fullscreen) {
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
@@ -792,6 +839,10 @@ public void run() {
dialog.setInAppBroswer(getInAppBrowser());
// Main container layout
+ RelativeLayout fsmain = 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());
LinearLayout main = new LinearLayout(cordova.getActivity());
main.setOrientation(LinearLayout.VERTICAL);
@@ -917,15 +968,16 @@ public boolean onKey(View v, int keyCode, KeyEvent event) {
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)
{
LOG.d(LOG_TAG, "File Chooser 5.0+");
// If callback exists, finish it.
- if(mUploadCallback != null) {
- mUploadCallback.onReceiveValue(null);
+ if(mUploadCallbackLollipop != null) {
+ mUploadCallbackLollipop.onReceiveValue(null);
}
- mUploadCallback = filePathCallback;
+ mUploadCallbackLollipop = filePathCallback;
// Create File Chooser Intent
Intent content = new Intent(Intent.ACTION_GET_CONTENT);
@@ -933,10 +985,56 @@ public boolean onShowFileChooser (WebView webView, ValueCallback filePath
content.setType("*/*");
// Run cordova startActivityForResult
- cordova.startActivityForResult(InAppBrowser.this, Intent.createChooser(content, "Select File"), FILECHOOSER_REQUESTCODE);
+ cordova.startActivityForResult(InAppBrowser.this, Intent.createChooser(content, "Select File"), FILECHOOSER_REQUESTCODE_LOLLIPOP);
return true;
}
+
+ // For Android 4.1+
+ public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture)
+ {
+ LOG.d(LOG_TAG, "File Chooser 4.1+");
+ // Call file chooser for Android 3.0+
+ openFileChooser(uploadMsg, acceptType);
+ }
+
+ // For Android 3.0+
+ public void openFileChooser(ValueCallback uploadMsg, String acceptType)
+ {
+ LOG.d(LOG_TAG, "File Chooser 3.0+");
+ mUploadCallback = uploadMsg;
+ Intent content = new Intent(Intent.ACTION_GET_CONTENT);
+ content.addCategory(Intent.CATEGORY_OPENABLE);
+
+ // run startActivityForResult
+ cordova.startActivityForResult(InAppBrowser.this, Intent.createChooser(content, "Select File"), FILECHOOSER_REQUESTCODE);
+ }
+
+ };
+
+ inAppChromeClient.setOnToggledFullscreen(new VideoEnabledWebChromeClient.ToggledFullscreenCallback() {
+ @Override
+ public void toggledFullscreen(boolean fullscreenV)
+ {
+ // 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 (fullscreenV)
+ {
+ enableFullScreen(activity, window);
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
+ }
+ else
+ {
+ if (!fullscreen)
+ {
+ 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();
@@ -1031,8 +1129,11 @@ public void postMessage(String data) {
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.MATCH_PARENT;
+ fsmain.addView(main);
+ fsmain.addView(fullScreenMain);
+
if (dialog != null) {
- dialog.setContentView(main);
+ dialog.setContentView(fsmain);
dialog.show();
dialog.getWindow().setAttributes(lp);
}
@@ -1083,12 +1184,12 @@ private void sendUpdate(JSONObject obj, boolean keepCallback, PluginResult.Statu
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
LOG.d(LOG_TAG, "onActivityResult");
// If RequestCode or Callback is Invalid
- if(requestCode != FILECHOOSER_REQUESTCODE || mUploadCallback == null) {
+ if(requestCode != FILECHOOSER_REQUESTCODE_LOLLIPOP || mUploadCallbackLollipop == null) {
super.onActivityResult(requestCode, resultCode, intent);
return;
}
- mUploadCallback.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent));
- mUploadCallback = null;
+ mUploadCallbackLollipop.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent));
+ mUploadCallbackLollipop = null;
}
/**
@@ -1098,7 +1199,6 @@ public class InAppBrowserClient extends WebViewClient {
EditText edittext;
CordovaWebView webView;
String beforeload;
- boolean waitForBeforeload;
/**
* Constructor.
@@ -1110,7 +1210,6 @@ public InAppBrowserClient(CordovaWebView webView, EditText mEditText, String bef
this.webView = webView;
this.edittext = mEditText;
this.beforeload = beforeload;
- this.waitForBeforeload = beforeload != null;
}
/**
@@ -1171,7 +1270,7 @@ public boolean shouldOverrideUrlLoading(String url, String method) {
}
// On first URL change, initiate JS callback. Only after the beforeload event, continue.
- if (useBeforeload && this.waitForBeforeload) {
+ if (useBeforeload) {
if(sendBeforeLoad(url, method)) {
return true;
}
@@ -1266,9 +1365,6 @@ else if (!url.startsWith("http:") && !url.startsWith("https:") && url.matches("^
}
}
- if (useBeforeload) {
- this.waitForBeforeload = true;
- }
return override;
}
@@ -1459,4 +1555,4 @@ public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, Str
super.onReceivedHttpAuthRequest(view, handler, host, realm);
}
}
-}
+}
\ No newline at end of file
diff --git a/src/android/InAppChromeClient.java b/src/android/InAppChromeClient.java
index d73b11d37..d011a708e 100644
--- a/src/android/InAppChromeClient.java
+++ b/src/android/InAppChromeClient.java
@@ -24,6 +24,9 @@ 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.annotation.TargetApi;
import android.os.Build;
import android.os.Message;
@@ -35,14 +38,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..ee26ce596
--- /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;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/android/VideoEnabledWebView.java b/src/android/VideoEnabledWebView.java
new file mode 100644
index 000000000..68c3a4402
--- /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;
+ }
+ }
+
+}
\ No newline at end of file