安卓 webview播放视频及横屏

本文详细介绍了在Android WebView中遇到的视频播放问题,包括视频无法播放、操作受限以及无法全屏播放。解决方案包括在AndroidManifest.xml中启用硬件加速,以及重写WebChromeClient的onShowCustomView()和onHideCustomView()方法来自定义横竖屏布局,实现全屏播放。通过这些方法,可以解决大部分WebView内视频播放的常见问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:

在项目中,会有在webview嵌入的网页中播放视频的需求,本来以为Android的WebView应该是默认支持视频播放的,不会有太大的问题,但是经过测试后,发现两个大问题:

  • 有些手机无法正常播放视频,出现白屏或者只有声音没有画面等,还有不能对视频进行操作(比如播放、暂停、自动播放等)
  • 视频无法全屏播放

视频在webview中正常播放:

这个只需要在对应的Activity中加入android:hardwareAccelerated="true"即可,如果不加的话,会在部分手机上出现白屏或有声音无画面等问题。还有不能对视频进行操作(比如播放、暂停、自动播放等)。

application和activity可直接在 AndroidManifest.xml 中添加该属性:

// 在application中
<application android:hardwareAccelerated ="true">
 
// 在activity中
<activity android:hardwareAccelerated="true" >

也可在代码中设置:

// 在代码中
getWindow.setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

注意:一定不要忘记加网络权限!


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

横竖屏播放:

webview加载视频网页的时候会遇到无法横屏的问题,此问题需要自己重新定义设置webview里面横竖屏布局。需要重写WebView的 WebChromeClient 的 onShowCustomView() 和 onHideCustomView() 方法就可以了。大概思路是:在 onShowCustomView() 中隐藏 WebView,并将得到的 View 添加到 FrameLayout 中显示,同时切换回横屏。在 onHideCustomView() 中隐藏 View,显示 WebView,同时切换回竖屏。具体代码如下:

	private WebView web_show;
    private WebSettings mWebSettings;
    /**
     * 视频全屏参数
     */
    protected static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    private View customView;
    private FrameLayout fullscreenContainer;
    private WebChromeClient.CustomViewCallback customViewCallback;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webvideo);

        web_show = findViewById(R.id.web_show);
        initWebView();
    }
    
	/**
     * 展示网页界面
     **/
    private void initWebView() {
        mWebSettings = web_show.getSettings();

        mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true);//设置js可以直接打开窗口,如window.open(),默认为false
        mWebSettings.setJavaScriptEnabled(true);//是否允许JavaScript脚本运行,默认为false。设置true时,会提醒可能造成XSS漏洞
        mWebSettings.setSupportZoom(true);//是否可以缩放,默认true
        mWebSettings.setBuiltInZoomControls(true);//是否显示缩放按钮,默认false
        mWebSettings.setUseWideViewPort(true);//设置此属性,可任意比例缩放。大视图模式
        mWebSettings.setLoadWithOverviewMode(true);//和setUseWideViewPort(true)一起解决网页自适应问题
        mWebSettings.setAppCacheEnabled(true);//是否使用缓存
        mWebSettings.setDomStorageEnabled(true);//开启本地DOM存储
        mWebSettings.setLoadsImagesAutomatically(true); // 加载图片
        mWebSettings.setMediaPlaybackRequiresUserGesture(false);//播放音频,多媒体需要用户手动?设置为false为可自动播放
        mWebSettings.setAllowFileAccess(true); // 允许访问文件

        web_show.loadUrl("http://liveshare.huya.com/iframe/swissski");

        //设置不用系统浏览器打开,直接显示在当前Webview
        web_show.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });
        web_show.setWebChromeClient(new WebChromeClient() {
            /*** 视频播放相关的方法 **/
            @Override
            public View getVideoLoadingProgressView() {
                FrameLayout frameLayout = new FrameLayout(HelloActivity.this);
                frameLayout.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
                return frameLayout;
            }

            @SuppressLint("SourceLockedOrientationActivity")
            @Override
            public void onShowCustomView(View view, CustomViewCallback callback) {
                showCustomView(view, callback);
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//播放时横屏幕,如果需要改变横竖屏,只需该参数就行了
            }

            @SuppressLint("SourceLockedOrientationActivity")
            @Override
            public void onHideCustomView() {
                hideCustomView();
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//不播放时竖屏
            }
        });
    }
    
	/**
     * 视频播放全屏
     **/
    private void showCustomView(View view, WebChromeClient.CustomViewCallback callback) {
        // if a view already exists then immediately terminate the new one
        if (customView != null) {
            callback.onCustomViewHidden();
            return;
        }

        this.getWindow().getDecorView();

        FrameLayout decor = (FrameLayout) getWindow().getDecorView();
        fullscreenContainer = new FullscreenHolder(HelloActivity.this);
        fullscreenContainer.addView(view, COVER_SCREEN_PARAMS);
        decor.addView(fullscreenContainer, COVER_SCREEN_PARAMS);
        customView = view;
        setStatusBarVisibility(false);
        customViewCallback = callback;
    }

    /**
     * 隐藏视频全屏
     */
    private void hideCustomView() {
        if (customView == null) {
            return;
        }
        setStatusBarVisibility(true);
        FrameLayout decor = (FrameLayout) getWindow().getDecorView();
        decor.removeView(fullscreenContainer);
        fullscreenContainer = null;
        customView = null;
        customViewCallback.onCustomViewHidden();
        web_show.setVisibility(View.VISIBLE);
    }

    /**
     * 全屏容器界面
     */
    static class FullscreenHolder extends FrameLayout {

        public FullscreenHolder(Context ctx) {
            super(ctx);
            setBackgroundColor(ctx.getResources().getColor(android.R.color.black));
        }

        @Override
        public boolean onTouchEvent(MotionEvent evt) {
            return true;
        }
    }

    private void setStatusBarVisibility(boolean visible) {
        int flag = visible ? 0 : WindowManager.LayoutParams.FLAG_FULLSCREEN;
        getWindow().setFlags(flag, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        web_show.stopLoading();
        web_show.setWebChromeClient(null);
        web_show.setWebViewClient(null);
        web_show = null;
    }

代码来源:https://blog.youkuaiyun.com/qq_35568796/article/details/85052103?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control

<think>好的,我现在需要回答用户关于Android WebView内嵌H5视频横屏播放的问题。首先,我要回忆一下自己对这个主题的了解。 用户的问题是希望在Android应用中通过WebView内嵌H5页面,并且当视频播放时能自动横屏。这个需求涉及到几个方面:WebView的设置、横屏切换的处理,以及可能的全屏播放问题。 首先,我需要考虑WebView的配置。为了让H5视频能够正常播放,可能需要启用JavaScript和DOM存储,还有可能需要设置WebChromeClient来处理全屏请求。记得WebView默认是支持视频播放的,需要特别设置。 然后,关于横屏的问题。当视频播放时,H5页面可能会触发全屏,这时候应用需要切换横屏。Android中处理屏幕方向通常是在Activity的manifest里设置,或者动态改变屏幕方向。但动态改变可能会有问题,比如Activity被销毁重建,这需要处理配置变化。 另外,全屏播放时,可能需要自定义WebChromeClient的onShowCustomView和onHideCustomView方法,来接管视图,这样可以在全屏时强制横屏,退出时恢复竖屏。 接下来,可能的步骤是: 1. 配置WebView启用JavaScript和必要的设置。 2. 设置WebChromeClient,处理全屏回调。 3. 在进入全屏时,改变Activity的屏幕方向为横屏,并隐藏系统UI。 4. 退出全屏时恢复竖屏,并显示系统UI。 5. 处理配置变化,防止Activity重建。 需要注意的是,同的Android版本可能有同的行为,尤其是配置变化处理。在AndroidManifest.xml中设置configChanges属性,如orientation|screenSize,可以避免Activity重启。同时,动态改变方向可能需要使用setRequestedOrientation方法。 另外,测试时可能会遇到H5页面本身的问题,比如某些视频播放器是否支持全屏触发,或者同浏览器的兼容性差异。可能需要和前端开发人员协作,确保H5页面正确触发全屏事件。 可能还需要处理全屏时的视图布局,将自定义视图添加到DecorView,并隐藏其他UI元素,比如ActionBar或状态栏,以提供真正的全屏体验。 总结下来,实现步骤大致如下: - 配置WebView支持视频播放。 - 处理全屏回调,切换横屏。 - 管理配置变化,避免Activity重启。 - 调整UI元素,确保全屏显示。 现在需要将这些步骤详细整理,并给出代码示例,同时提醒可能的注意事项,比如版本兼容性、与H5的协作等。</think>在Android WebView中实现H5视频横屏播放需要以下步骤: $$注意:以下代码示例基于Kotlin语言$$ 一、WebView基础配置 ```xml <!-- AndroidManifest.xml --> <activity android:name=".MainActivity" android:configChanges="orientation|screenSize|keyboardHidden" android:screenOrientation="portrait"/> ``` ```kotlin // WebView初始化 webView.settings.apply { javaScriptEnabled = true domStorageEnabled = true mediaPlaybackRequiresUserGesture = false } webView.webChromeClient = object : WebChromeClient() { private var customView: View? = null override fun onShowCustomView(view: View?, callback: CustomViewCallback?) { if (customView != null) { onHideCustomView() return } // 横屏处理 activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE // 隐藏系统UI activity.window.decorView.systemUiVisibility = ( View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY ) // 添加全屏视图 customView = view (activity.window.decorView as FrameLayout).addView(view) } override fun onHideCustomView() { // 恢复竖屏 activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT // 显示系统UI activity.window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE // 移除全屏视图 (activity.window.decorView as FrameLayout).removeView(customView) customView = null } } ``` 二、关键点说明 1. 配置变化处理 $$android:configChanges="orientation|screenSize"$$ 防止Activity在横竖屏切换时重建 2. 屏幕方向控制 $$ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE$$ $$ActivityInfo.SCREEN_ORIENTATION_PORTRAIT$$ 3. 系统UI控制 $$SYSTEM_UI_FLAG_FULLSCREEN$$ 隐藏状态栏 $$SYSTEM_UI_FLAG_HIDE_NAVIGATION$$ 隐藏导航栏 $$SYSTEM_UI_FLAG_IMMERSIVE_STICKY$$ 沉浸式体验 三、H5页面要求 1. 视频标签需要添加属性: ```html <video controls playsinline webkit-playsinline x5-video-player-type="h5" x5-video-player-fullscreen="true"> </video> ``` 2. 建议的CSS样式: ```css video { object-fit: fill; width: 100% !important; height: 100% !important; } ``` 四、常见问题处理 1. 黑边问题:检查视频比例与容器是否匹配 2. 方向锁定失败:确保没有其他代码覆盖屏幕方向设置 3. 播放器控制栏错位:调整H5页面的全屏样式 4. Android 8.0+兼容:需添加`<uses-permission android:name="android.permission.INTERNET"/>` 五、扩展功能实现 ```kotlin // 监听设备方向传感器实现自动旋转 private val orientationEventListener by lazy { object : OrientationEventListener(activity) { override fun onOrientationChanged(orientation: Int) { if (orientation in 45..135) { activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE } else if (orientation in 225..315) { activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE } } } } // 在onShowCustomView中启用 orientationEventListener.enable() // 在onHideCustomView中禁用 orientationEventListener.disable() ```
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值