Android 4.2+(API 17+)中addJavascriptInterface必须加@JavascriptInterface注解,否则JS调用静默失效;该注解是系统级安全机制,仅标注的public方法才被WebView暴露给JS,且参数和返回值受限于基本类型、Serializable类等。

Android WebView 里 addJavascriptInterface 是最直接的 JS ↔ Java 双向调用方式,但它在 Android 4.2+ 后必须加 @JavascriptInterface 注解才生效;不加会导致方法静默失效——你点按钮没反应、没报错、也没日志,纯靠排查才能发现。
为什么 addJavascriptInterface 在 Android 4.2+ 必须加注解
这是 Android 系统级安全补丁:未标注 @JavascriptInterface 的 Java 方法,WebView 会直接忽略其暴露行为。即使你写了 mWebView.addJavascriptInterface(new JsBridge(), "bridge"),JS 里调用 window.bridge.doSomething() 也会变成“方法不存在”。
- 只影响 Android 4.2(API 17)及以上版本;4.1 及以下仍可不加,但已无实际兼容价值
- 注解必须加在 public 方法上,且方法不能是 static 或 private
- 参数类型仅支持基本类型(
String、int、boolean)、JSONObject、JSONArray,或自定义类(需实现Serializable) - 返回值同理,不支持泛型、Map、List 等运行时擦除类型——否则 JS 调用时抛
JSONException
shouldOverrideUrlLoading 拦截自定义协议的坑
用 myapp://action?param=value 这种方式传参,看似简单,但实际容易卡在三个地方:
- Android 7.0+(API 24)起,
shouldOverrideUrlLoading(WebView, String)已被废弃,必须改用shouldOverrideUrlLoading(WebView, WebResourceRequest),否则拦截失效(尤其在 Chrome 内核 WebView 中) - URL 中中文或特殊符号(如
=、&)未 encode,Native 端用Uri.parse(url).getQueryParameter("key")拿不到值 - 多次快速触发相同 scheme(比如连点按钮),部分低版本系统会丢弃后续请求,建议 JS 层加防抖,或 Native 层对 scheme 做幂等处理
JS 调用 Native 后如何可靠回传结果
单纯靠 URL scheme 或 addJavascriptInterface 无法同步返回复杂数据——JS 调用后立刻执行下一步,而 Native 还在处理网络或 IO。可靠做法是把回调抽象成“任务 ID + 回调函数名”:
立即学习“前端免费学习笔记(深入)”;
- JS 调用时传一个唯一
callbackId和回调函数名(如"onLoginSuccess") - Native 处理完后,用
mWebView.evaluateJavascript("window." + callbackName + "(" + resultJson + ")", null)主动触发 JS 回调 - 避免用
loadUrl("javascript:..."):它在 Android 4.4+ 上可能被异步延迟执行,且不支持返回值 - 注意
evaluateJavascript需要 API 19+;低于此版本得降级走loadUrl+onPageFinished轮询,但体验差
WebView 初始化时最容易漏的安全配置
交互功能能跑通 ≠ 安全可用。下面三项不设,上线后可能被 XSS 或远程代码注入利用:
-
setJavaScriptEnabled(true)是前提,但必须配合setAllowFileAccess(false)和setAllowContentAccess(false),否则 JS 可读取本地文件 - 若 H5 页面来自 https,务必调用
setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER),禁用 http 资源混载 - 禁止通过
addJavascriptInterface暴露敏感类(如Runtime、System、Context),哪怕只是临时调试——APK 被反编译后极易被利用
真正难的不是让 JS 和 Native “通上”,而是通得稳、通得快、通得安全。比如一次图片上传,JS 触发 Native 调相机 → Native 返回 base64 → JS 渲染预览 → 用户点击提交 → Native 发起 multipart 请求,中间任意一环没做超时、错误透出、线程切换保护,就容易卡死或白屏。这些细节不会报红,但会在弱网、低端机、后台切前台时集中爆发。



















