You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Java中WebView视频启动检测:如何判断WebView是否发声

检测WebView中视频开始播放的实现方案

Hey there! 我来分享几个可行的方案,帮你搞定WebView里视频播放的检测需求——包括你提到的音频检测思路,还有更精准的JS/WebView交互方法:

方案一:通过设备音频状态检测(你的思路)

这个方法是监听设备的全局音频播放状态,间接判断WebView里的视频是否开始播放。不过要注意,它会检测整个设备的音频,所以需要结合WebView的当前状态(比如是否处于前台、是否是当前活跃的WebView)来过滤误判。

Android 端实现

可以借助AudioManager来监听音频焦点或主动检查音频状态:

// 获取AudioManager实例
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

// 方式1:定时检查音频是否在播放(比如用Handler每隔1秒查询一次)
Handler handler = new Handler(Looper.getMainLooper());
Runnable checkAudioRunnable = new Runnable() {
    @Override
    public void run() {
        boolean isAudioPlaying = audioManager.isMusicActive();
        if (isAudioPlaying && webView.isShown()) {
            // 结合WebView可见性,判断大概率是WebView里的视频在播放
            // 执行你的逻辑
        }
        handler.postDelayed(this, 1000);
    }
};
handler.post(checkAudioRunnable);

// 方式2:监听音频焦点变化(更及时)
AudioManager.OnAudioFocusChangeListener focusListener = new AudioManager.OnAudioFocusChangeListener() {
    @Override
    public void onAudioFocusChange(int focusChange) {
        if (focusChange == AudioManager.AUDIOFOCUS_GAIN && webView.isShown()) {
            // 音频开始播放,且WebView可见,触发视频播放逻辑
        } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
            // 音频停止播放
        }
    }
};
// 请求音频焦点以监听变化
audioManager.requestAudioFocus(focusListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);

iOS 端实现

使用AVAudioSession来检测或监听音频状态:

import AVFoundation

// 方式1:主动检查是否有其他音频在播放
func checkAudioPlaying() {
    let session = AVAudioSession.sharedInstance()
    do {
        try session.setActive(true)
        let isPlaying = session.isOtherAudioPlaying
        if isPlaying && webView.isHidden == false {
            // WebView可见且有音频播放,判断视频开始
        }
    } catch {
        print("音频状态检查失败:\(error.localizedDescription)")
    }
}

// 方式2:监听音频中断通知(捕捉播放状态变化)
override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(audioInterrupted(_:)),
        name: AVAudioSession.interruptionNotification,
        object: nil
    )
}

@objc func audioInterrupted(_ notification: Notification) {
    guard let info = notification.userInfo,
          let typeValue = info[AVAudioSessionInterruptionTypeKey] as? UInt,
          let type = AVAudioSession.InterruptionType(rawValue: typeValue) else { return }
    
    if type == .ended, let optionValue = info[AVAudioSessionInterruptionOptionKey] as? UInt,
       optionValue == AVAudioSession.InterruptionOptions.shouldResume.rawValue {
        // 音频恢复播放,结合WebView状态判断
        if webView.isHidden == false {
            // 执行视频播放逻辑
        }
    }
}

方案二:JS + WebView 交互(更精准)

这个方法直接监听网页内<video>元素的play事件,通过JS桥通知原生端,能精准定位到WebView里的视频播放,不会被其他音频干扰。

Android 端实现

  1. 先开启WebView的JS支持,并注入监听脚本:
WebView webView = findViewById(R.id.webView);
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);

// 注入JS接口,让JS能通知原生端
webView.addJavascriptInterface(new VideoPlayCallback(), "videoCallback");

// 网页加载完成后注入监听脚本
webView.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        // 监听所有video元素的play事件,包括动态加载的视频
        String jsScript = """
            // 监听现有video元素
            var videos = document.getElementsByTagName('video');
            for(var i=0; i<videos.length; i++) {
                videos[i].addEventListener('play', function() {
                    window.videoCallback.onVideoStarted();
                });
            }
            // 监听动态新增的video元素
            var observer = new MutationObserver(function(mutations) {
                mutations.forEach(function(mutation) {
                    mutation.addedNodes.forEach(function(node) {
                        if(node.tagName === 'VIDEO') {
                            node.addEventListener('play', function() {
                                window.videoCallback.onVideoStarted();
                            });
                        }
                    });
                });
            });
            observer.observe(document.body, {childList: true, subtree: true});
            """;
        webView.evaluateJavascript(jsScript, null);
    }
});

// 定义JS回调接口
public class VideoPlayCallback {
    @JavascriptInterface
    public void onVideoStarted() {
        // 视频开始播放的回调,切换到主线程处理UI逻辑
        runOnUiThread(() -> {
            // 执行你的业务逻辑,比如记录状态、弹出提示等
        });
    }
}

iOS 端实现(用WKWebView)

import WebKit

class WebViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler {
    var webView: WKWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 配置WebView,添加消息处理器
        let config = WKWebViewConfiguration()
        config.userContentController.add(self, name: "videoPlayHandler")
        
        webView = WKWebView(frame: view.bounds, configuration: config)
        webView.navigationDelegate = self
        view.addSubview(webView)
        
        // 加载目标网页
        if let url = URL(string: "你的网页URL") {
            webView.load(URLRequest(url: url))
        }
    }
    
    // 网页加载完成后注入JS脚本
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        let jsScript = """
            // 监听现有和动态新增的video元素
            function setupVideoListeners() {
                var videos = document.getElementsByTagName('video');
                for(let i=0; i<videos.length; i++) {
                    videos[i].addEventListener('play', function() {
                        window.webkit.messageHandlers.videoPlayHandler.postMessage('started');
                    });
                }
            }
            setupVideoListeners();
            // 监听DOM变化,处理动态加载的视频
            new MutationObserver(function(mutations) {
                mutations.forEach(function(mutation) {
                    mutation.addedNodes.forEach(function(node) {
                        if(node.tagName === 'VIDEO') {
                            node.addEventListener('play', function() {
                                window.webkit.messageHandlers.videoPlayHandler.postMessage('started');
                            });
                        }
                    });
                });
            }).observe(document.body, {childList: true, subtree: true});
            """
        webView.evaluateJavaScript(jsScript) { _, error in
            if let error = error {
                print("JS注入失败:\(error)")
            }
        }
    }
    
    // 接收JS发送的视频播放通知
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "videoPlayHandler" {
            // 视频开始播放,执行你的逻辑
            print("WebView内的视频已开始播放!")
        }
    }
}

方案对比

  • 音频检测:优点是无需修改网页代码,适用于第三方网页;缺点是全局检测容易误判(比如其他APP发声),需要额外逻辑过滤。
  • JS交互监听:优点是精准定位WebView内的视频,无干扰;缺点是需要WebView开启JS支持,若网页动态加载视频,需配合MutationObserver监听DOM变化。

如果能对网页进行JS注入(或网页本身允许),优先选择JS交互的方案,准确性更高~

内容的提问来源于stack exchange,提问作者Kevin La Delfa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 18:37:50