You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

WebView离线HTML嵌入视频无网络错误的自定义处理问询

解决WebView无网络时嵌入视频错误提示替换问题

嘿,这个问题我之前帮人处理过,其实有两个靠谱的方案,看你更适合哪种:

方案一:修改本地HTML,给视频添加自定义 fallback 内容

这个方案最直接——既然你的HTML是本地离线的,直接修改它的结构就能实现需求,不需要动Android端的代码。

针对原生

如果你的视频是用原生<video>标签嵌入的,直接在标签里添加加载失败时显示的自定义内容:

<video controls width="100%">
  <source src="your-video-url.mp4" type="video/mp4">
  <!-- 这里是自定义的无网络/加载错误提示 -->
  <div style="padding:20px; text-align:center; background:#f5f5f5; border:1px solid #ddd;">
    <p>📺 当前无网络,视频无法加载</p>
    <p>请连接网络后重试</p>
  </div>
</video>

针对iframe嵌入的第三方视频

如果是用<iframe>嵌入的第三方平台视频(比如YouTube、B站等),可以给它套一个容器,再用JS检测网络状态或加载错误来显示自定义提示:

<!-- 给每个视频套一个容器 -->
<div class="video-container">
  <iframe src="your-video-embed-url" frameborder="0" allowfullscreen></iframe>
  <!-- 初始隐藏的自定义提示 -->
  <div class="video-fallback" style="display:none; padding:20px; text-align:center; background:#f5f5f5; border:1px solid #ddd;">
    <p>📺 当前无网络,视频无法加载</p>
    <p>请连接网络后重试</p>
  </div>
</div>

<script>
// 页面加载时先检查网络状态
function checkNetwork() {
  if (!navigator.onLine) {
    // 无网络时隐藏iframe,显示提示
    document.querySelectorAll('.video-container iframe').forEach(iframe => {
      iframe.style.display = 'none';
      iframe.nextElementSibling.style.display = 'block';
    });
  }
}

// 监听网络状态变化
window.addEventListener('online', checkNetwork);
window.addEventListener('offline', checkNetwork);

// 监听iframe加载错误(即使有网络也可能加载失败)
document.querySelectorAll('.video-container iframe').forEach(iframe => {
  iframe.addEventListener('error', () => {
    iframe.style.display = 'none';
    iframe.nextElementSibling.style.display = 'block';
  });
});

// 初始化执行一次
window.onload = checkNetwork;
</script>

方案二:通过Android WebViewClient拦截错误,注入JS替换内容

如果不方便修改本地HTML,或者想在Android端统一处理所有视频错误,可以通过自定义WebViewClient来实现。

步骤1:修改你的WebViewClientClass

重写错误回调方法,检测网络状态和视频加载错误,然后注入JS替换错误区域:

public class WebViewClientClass extends WebViewClient {
    @Override
    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
        super.onReceivedError(view, errorCode, description, failingUrl);
        // 判断是否是视频资源或无网络状态
        if (isVideoResource(failingUrl) || !isNetworkAvailable(view.getContext())) {
            // 注入JS替换所有视频元素为自定义提示
            String customFallbackJs = "javascript:(function(){" +
                "var videoElements = document.querySelectorAll('video, iframe');" +
                "for(let i = 0; i < videoElements.length; i++){" +
                "    const parent = videoElements[i].parentNode;" +
                "    const fallbackDiv = document.createElement('div');" +
                "    fallbackDiv.style.padding = '20px';" +
                "    fallbackDiv.style.textAlign = 'center';" +
                "    fallbackDiv.style.background = '#f5f5f5';" +
                "    fallbackDiv.style.border = '1px solid #ddd';" +
                "    fallbackDiv.innerHTML = '<p>📺 当前无网络,视频无法加载</p><p>请连接网络后重试</p>';" +
                "    parent.replaceChild(fallbackDiv, videoElements[i]);" +
                "}" +
            "})()";
            view.loadUrl(customFallbackJs);
        }
    }

    // 判断URL是否是视频相关资源
    private boolean isVideoResource(String url) {
        if (url == null) return false;
        String lowerUrl = url.toLowerCase();
        return lowerUrl.contains(".mp4") || lowerUrl.contains(".avi") || lowerUrl.contains(".mov") 
                || lowerUrl.contains("youtube") || lowerUrl.contains("vimeo");
    }

    // 检测设备网络是否可用
    private boolean isNetworkAvailable(Context context) {
        ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = connManager.getActiveNetworkInfo();
        return activeNetwork != null && activeNetwork.isConnected();
    }
}

步骤2:添加网络权限

别忘了在AndroidManifest.xml中添加获取网络状态的权限:

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

两种方案的选择

  • 如果你的离线HTML是可以修改的,方案一更简单,兼容性也更好;
  • 如果无法修改HTML,或者需要统一管理所有视频的错误提示,方案二更合适。

内容的提问来源于stack exchange,提问作者Ali

火山引擎 最新活动