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

Android Java开发WebView重写onWindowVisibilityChanged不生效问题

代码错误排查与修正方案

你的代码存在3个核心问题,导致重写逻辑完全不生效:

  • 自定义MyWebView未实际生效:一方面你没有把布局XML里的原生WebView控件替换为自定义MyWebView,findViewById拿到的是系统原生WebView实例,重写的onWindowVisibilityChanged逻辑根本不会执行;另一方面你将MyWebView定义为Activity的非静态内部类,这类内部类无法被布局inflater实例化,就算替换布局标签也会直接崩溃。
  • 重写逻辑覆盖不全:仅拦截onWindowVisibilityChanged的GONE状态不够,锁屏/退后台时WebView还会收到INVISIBLE状态回调,同时系统会通过WebView.onPause()直接暂停所有媒体播放,这部分逻辑没有拦截。
  • 缺少系统必需配置:Android 8.0以上版本,应用退后台播放媒体必须配置前台服务与对应权限,否则系统会直接冻结后台媒体线程。

修正步骤

1. 调整MyWebView类定义

首先把MyWebView改为静态内部类,或者抽成独立的public类,补全所有需要拦截的回调:

// 必须加static修饰,作为静态内部类才能被布局实例化
public static class MyWebView extends WebView {

    public MyWebView(Context context) {
        super(context);
    }

    public MyWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        // 仅在窗口可见时执行父类逻辑,拦截所有后台/锁屏状态的回调
        if (visibility == VISIBLE) {
            super.onWindowVisibilityChanged(visibility);
        }
    }

    @Override
    protected void onVisibilityChanged(View changedView, int visibility) {
        // 拦截控件可见性变为非可见的回调
        if (visibility == VISIBLE) {
            super.onVisibilityChanged(changedView, visibility);
        }
    }

    @Override
    public void onPause() {
        // 注释掉super调用,禁止系统触发WebView暂停逻辑,该方法会直接停止媒体播放
        // super.onPause();
    }
}

2. 替换布局中的WebView控件

打开R.layout.activity_nitter布局文件,将原有原生WebView标签替换为自定义MyWebView的全类名,假设你的应用包名为com.xxx.webapp,对应写法如下:

<!-- 替换原有<WebView />节点 -->
<com.xxx.webapp.WebApp.MyWebView
    android:id="@+id/webview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

注意:如果MyWebView被抽成独立类,全类名直接写com.xxx.webapp.MyWebView即可

3. 补全WebSettings与权限配置

首先在AndroidManifest.xml中添加后台播放必需的权限:

<!-- 基础前台服务权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- Android 14及以上媒体播放前台服务权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<!-- Android 13及以上通知权限,用于展示前台服务常驻通知 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

在原有onCreate的WebSettings配置中补充以下参数:

// 取消媒体播放必须用户手动触发的限制
webSettings.setMediaPlaybackRequiresUserGesture(false);
// 开启DOM存储,避免部分网页媒体后台播放时存储异常
webSettings.setDomStorageEnabled(true);

4. 配置前台服务

在Activity触发onStop(退后台/锁屏)时启动媒体播放类型的前台服务,挂一个常驻播放通知,避免系统因应用无前台界面杀死媒体进程;在Activity回到前台onStart时停止前台服务即可。


验证注意事项

  • 不要在MIUI、ColorOS、OriginOS等国产定制ROM上做首次验证,这类系统默认禁止第三方应用后台播放声音,需要手动在系统应用设置中开启「后台运行」「后台播放音频」权限才能正常生效。
  • 测试时不要主动在Activity的onPause/onStop生命周期中调用webView.onPause(),否则会直接触发媒体暂停。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 07:51:19