作者:钟离,酷家乐 PC 客户端负责人
原文地址:https://webfe.kujiale.com/browser-to-client/
酷家乐客户端:下载地址 https://www.kujiale.com/activity/136
文章背景:在酷家乐客户端在 V12 改版成功后,我们积累了许多的宝贵的经验和最佳实践。前端社区里关于 Electron 知识相对较少,因此希望将这些内容以系列文章的形式分享出来。
系列文章:
- 【Electron】酷家乐客户端开发实践分享 — 入坑篇
- 【Electron】酷家乐客户端开发实践分享 — 软件自动更新
- 【Electron】酷家乐客户端开发实践分享 — 浏览器启动客户端
- 【Electron】酷家乐客户端开发实践分享 — 进程通信
- 不定期更新 …
背景
许多本地应用(例如 vscode、QQ),都支持通过浏览器来启动 PC 上的本地软件
这个功能够使网页端和客户端联动起来,用户体验还是很好的,实现起来也并不复杂。酷家乐客户端已经支持了这个功能,如下图:
实现原理
浏览器在解析 url 的时候,会尝试从系统本地寻找 url 协议所关联的应用,如果有关联的应用,则尝试打开这个应用
例如 VsCode 从 web 端安装插件的时候,实际上是访问了一个 vscode
协议的 url,从而达到启动用户本地 VsCode 的目的
具体实现
现在,我们只需要 将自定义的协议注册到用户电脑上,就可以实现功能了。用户浏览器里访问带有自定义协议的 url,即可启动我们的客户端。
Windows
在 windows 下,注册一个协议比较简单,写注册表 就可以了。这部分微软爸爸有很详细的文档,参考 Registering an Application to a URI Scheme)
建议在安装程序中写入注册表项,并且指定在卸载程序中,删除这些注册表项。以下是 inno setup 打包程序中,操作注册表的示例代码
[Registry]
Root: HKCR; SubKey: Kujiale; ValueData: "KujialeProtocol"; ValueType: string; Flags: createvalueifdoesntexist uninsdeletekey;
Root: HKCR; SubKey: Kujiale; ValueName: "URL Protocol"; ValueData: "{app}\{#appExe}"; ValueType: string; Flags: createvalueifdoesntexist uninsdeletekey;
Root: HKCR; SubKey: Kujiale\DefaultIcon; ValueData: "{app}\{#appExe}"; ValueType: string; Flags: createvalueifdoesntexist uninsdeletekey;
Root: HKCR; SubKey: Kujiale\shell\open\command; ValueData: "{app}\{#appExe}""%1"""; Flags: createvalueifdoesntexist uninsdeletekey; ValueType: string;
当然,也可以在软件启动的时候操作注册表,这个时候其实是用 NodeJs 来与注册表交互,推荐一个 npm 包 node-regedit
自定义协议注册成功后,注册表里是这样子的
MacOS
在 MacOS 系统下面,我们就没有注册表可以写了,所以要换一个实现方法。在这之前,先介绍一些东西
info.plist
iOS 和 MacOS 的应用包中,都有一个 info.plist 文件,这个文件主要用来记录应用的一些 meta 信息,参考 Information Property List。文件用键值对的形式来记录信息(xml),结构如下:
CFBundleURLTypes
官方解释:CFBundleURLTypes:A list of URL schemes (http, ftp, and so on) supported by the app.
其实呢,这个就是 info.plist 里面的一个 key,对应的 value 是一个数组。可以通过这个字段来为应用注册一个 or 多个 URL Schema。参考 CFBundleURLTypes
修改 info.plist 文件
在了解了 plist 文件之后,我们现在只需为 App 包中 info.plist,设置 CFBundleURLTypes 的值即可。那么如何修改呢,手写吗?nonono,这种事情当然要交给工具来做,不然太 low 了。
在 Electron Packager 中,有一个配置 protocols
可以注册自定义协议,只对 MacOS 端生效,原理就是上面提到的修改 infi.plist 文件。
// for mac
options.protocols = [{
name: '钟离',
schemes: ['zhongli', 'test'], // 可以注册多个协议
}];
接收参数
协议注册完毕之后,我们已经可以在浏览器中,通过访问自定义协议 url 来启动客户端了。
对于 url 中的不同参数,客户端的行为也是不一样的,例如 vscode:extension/ms-python.python
这个 url,启动了 VsCode 的同时也告诉了 VsCode:我要安装插件,插件名是 ms-phthon.python。
Vscode 通过解析 url 中的参数来实现自定义行为,那么作为客户端如何拿到这个 url 呢?
Windows
对于 windows,参数会通过启动参数的形式传递给应用程序。因此,我们可以很方便的拿到这个参数
// 通过自定义 url 启动客户端时
console.log(process.argv);
// 打印出
[
'C://your-app.exe', // 启动路径
'kujiale://111', // 启动的自定义 url
]
MacOS
在 Mac 下不会通过启动参数传递给应用,通过自定义协议打开应用,app 会收到 open-url 事件
// mac 下通过 kujiale 协议启动应用
app.on('open-url', (e, url) => { // eslint-disable-line
parse(url);解析 url
});
最后
本文分了两部分来讲述如何从浏览器启动 PC 端的应用
- 注册自定义协议,对于所有应用程序都适用
- 接收参数,对使用 Electron 构建的应用适用
欢迎大家在评论区讨论,技术交流 & 内推 -> zhongli@qunhemail.com