HTML5视频在Android WebView中无法工作

10

我在webview中运行android应用已经有一年了。 但是最近有些客户反映我的应用中的html5视频无法播放。 我有五部手机用于测试,所有我的手机都没有问题。大多数客户使用应用程序没有任何问题。

我将preload属性值从auto更改为meta,因为我想要减少网络负载。

下面的图片是客户的截图。 有一个时间显示为27:10,但没有显示加载图标(我认为加载已经完成)。 然而,客户无法按下播放按钮,当播放按钮被按下时,视频元素周围会出现一个橙色线条。

进入图像描述

客户的手机型号是galaxy note 8和galaxy J7,安卓版本为8。但在我的测试中没有发现问题。并且还有使用安卓8的客户没有任何问题。

我该怎么解决呢?谢谢。

html

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

Android - 主活动

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系统WebView于3月11日进行了更新(不确定是否是更新发布的时间还是我的手机更新的时间;只是根据Google Play商店中Android系统WebView的“最后更新”来判断),因此我认为可能是这个原因导致的。 - Daniel
我收到了来自三星8和华为P20用户的相同问题报告。 - user11252857
我成功地在我的测试手机上复现了相同的症状。我等了将近五分钟,橙色线条消失了,我能够播放视频。这是网络问题吗?但我的服务器没问题,在使用相同WiFi的其他测试手机上,加载是立即完成的。感谢回答的人们的建议,我将使用JavaScript。 - S.E Saint
这绝对是 Android 系统 WebView 中的一个 bug。我在使用 Android WebView 版本 73.0.3683.90 的 Android Pie 上的 Galaxy S8 上遇到了这个问题。我回滚到版本 71.0.3578.99,这个问题就消失了。 - Pete
WebView 中的视频以前可以正常播放,但在我的 S9+ 上(Pie 更新后?)不再起作用了。我的手机显示 Android 系统 WebView 已禁用(v69),Chrome 已启用。 - Ernie Thomason
4个回答

6
以下代码在我的电脑上运行良好,请检查一次。 将此行添加到清单文件中。
   <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_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"/>


2
解决问题的那一行代码是:webView.getSettings().setMediaPlaybackRequiresUserGesture(false);(API 17)。但是我仍然无法让全屏按钮正常工作! - Ernie Thomason
@ErnieThomason 我之前也遇到这个问题,设置setMediaPlaybackRequiresUserGesture(false)解决了! - Seb83

1
我在我的视频应用程序中遇到了与Android System Webview 73相同的问题。似乎默认的html5视频播放器存在一些样式问题。我可以在javascript中自动播放或调用play()函数。
我的解决方案是使用其他javascript视频播放器。我使用videoJS替换了视频播放器界面,现在它可以正常工作了。

0

我遇到了同样的问题。

要解决这个问题,

在你的HTML视频标签上放置一个id,并在你的Java代码中调用该id

例如:

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

WebViewClient 中,重写 onPageFinished 方法,并添加以下代码:
webView.loadUrl("javascript:(function() { document.getElementById('video').play(); })()");
webView.loadUrl("javascript:(function() { document.getElementById('video').pause(); })()");

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


0

由于JavaScript调用播放/暂停视频的功能可行,我通过在视频前面包含一个div并将其大小调整为与Android放置在视频中心附近的播放按钮相匹配来解决了这个问题。以下是React的片段:

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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接