mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-14 18:06:39 -04:00
Convert VideoEnabledWebChromeClient.java to Kotlin
This commit is contained in:
parent
820615edf3
commit
4d71421fe6
@ -24,10 +24,11 @@ import android.os.Handler
|
||||
import android.os.Message
|
||||
import android.util.AttributeSet
|
||||
import android.view.ContextMenu
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.WebView
|
||||
import org.kiwix.videowebview.VideoEnabledWebView
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import org.kiwix.kiwixmobile.core.BuildConfig
|
||||
import org.kiwix.kiwixmobile.core.CoreApp.Companion.coreComponent
|
||||
@ -38,6 +39,8 @@ import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
||||
import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.getCurrentLocale
|
||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||
import org.kiwix.kiwixmobile.core.utils.files.FileUtils
|
||||
import org.kiwix.videowebview.VideoEnabledWebChromeClient.ToggledFullscreenCallback
|
||||
import org.kiwix.videowebview.VideoEnabledWebView
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val INITIAL_SCALE = 100
|
||||
@ -59,8 +62,18 @@ open class KiwixWebView @SuppressLint("SetJavaScriptEnabled") constructor(
|
||||
|
||||
private val compositeDisposable = CompositeDisposable()
|
||||
|
||||
private fun setWindowVisibility(systemUiVisibility: Int) {
|
||||
(context as Activity).window.decorView.systemUiVisibility = systemUiVisibility
|
||||
private fun setWindowVisibility(isFullScreen: Boolean) {
|
||||
val window = (context as Activity).window
|
||||
WindowCompat.setDecorFitsSystemWindows(window, !isFullScreen)
|
||||
WindowInsetsControllerCompat(window, window.decorView.rootView).apply {
|
||||
if (isFullScreen) {
|
||||
hide(WindowInsetsCompat.Type.statusBars())
|
||||
hide(WindowInsetsCompat.Type.navigationBars())
|
||||
} else {
|
||||
show(WindowInsetsCompat.Type.statusBars())
|
||||
show(WindowInsetsCompat.Type.navigationBars())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
@ -83,12 +96,12 @@ open class KiwixWebView @SuppressLint("SetJavaScriptEnabled") constructor(
|
||||
clearCache(true)
|
||||
setWebViewClient(webViewClient)
|
||||
webChromeClient = KiwixWebChromeClient(callback, nonVideoView, videoView, this).apply {
|
||||
setOnToggledFullscreen { fullscreen ->
|
||||
setWindowVisibility(
|
||||
if (fullscreen) View.SYSTEM_UI_FLAG_LOW_PROFILE else View.SYSTEM_UI_FLAG_VISIBLE
|
||||
)
|
||||
callback.onFullscreenVideoToggled(fullscreen)
|
||||
}
|
||||
setOnToggledFullscreen(object : ToggledFullscreenCallback {
|
||||
override fun toggledFullscreen(fullscreen: Boolean) {
|
||||
setWindowVisibility(fullscreen)
|
||||
callback.onFullscreenVideoToggled(fullscreen)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,309 +0,0 @@
|
||||
/*
|
||||
* Kiwix Android
|
||||
* Copyright (c) 2022 Kiwix <android.kiwix.org>
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.kiwix.videowebview;
|
||||
|
||||
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
|
||||
activityNonVideoView.setVisibility(View.INVISIBLE);
|
||||
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
|
||||
activityVideoView.setVisibility(View.INVISIBLE);
|
||||
activityVideoView.removeView(videoViewContainer);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Kiwix Android
|
||||
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package org.kiwix.videowebview
|
||||
|
||||
import android.media.MediaPlayer
|
||||
import android.media.MediaPlayer.OnCompletionListener
|
||||
import android.media.MediaPlayer.OnPreparedListener
|
||||
import android.view.SurfaceView
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.WebChromeClient
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.VideoView
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
open class VideoEnabledWebChromeClient :
|
||||
WebChromeClient,
|
||||
OnPreparedListener,
|
||||
OnCompletionListener,
|
||||
MediaPlayer.OnErrorListener {
|
||||
interface ToggledFullscreenCallback {
|
||||
fun toggledFullscreen(fullscreen: Boolean)
|
||||
}
|
||||
|
||||
private var activityNonVideoView: View? = null
|
||||
private var activityVideoView: ViewGroup? = null
|
||||
private var loadingView: View? = null
|
||||
private var webView: VideoEnabledWebView? = null
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
private var isVideoFullscreen = false
|
||||
|
||||
// Indicates if the video is being displayed using a custom view (typically full-screen)
|
||||
private var videoViewContainer: FrameLayout? = null
|
||||
private var videoViewCallback: CustomViewCallback? = null
|
||||
private var toggledFullscreenCallback: ToggledFullscreenCallback? = null
|
||||
|
||||
/**
|
||||
* 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("EmptySecondaryConstructor", "unused")
|
||||
constructor() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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")
|
||||
constructor(activityNonVideoView: View?, activityVideoView: ViewGroup?) {
|
||||
this.activityNonVideoView = activityNonVideoView
|
||||
this.activityVideoView = activityVideoView
|
||||
loadingView = null
|
||||
webView = null
|
||||
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")
|
||||
constructor(
|
||||
activityNonVideoView: View?,
|
||||
activityVideoView: ViewGroup?,
|
||||
loadingView: View?
|
||||
) {
|
||||
this.activityNonVideoView = activityNonVideoView
|
||||
this.activityVideoView = activityVideoView
|
||||
this.loadingView = loadingView
|
||||
webView = null
|
||||
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")
|
||||
constructor(
|
||||
activityNonVideoView: View?,
|
||||
activityVideoView: ViewGroup?,
|
||||
loadingView: View?,
|
||||
webView: VideoEnabledWebView?
|
||||
) {
|
||||
this.activityNonVideoView = activityNonVideoView
|
||||
this.activityVideoView = activityVideoView
|
||||
this.loadingView = loadingView
|
||||
this.webView = webView
|
||||
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)
|
||||
*/
|
||||
fun isVideoFullscreen(): Boolean = 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")
|
||||
fun setOnToggledFullscreen(callback: ToggledFullscreenCallback) {
|
||||
toggledFullscreenCallback = callback
|
||||
}
|
||||
|
||||
@SuppressWarnings("NestedBlockDepth", "deprecation")
|
||||
override fun onShowCustomView(view: View, callback: CustomViewCallback) {
|
||||
if (view is FrameLayout) {
|
||||
// A video wants to be shown
|
||||
val focusedChild = view.focusedChild
|
||||
|
||||
// Save video related variables
|
||||
isVideoFullscreen = true
|
||||
videoViewContainer = view
|
||||
videoViewCallback = callback
|
||||
|
||||
// Hide the non-video view, add the video view, and show it
|
||||
activityNonVideoView?.visibility = View.INVISIBLE
|
||||
activityVideoView?.addView(
|
||||
videoViewContainer,
|
||||
ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
)
|
||||
activityVideoView?.visibility = View.VISIBLE
|
||||
if (focusedChild is VideoView) {
|
||||
// android.widget.VideoView (typically API level <11)
|
||||
|
||||
// Handle all the required events
|
||||
focusedChild.setOnPreparedListener(this)
|
||||
focusedChild.setOnCompletionListener(this)
|
||||
focusedChild.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
|
||||
|
||||
webView?.let {
|
||||
if (it.settings.javaScriptEnabled && focusedChild is SurfaceView) {
|
||||
// Run javascript code that detects the video end and notifies the Javascript interface
|
||||
var js = "javascript:"
|
||||
js += "var _ytrp_html5_video_last;"
|
||||
js += "var _ytrp_html5_video = document.getElementsByTagName('video')[0];"
|
||||
js += "if (_ytrp_html5_video != undefined"
|
||||
js += " && _ytrp_html5_video != _ytrp_html5_video_last) {"
|
||||
js += "_ytrp_html5_video_last = _ytrp_html5_video;"
|
||||
js += "function _ytrp_html5_video_ended() {"
|
||||
// Must match Javascript interface name and method of VideoEnableWebView
|
||||
js += "_VideoEnabledWebView.notifyVideoEnd();"
|
||||
js += "}"
|
||||
js += "_ytrp_html5_video.addEventListener('ended', _ytrp_html5_video_ended);"
|
||||
js += "}"
|
||||
it.loadUrl(js)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notify full-screen change
|
||||
toggledFullscreenCallback?.toggledFullscreen(true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onShowCustomView(
|
||||
view: View,
|
||||
requestedOrientation: Int,
|
||||
callback: CustomViewCallback
|
||||
) { // Available in API level 14+, deprecated in API level 18+
|
||||
onShowCustomView(view, callback)
|
||||
}
|
||||
|
||||
override fun 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
|
||||
activityVideoView?.visibility = View.INVISIBLE
|
||||
activityVideoView?.removeView(videoViewContainer)
|
||||
activityNonVideoView?.visibility = View.VISIBLE
|
||||
|
||||
// Call back (only in API level <19, because in API level 19+ with chromium webview it crashes)
|
||||
videoViewCallback?.let {
|
||||
if (it.javaClass.name.contains(".chromium.")) {
|
||||
it.onCustomViewHidden()
|
||||
}
|
||||
}
|
||||
// Reset video related variables
|
||||
isVideoFullscreen = false
|
||||
videoViewContainer = null
|
||||
videoViewCallback = null
|
||||
|
||||
// Notify full-screen change
|
||||
toggledFullscreenCallback?.toggledFullscreen(false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getVideoLoadingProgressView(): View? { // Video will start loading
|
||||
return if (loadingView != null) {
|
||||
loadingView?.visibility = View.VISIBLE
|
||||
loadingView
|
||||
} else {
|
||||
super.getVideoLoadingProgressView()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPrepared(
|
||||
mp: MediaPlayer
|
||||
) {
|
||||
// - Video will start playing, only called in the case of
|
||||
// android.widget.VideoView (typically API level <11)
|
||||
loadingView?.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onCompletion(
|
||||
mp: MediaPlayer
|
||||
) {
|
||||
// - Video finished playing, only called in the case
|
||||
// of android.widget.VideoView (typically API level <11)
|
||||
onHideCustomView()
|
||||
}
|
||||
|
||||
// - Error while playing video, only called in the case
|
||||
// of android.widget.VideoView (typically API level <11)
|
||||
override fun onError(
|
||||
mp: MediaPlayer,
|
||||
what: Int,
|
||||
extra: Int
|
||||
): Boolean =
|
||||
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")
|
||||
fun onBackPressed(): Boolean {
|
||||
return if (isVideoFullscreen) {
|
||||
onHideCustomView()
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
@ -80,7 +80,7 @@ open class VideoEnabledWebView : WebView {
|
||||
* @return true it the video is being displayed using a custom view (typically full-screen)
|
||||
*/
|
||||
val isVideoFullscreen: Boolean
|
||||
get() = videoEnabledWebChromeClient?.isVideoFullscreen == true
|
||||
get() = videoEnabledWebChromeClient?.isVideoFullscreen() == true
|
||||
|
||||
/**
|
||||
* Pass only a VideoEnabledWebChromeClient instance.
|
||||
|
Loading…
x
Reference in New Issue
Block a user