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 端实现
- 先开启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
相关产品推荐
相关产品推荐

