html5 视频不适用于 android webview

Posted

技术标签:

【中文标题】html5 视频不适用于 android webview【英文标题】:html5 video does not work with android webview 【发布时间】:2019-08-06 01:42:15 【问题描述】:

我已经在 webview 中运行 android 应用程序一年了。 但是前几天有一些客户说我的应用程序中没有播放html5视频。 我有五部手机要测试,我所有的手机都没有问题。大多数客户在使用该应用时没有任何问题。

我将 preload 属性值从 auto 更改为 meta 因为我想是由于网络负载。

下图为客户截图。 有一个时间是 27:10,并且没有用于加载的微调器。 (我认为加载已经结束) 但是,客户无法按下播放按钮,并且当按下播放按钮时,视频元素周围会出现一条橙色线。

客户的手机是galaxy note 8 &galaxy J7,安卓版本是8。但是在我的测试中没有问题。并且有 Android 8 客户在使用该服务时没有任何问题。

我该如何解决?谢谢。

html

<video preload="meta"  autoplay="autoplay" controls="" playsinline="">               
        <source type="video/mp4" src="url.../file.mp4">
        HTML5 is not supported.
    </video>

android - MainActivity

public class MainActivity extends AppCompatActivity 

    private WebView webView;
    private BackPressCloseHandler backPressCloseHandler = new BackPressCloseHandler(this);

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

        webView = findViewById(R.id.webView);
        /* webView settings */
        webView.getSettings().setSupportZoom(true);
        webView.getSettings().setBuiltInZoomControls(true);
        webView.getSettings().setjavascriptEnabled(true);
        webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
        webView.setWebChromeClient(new FullscreenableChromeClient(MainActivity.this));
        webView.setWebViewClient(new WebViewClientClass());

        webView.loadUrl("MY URL IS HERE");
     //onCreate

    private class WebViewClientClass extends WebViewClient 

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) 
            view.loadUrl(url);
            return true;
        
    

启用视频全屏的自定义类

import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.WebChromeClient;
import android.widget.FrameLayout;

public class FullscreenableChromeClient extends WebChromeClient 
    private Activity mActivity = null;

    private View mCustomView;
    private WebChromeClient.CustomViewCallback mCustomViewCallback;
    private int mOriginalOrientation;
    private FrameLayout mFullscreenContainer;
    private static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);

    public FullscreenableChromeClient(Activity activity) 
        this.mActivity = activity;
    

    @Override
    public void onShowCustomView(View view, CustomViewCallback callback) 

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) 
            if (mCustomView != null) 
                callback.onCustomViewHidden();
                return;
            

            mOriginalOrientation = mActivity.getRequestedOrientation();
            FrameLayout decor = (FrameLayout) mActivity.getWindow().getDecorView();
            mFullscreenContainer = new FullscreenHolder(mActivity);
            mFullscreenContainer.addView(view, COVER_SCREEN_PARAMS);
            decor.addView(mFullscreenContainer, COVER_SCREEN_PARAMS);
            mCustomView = view;
            setFullscreen(true);
            mCustomViewCallback = callback;
//          mActivity.setRequestedOrientation(requestedOrientation);

        

        super.onShowCustomView(view, callback);
    

    @SuppressWarnings("deprecation")
    @Override
    public void onShowCustomView(View view, int requestedOrientation, WebChromeClient.CustomViewCallback callback) 
        this.onShowCustomView(view, callback);
    

    @Override
    public void onHideCustomView() 
        if (mCustomView == null) 
            return;
        

        setFullscreen(false);
        FrameLayout decor = (FrameLayout) mActivity.getWindow().getDecorView();
        decor.removeView(mFullscreenContainer);
        mFullscreenContainer = null;
        mCustomView = null;
        mCustomViewCallback.onCustomViewHidden();
        mActivity.setRequestedOrientation(mOriginalOrientation);

    

    private void setFullscreen(boolean enabled) 

        Window win = mActivity.getWindow();
        WindowManager.LayoutParams winParams = win.getAttributes();
        final int bits = WindowManager.LayoutParams.FLAG_FULLSCREEN;
        if (enabled) 
            winParams.flags |= bits;
         else 
            winParams.flags &= ~bits;
            if (mCustomView != null) 
                mCustomView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
            
        
        win.setAttributes(winParams);
    

    private static class FullscreenHolder extends FrameLayout 
        public FullscreenHolder(Context ctx) 
            super(ctx);
            setBackgroundColor(ContextCompat.getColor(ctx, android.R.color.black));
        
        @Override
        public boolean onTouchEvent(MotionEvent evt) 
            return true;
        
    

manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="...">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:hardwareAccelerated="true"
        android:theme="@style/AppTheme">
        <activity android:name="....webview.MainActivity"
            android:configChanges="keyboardHidden|orientation|screenSize">

        </activity>
        <activity android:name="....webview.IntroActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

        </activity>
    </application>

</manifest>

【问题讨论】:

这里的情况相同,但我可以在手机上复制。 Android System WebView 的更新已于 3 月 11 日更新(不确定是更新发布的时间还是我的手机更新的时间;只是在 Android System WebView 的 Google Play 商店中关闭“最后更新”),所以我我假设它做到了。 我收到了来自三星 8 和华为 P20 用户的相同问题的报告 我成功地在我的测试手机上重现了相同的症状。我等了将近五分钟,橙色线消失了,我可以播放视频了。是网络问题吗?但是我的服务器很好,并且在使用相同 WiFi 的其他测试手机上,加载立即完成。感谢回答的人的建议,我将使用 JavaScript。 这绝对是Android系统WebView的一个bug。我在使用 Android WebView 版本 73.0.3683.90 的带有 Android Pie 的 Galaxy S8 上遇到了这个问题。我回滚到版本 71.0.3578.99,这个问题就消失了。 WebView 中的视频过去对我有用,但在我的 S9+ 上不再适用(更新 Pie 之后?)。我的手机显示已禁用 Android System WebView (v69),已启用 Chrome。 【参考方案1】:

以下代码对我来说工作正常,请检查一次

在清单文件中添加这一行

   <application android:hardwareAccelerated="true" ...>

MainActivity

public class MainActivity extends AppCompatActivity 

private WebView webview;

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

    webview = findViewById(R.id.webView);
    webview.setWebViewClient(new MyBrowser());
    webview.setWebChromeClient(new WebChromeClient());
    webview.getSettings().setLoadsImagesAutomatically(true);
    webview.getSettings().setJavaScriptEnabled(true);
    webview.getSettings().setAllowFileAccess(true);
    webview.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
    webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
    webview.getSettings().setPluginState(WebSettings.PluginState.ON);
    webview.getSettings().setMediaPlaybackRequiresUserGesture(false);
    webview.loadUrl("https://www.w3schools.com/html/html5_video.asp");


private class MyBrowser extends WebViewClient 
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) 
        view.loadUrl(url);
        return true;
    

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>

<WebView
    android:id="@+id/webView"
    android:layout_
    android:layout_
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"/>

【讨论】:

为我修复它的行是 webView.getSettings().setMediaPlaybackRequiresUserGesture(false); (API 17)但我仍然无法让全屏按钮工作! @ErnieThomason 我遇到了同样的问题,setMediaPlaybackRequiresUserGesture(false) 修复了它!【参考方案2】:

我的视频应用上的 Android System Webview 73 也遇到了同样的问题。默认的 html5 视频播放器似乎存在一些样式问题。我可以在 javascript 中进行自动播放或调用 play() 函数。

我的解决方案是使用其他一些 javascript 视频播放器。我使用videoJS替换了视频播放器界面,现在可以使用了。

【讨论】:

【参考方案3】:

由于 javascript 调用播放/暂停视频工作,我在我们的应用程序中修复了这个问题,方法是在视频前面添加一个 div,并调整其大小以匹配 Android 放置在视频中心附近的播放按钮。这是 React 的 sn-p:

const isAndroid = () => navigator.userAgent.indexOf('Android') >= 0;

let videoPlayer;

...

<div className="video-wrap">
  <video
    ref=node => videoPlayer = node
    controls
    controlsList="nodownload"
    crossOrigin="anonymous"
    poster=episode.posterUrl
  >
    <source src=episode.h264Url type="video/mp4" />
    episode.webmUrl ? (
      <source src=episode.webmUrl type="video/webm" />
    ) : null
    episode.vttUrl ? (
      <track kind="captions" label="English" src=episode.vttUrl srcLang="en" />
    ) : null
  </video>

   isAndroid() ? (
    <div
      className="android-playback-fix"
      onClick=e => 
        e.preventDefault();

        if (videoPlayer.paused) 
          videoPlayer.play();
         else 
          videoPlayer.pause();
        
      
    ></div>
  ) : null
</div>

这是 CSS:

.video-wrap 
  position: relative;


.android-playback-fix 
  border-radius: 100%;
  height: 75px;
  left: 50%;
  position: absolute;
  top: 45%;
  transform: translate(-50%, -50%);
  width: 75px;

【讨论】:

【参考方案4】:

我遇到了同样的问题。

解决这个问题。

在您的 HTML 视频标签上添加 id,并在您的 java 代码中调用 id

例如

<video id = "video" preload="meta"  autoplay="autoplay" controls="" playsinline=""><source type="video/mp4" src="url.../file.mp4"></video>

onPageFinished - 覆盖 WebViewClient 时,输入此代码

webView.loadUrl("javascript:(function()  document.getElementById('video').play(); )()");
webView.loadUrl("javascript:(function()  document.getElementById('video').pause(); )()");

这将注入 javascript 函数以允许自动播放视频

【讨论】:

以上是关于html5 视频不适用于 android webview的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 视频播放器不适用于 Twitter 视频

HTML5 视频不适用于 iPad 上的 jquery bxSlider 插件

HTML5 视频自动播放不适用于 slick.js

HTML5视频获取currentTime不适用于媒体事件javascript addEventListener

为啥 HTML 5 视频标签不适用于将 YouTube 视频用作源?

HTML 5 视频标签不适用于任何浏览器