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

如何通过JavaScriptInterface调用WebChromeClient内部的onHideCustomView方法?

解决方法:在JavaScriptInterface中调用WebChromeClient的onHideCustomView()

首先,不建议通过反射或者栈追踪的方式去调用匿名内部类的方法——匿名内部类的类名(比如MainActivity$34)是编译时动态生成的,稳定性差,而且这种做法也不符合Android的设计规范。我们可以用更优雅、安全的方式实现需求:


方案1:抽离核心逻辑(推荐)

onHideCustomView()里的业务逻辑单独抽成一个公共方法,让WebChromeClient和JavaScriptInterface都调用这个方法,这样就不需要直接访问WebChromeClient的回调了。

步骤示例:

  1. 在Activity中定义公共的视图隐藏方法:
public class MainActivity extends AppCompatActivity {
    // 假设你有自定义视图的引用
    private View mCustomView;

    // 抽离onHideCustomView的核心逻辑
    public void hideCustomView() {
        if (mCustomView != null) {
            mCustomView.setVisibility(View.GONE);
            // 这里添加原来onHideCustomView里的其他逻辑:比如恢复WebView的显示、清理播放器资源等
        }
    }

    // 初始化WebChromeClient时,直接调用这个抽离的方法
    private WebChromeClient mWebChromeClient = new WebChromeClient() {
        @Override
        public void onHideCustomView() {
            hideCustomView();
        }

        // 其他WebChromeClient回调方法...
    };
}
  1. 让JavaScriptInterface持有Activity的弱引用,调用这个公共方法:
public class MyJsInterface {
    // 使用WeakReference避免内存泄漏
    private WeakReference<MainActivity> mActivityRef;

    public MyJsInterface(MainActivity activity) {
        mActivityRef = new WeakReference<>(activity);
    }

    @JavascriptInterface
    public void triggerHideCustomView() {
        MainActivity activity = mActivityRef.get();
        if (activity != null) {
            activity.hideCustomView();
        }
    }
}
  1. 给WebView绑定这个Interface:
WebView webView = findViewById(R.id.web_view);
webView.setWebChromeClient(mWebChromeClient);
webView.addJavascriptInterface(new MyJsInterface(this), "AndroidBridge");

之后在JS中就可以这样调用:

window.AndroidBridge.triggerHideCustomView();

方案2:直接持有WebChromeClient实例(不推荐,但如果需要可以用)

如果你不想抽离逻辑,也可以把WebChromeClient变成Activity的成员变量,让JavaScriptInterface持有它的引用:

public class MainActivity extends AppCompatActivity {
    private WebChromeClient mWebChromeClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化WebChromeClient为成员变量
        mWebChromeClient = new WebChromeClient() {
            @Override
            public void onHideCustomView() {
                // 你的原逻辑
            }
        };

        WebView webView = findViewById(R.id.web_view);
        webView.setWebChromeClient(mWebChromeClient);
        webView.addJavascriptInterface(new MyJsInterface(this), "AndroidBridge");
    }

    public WebChromeClient getWebChromeClient() {
        return mWebChromeClient;
    }
}

然后在Interface中调用:

public class MyJsInterface {
    private WeakReference<MainActivity> mActivityRef;

    public MyJsInterface(MainActivity activity) {
        mActivityRef = new WeakReference<>(activity);
    }

    @JavascriptInterface
    public void triggerHideCustomView() {
        MainActivity activity = mActivityRef.get();
        if (activity != null && activity.getWebChromeClient() != null) {
            activity.getWebChromeClient().onHideCustomView();
        }
    }
}

注意事项

  • 一定要用WeakReference持有Activity/View的引用,避免内存泄漏。
  • 所有供JS调用的方法必须加上@JavascriptInterface注解,否则在高版本Android中无法调用。
  • 优先选择方案1,因为它将业务逻辑与回调解耦,代码更易维护和扩展。

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

火山引擎 最新活动