前端通信 API
概述
用途:网页里通过全局对象 jade 和外面 C/C++ 写的宿主互相发消息。订阅事件用 jade.on;让宿主算点东西、拿文件路径等用 jade.invoke。页面须运行在 JadeView 提供的 WebView 环境(含 set_protocol_service_path 给出的内置地址 或等价加载方式),否则没有 jade 对象。
通信方式
调用宿主方法(jade.invoke)
用途:像「远程调用宿主函数」:你把命令名和数据丢过去,宿主在 register_ipc_handler 里处理,再把结果异步还给你。适合读配置、选文件、跑耗时任务等。
2.0 推荐写法:
await jade.invoke('命令名', 传给宿主的数据, { timeout: 5000 });
- 第二段可以是字符串、对象等,宿主收到的一般是 JSON 文本。
- 第三段可选:
timeout控制最多等多久;不写则用默认超时。 - 内部是两段异步:大结果或慢任务时更稳;旧版
invokeAsync已删除,请只用invoke。
订阅宿主消息(jade.on)
用途:监听宿主 send_ipc_message 推过来的消息,或库内约定的通知(事件名与负载格式见 事件类型)。
const off = jade.on('事件名', function (payload) {
// payload 一般为对象(库已解析 JSON)
});
// 不再需要时取消订阅:
// off();
- 第一个参数:字符串,与 C 侧
send_ipc_message的message_type或文档中的事件名一致。 - 第二个参数:回调,参数是解析后的数据(常见为对象)。
- 返回值:取消订阅函数,调用后不再接收该监听。
使用建议
消息体积与性能
- 单次传递的数据不要过大;WebView2 上建议控制在约 252MB 以内,再大容易崩或卡死。
- 只订阅需要的事件,用完记得
off(),避免泄漏与重复处理。
示例
const result = await jade.invoke('message', { data: 'test' }, { timeout: 5000 });
宿主侧为每个 命令名 调 register_ipc_handler,见 IPC 通信 API。
宿主回调示例
以下为常见命令的 register_ipc_handler 回调写法。
message 命令
const char* message_callback(uint32_t window_id, const char* event_data) {
printf("收到 message 命令,窗口ID: %u, 数据: %s\n", window_id, event_data);
char result[256];
snprintf(result, sizeof(result),
"{\"status\":\"success\",\"message\":\"已收到\",\"window_id\":%u}",
window_id);
return jade_text_create(result);
}
setBackdrop 命令
const char* set_backdrop_callback(uint32_t window_id, const char* event_data) {
printf("收到 setBackdrop,窗口ID: %u, 类型: %s\n", window_id, event_data);
return jade_text_create("{\"success\":true,\"result\":\"背景材料设置完成\"}");
}
setTheme 命令(异步处理)
const char* set_theme_callback(uint32_t window_id, const char* event_data) {
printf("收到 setTheme,窗口ID: %u, 主题: %s\n", window_id, event_data);
// 1. 立即返回确认
char result[128];
snprintf(result, sizeof(result),
"{\"status\":\"success\",\"message\":\"已接收,异步处理中\"}");
// 2. 异步处理 ... 完成后 send_ipc_message 通知前端
send_ipc_message(window_id, "setTheme",
"{\"theme\":\"Dark\",\"status\":\"completed\"}");
return jade_text_create(result);
}
完整示例
// 初始化时设置背景材料
(async function () {
try {
await jade.invoke('setBackdrop', 'mica');
} catch (error) {
console.error('设置失败:', error);
}
})();
// 监听窗口状态变化
jade.on('window-state-changed', function (data) {
console.log('窗口状态变化:', data);
});
// 按钮点击事件处理
document.getElementById('sendBtn').addEventListener('click', async function () {
const message = document.getElementById('msgInput').value;
try {
const result = await jade.invoke('message', message);
console.log('发送成功:', result);
} catch (error) {
console.error('发送失败:', error);
}
});
常见问题
1. 调用失败,提示 "JadeView API not available"
- 原因:页面不是通过 JadeView 支持的协议加载的。前端 API 仅在通过
set_protocol_service_path加载的页面或等价的 WebView 环境中可用。 - 解决:确保使用
set_protocol_service_path提供的协议 URL 创建窗口,或使用从内存加载的 JAPK 页面。
2. 调用失败,提示超时
- 检查宿主是否正确注册了对应的 IPC handler
- 检查命令名称是否拼写正确(区分大小写)
- 确认
timeout参数对耗时操作设置了足够的时间
3. 事件不触发
- 检查宿主侧
send_ipc_message的message_type是否与jade.on第一个参数一致 - 确认订阅在事件发送之前执行
4. 性能问题
- 减少不必要的 API 调用
- 及时调用取消订阅函数释放监听
- 单次传输数据控制在约 252MB 以内