目录
App中内嵌H5页面实现通信
Admin6/12/2025758 阅读
在App中内嵌H5页面并实现通信是常见的混合开发场景,主要通过JavaScript与原生代码交互实现。以下是主流平台的核心实现方案:
一、通信原理
H5 → App
H5调用原生能力(如相机、存储等)
App → H5
原生触发H5页面更新(如传递用户信息)
双向通信
通过约定协议实现数据交换
二、Android实现方案
方法1:JavaScriptInterface(官方推荐)
language
// 1. 定义接口类
public class JsBridge {
@JavascriptInterface
public void showToast(String msg) {
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
}
}
// 2. 注册到WebView
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new JsBridge(), \"AndroidBridge\");
// 3. H5调用
window.AndroidBridge.showToast(\"Hello from H5!\");
方法2:URL Scheme拦截
language
// H5触发自定义协议
location.href = \"myapp://action?param1=value1\";
language
// Android拦截请求
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith(\"myapp://\")) {
// 解析并执行原生操作
return true; // 拦截请求
}
return false;
}
});
三、iOS实现方案
方法1:WKScriptMessageHandler(推荐)
language
// 1. 注册消息处理器
let contentController = WKUserContentController()
contentController.add(self, name: \"iosBridge\")
// 2. H5发送消息
window.webkit.messageHandlers.iosBridge.postMessage({data: \"Hello\"})
// 3. 原生处理消息
func userContentController(_ controller: WKUserContentController,
didReceive message: WKScriptMessage) {
if message.name == \"iosBridge\",
let data = message.body as? [String: Any] {
print(\"Received:\", data[\"data\"] ?? \"\")
}
}
方法2:JavaScriptCore(UIWebView旧方案)
language
// 1. 获取JSContext
JSContext *context = [webView valueForKeyPath:@\"documentView.webView.mainFrame.javaScriptContext\"];
// 2. 注入对象
context[@\"nativeBridge\"] = ^(NSString *msg) {
NSLog(@\"H5消息: %@\", msg);
};
// H5调用
nativeBridge(\"Hello iOS!\");
四、通用增强方案
1. 封装JS Bridge库
language
// 统一调用入口
function callNative(method, params, callback) {
// Android
if (window.AndroidBridge) {
window.AndroidBridge[method](JSON.stringify(params));
}
// iOS
else if (window.webkit?.messageHandlers?.iosBridge) {
window.webkit.messageHandlers.iosBridge.postMessage({
func: method,
data: params
});
}
}
2. 安全加固
language
通信双方验证来源(防止恶意页面调用)
iOS启用requiresUserActionForMediaPlayback
Android禁用setAllowUniversalAccessFromFileURLs
五、完整通信流程示例

六、调试技巧
Android
使用Chrome chrome://inspect 调试WebView
iOS
Safari开发者工具调试WebView
抓包工具
使用Charles分析通信数据
注意事项
异步处理:所有原生操作需异步返回结果
版本兼容:Android 4.2+ 必须使用@JavascriptInterface
参数类型:复杂数据使用JSON序列化
内存泄漏:iOS的WKScriptMessageHandler需及时移除
建议使用成熟开源库简化开发:
Android:JockeyJS
iOS:WebViewJavascriptBridge
通过标准化通信协议,可实现H5与App的高效、安全交互,同时保持H5的动态更新能力。
H5 端通用实现(JockeyJS + WebViewJavascriptBridge)
1. 初始化 Bridge
language
// 兼容 Android 和 iOS 的初始化函数
function initBridge(callback) {
if (window.WebViewJavascriptBridge) {
return callback(window.WebViewJavascriptBridge);
}
if (window.Jockey) { // Android 的 JockeyJS
callback({
callHandler: Jockey.trigger,
registerHandler: Jockey.on
});
} else { // iOS 的 WebViewJavascriptBridge
document.addEventListener('WebViewJavascriptBridgeReady', () => {
callback(window.WebViewJavascriptBridge);
}, false);
}
}
initBridge(function(bridge) {
// 注册 JS 处理器供原生调用
bridge.registerHandler(\"changeTheme\", function(data, responseCallback) {
document.body.className = data.theme;
responseCallback(\"Theme applied!\"); // 通知原生完成
});
// 调用原生方法(如获取用户信息)
bridge.callHandler(\"getUserInfo\", { userId: \"1001\" }, function(response) {
console.log(\"用户数据:\", response.name, response.email);
});
});
封装方法参考
language
// ios终端
const u = navigator.userAgent;
export const isWeiXin = !!/MicroMessenger/i.test(u);
export const isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; // android终端
export const isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
// import VConsole from 'vconsole'
// new VConsole()
const printException = (func: () => void) => {
try {
func();
return true;
} catch (e) {
console.error('非客户端环境,无法调用');
return false;
}
};
/**
* @function 客户端回调传参
* @androidFuncName 安卓方法
* @iosFuncName 苹果方法
* @iosCallbackName 苹果回调
* */
const waitAppCallback = (androidFuncName: string, iosFuncName: string, iosCallbackName: string) => {
return new Promise((resolve, reject) => {
try {
if (isAndroid) {
(window as any).Android[androidFuncName] &&
resolve((window as any).Android[androidFuncName]());
} else if (isiOS) {
(window as any)[iosCallbackName] = (appArgs: string) => {
resolve(appArgs);
};
(window as any).webkit &&
(window as any).webkit.messageHandlers[iosFuncName].postMessage('');
} else {
reject();
}
} catch (e) {
console.error('非客户端环境,无法调用', `这是${androidFuncName}方法`);
reject(e);
}
});
};
2. 主动发送消息给原生
language
// H5 触发扫码功能
document.getElementById(\"scan-btn\").addEventListener(\"click\", () => {
bridge.callHandler(\"scanQRCode\", \"qrcode\", (result) => {
alert(`扫码结果: ${result.code}`);
});
});
移动端调试神器eruda使用详解(推荐)
language
pnpm add eruda
移动端调试神器vConsole使用详解
language
pnpm add vconsole
H5在ios浏览器全屏显示
viewport-fit=cover 可以全屏显示
language
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover\">
禁用ios 禁止网页回弹效果
language
html {
overscroll-behavior: none;
}
评论
共 0 条 后参与评论