如何通过JavaScriptInterface调用WebChromeClient内部的onHideCustomView方法?
解决方法:在JavaScriptInterface中调用WebChromeClient的onHideCustomView()
首先,不建议通过反射或者栈追踪的方式去调用匿名内部类的方法——匿名内部类的类名(比如MainActivity$34)是编译时动态生成的,稳定性差,而且这种做法也不符合Android的设计规范。我们可以用更优雅、安全的方式实现需求:
方案1:抽离核心逻辑(推荐)
把onHideCustomView()里的业务逻辑单独抽成一个公共方法,让WebChromeClient和JavaScriptInterface都调用这个方法,这样就不需要直接访问WebChromeClient的回调了。
步骤示例:
- 在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回调方法... }; }
- 让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(); } } }
- 给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




