安卓WebView中全屏播放网页视频
来源:互联网 发布:淘宝中如何发布宝贝 编辑:程序博客网 时间:2024/05/22 12:03
Android中WebView是支持播放网页视频的,需打开WebView的脚本支持:
//设置WebView属性,能够执行Javascript脚本webView.getSettings().setJavaScriptEnabled(true);
但是要全屏播放网页中的视频,在Android 4.0以下,能支持,4.0以上就有点鸡肋了。解决方法是需要重写WebView和WebChromeCient,实现方式是当全屏的时候隐藏掉界面的其他控件,使用一个占满屏幕宽高的ViewGroup来承载视频的播放。布局代码如下:
<LinearLayout android:id="@+id/parent" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <your_package_name.VideoEnabledWebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent" /></LinearLayout><FrameLayout android:id="@+id/videoLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" android:background="#000000" />
当用户点击全屏播放的时候,隐藏掉id为parent的部分(visibility设置为gone),使用id为videoLayout的FragmentLayout(visibility设置为visible)来承载视频。这一切操作,都封装在了自定义的WebChromeCient里,使用时只需按以上方式写xml,需要注意的是视频的载体ViewGroup必须为FrameLayout。
自定义WebChromeClient的代码如下:
import android.app.ActionBar.LayoutParams;import android.app.Activity;import android.media.MediaPlayer;import android.media.MediaPlayer.OnCompletionListener;import android.media.MediaPlayer.OnErrorListener;import android.media.MediaPlayer.OnPreparedListener;import android.view.View;import android.view.ViewGroup;import android.view.WindowManager;import android.webkit.WebChromeClient;import android.widget.FrameLayout;import android.widget.VideoView;public class VideoEnabledWebChromeClient extends WebChromeClient implements OnPreparedListener, OnCompletionListener, OnErrorListener { public interface ToggledFullscreenCallback { 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; private Activity mContext; /** * 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 */ 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. */ public VideoEnabledWebChromeClient(Activity activity, View activityNonVideoView, ViewGroup activityVideoView) { this.mContext = activity; 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 without a parent view. */ public VideoEnabledWebChromeClient(Activity activity,View activityNonVideoView, ViewGroup activityVideoView, View loadingView) { this.mContext = activity; 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 without 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). */ public VideoEnabledWebChromeClient(Activity activity,View activityNonVideoView, ViewGroup activityVideoView, View loadingView, VideoEnabledWebView webView) { this.mContext = activity; 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 */ 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.GONE); activityVideoView.addView(videoViewContainer, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); activityVideoView.setVisibility(View.VISIBLE); if (focusedChild instanceof VideoView) { // VideoView (typically API level <11) VideoView videoView = (VideoView) focusedChild; // Handle all the required events videoView.setOnPreparedListener(this); videoView.setOnCompletionListener(this); videoView.setOnErrorListener(this); } else // Usually android.webkit.HTML5VideoFullScreen$VideoSurfaceView, sometimes android.webkit.HTML5VideoFullScreen$VideoTextureView { // HTML5VideoFullScreen (typically API level 11+) // Handle HTML5 video ended event if (webView != null && webView.getSettings().getJavaScriptEnabled()) { // Run javascript code that detects the video end and notifies the interface String js = "javascript:"; js += "_ytrp_html5_video = document.getElementsByTagName('video')[0];"; js += "if (_ytrp_html5_video !== undefined) {"; { js += "function _ytrp_html5_video_ended() {"; { js += "_ytrp_html5_video.removeEventListener('ended', _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); } setFullscreen(true); } } @Override public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback) // Only available in API level 14+ { onShowCustomView(view, callback); } @Override public void onHideCustomView() { // This method must be manually (internally) called on video end in the case of VideoView (typically API level <11) // This method must be manually (internally) called on video end in the case of HTML5VideoFullScreen (typically API level 11+) because it's not always called automatically // This method must be manually (internally) 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.GONE);//播放视频的 activityVideoView.removeView(videoViewContainer); activityNonVideoView.setVisibility(View.VISIBLE); // Call back if (videoViewCallback != null) videoViewCallback.onCustomViewHidden(); // Reset video related variables isVideoFullscreen = false; videoViewContainer = null; videoViewCallback = null; // Notify full-screen change if (toggledFullscreenCallback != null) { toggledFullscreenCallback.toggledFullscreen(false); } setFullscreen(false); } } @Override public View getVideoLoadingProgressView() // Video will start loading, only called in the case of VideoView (typically API level <11) { 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 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 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 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 it is not (video view is not visible) */ public boolean onBackPressed() { if (isVideoFullscreen) { onHideCustomView(); return true; } else { return false; } } private void setFullscreen(boolean enable) { if (enable) { //show status bar WindowManager.LayoutParams lp = mContext.getWindow().getAttributes(); lp.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN; mContext.getWindow().setAttributes(lp); mContext.getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); } else { //hide status bar WindowManager.LayoutParams lp = mContext.getWindow().getAttributes(); lp.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN); mContext.getWindow().setAttributes(lp); mContext.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); } }}
自定义WebView的代码如下:
import android.annotation.SuppressLint;import android.content.Context;import android.util.AttributeSet;import android.webkit.WebChromeClient;import android.webkit.WebView;import java.util.Map;public class VideoEnabledWebView extends WebView { private VideoEnabledWebChromeClient videoEnabledWebChromeClient; private boolean addedJavascriptInterface; public VideoEnabledWebView(Context context) { this(context, null); } public VideoEnabledWebView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public VideoEnabledWebView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); addedJavascriptInterface = false; } /** * 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<String, String> 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) addJavascriptInterface(new Object() { }, "_VideoEnabledWebView"); // Must match Javascript interface name of VideoEnabledWebChromeClient addedJavascriptInterface = true; } }}
在Activity里使用:
webView = (VideoEnabledWebView) findViewById(R.id.webView);parent = (LinearLayout) findViewById(R.id.parent);videoLayout = (FrameLayout) findViewById(R.id.videoLayout);webView.setWebChromeClient(new VideoEnabledWebChromeClient(this, parent, videoLayout));//load urlwebView.loadUrl(getIntent().getStringExtra("url"));
需要注意的地方:在创建 VideoEnabledWebChromeClient对象时,不能使用其无参构造方法,否则会抛空指针异常。
最后,在AndroidManifest.xml文件中配置Activity的configChanges属性,解决横竖屏切换导致WebView重新加载url。
<activity android:name=".WebViewActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
本项目(Demo)源码地址:
https://github.com/zengd0/WebViewPlayVideoDemo
1 0
- 安卓WebView中全屏播放网页视频
- 安卓WebView中全屏播放网页视频
- Android使用WebView全屏播放网页视频
- WebView全屏播放h5视频
- Android中加载WebView的H5全屏视频播放
- Android webview全屏播放HTML5中的视频
- WebView播放html5视频和全屏。
- webview全屏播放html5的视频
- android webview 播放视频 全屏问题
- android webView 全屏播放网络视频
- 安卓WebView加载腾讯视频无法播放
- Android WebView播放视频(包括全屏播放)
- Android WebView播放视频(包括全屏播放),androidwebview
- Android WebView 真正播放视频 全屏 横屏播放
- 网页中插入能全屏播放swf,flv视频的播放器
- 【转载】网页中插入能全屏播放swf,flv视频的播放器
- 网页中插入能全屏播放swf,flv视频的播放器
- 网页中播放视频
- 监听按钮的点击事件
- Python中的函数修饰符
- C++实现双链表的基本功能
- 计算给定多项式 在给定点 x = 1.1 处的值 f(1.1)
- 根据分类id,获取该分类下的商品数据(商品名,价格,路径,缩略图)
- 安卓WebView中全屏播放网页视频
- FFMPEG视音频编解码零基础学习方法
- HTML li如何垂直居中
- 几个之前不清楚的正则
- 后台执行Jquery代码
- Mac 在命令行中获得Root权限
- thinkphp5 console命令行执行计划任务
- [转]几种常见的网络协议--作者:小顾问(博客园)
- Mybatis 框架入门(一)