本文代码参考自:https://www.jianshu.com/p/d880c0ca0911 作者有详细说明,请认真阅读。
只有在安装并运行过一次之后,这个功能才会生效!没有安装并运行过程序,协议当然不会被注册。
背景
对于一个 URL 来说,其实就是指定了一个协议(protocol),然后让系统用对应的应用去打开它。如 myapp://startapp/here?a=1&b=2,系统会去找到已经注册了 myapp 这个协议的应用,然后把 URL 当做参数传过去。
这样我们就可以在浏览器中通过一个 <a> 标签简单地唤起应用了。
<a href="PocketBook:?a=1&b=2">打开</a>
核心代码:
/**
* 协议处理
*/
function protocalHandler() {
const args = [];
if (!app.isPackaged) {
// 如果是开发阶段,需要把我们的脚本的绝对路径加入参数中
args.push(path.resolve(process.argv[1]))
}
// 加一个 `--` 以确保后面的参数不被 Electron 处理
args.push('--')
// 注册协议
const PROTOCOL = pkg.name
app.setAsDefaultProtocolClient(PROTOCOL, process.execPath, args)
// 如果打开协议时,没有其他实例,则当前实例当做主实例,处理参数
handleArgv(process.argv)
// 其他实例启动时,主实例会通过 second-instance 事件接收其他实例的启动参数 `argv`
app.on('second-instance', (event, argv) => {
// Windows 下通过协议URL启动时,URL会作为参数,所以需要在这个事件里处理
if (process.platform === 'win32') {
handleArgv(argv)
}
})
// macOS 下通过协议URL启动时,主实例会通过 open-url 事件接收这个 URL
app.on('open-url', (event, urlStr) => {
handleUrl(urlStr)
})
// 处理参数
function handleArgv(argv) {
const prefix = `${PROTOCOL}:`;
// 开发阶段,跳过前两个参数(`electron.exe .`)
// 打包后,跳过第一个参数(`myapp.exe`)
const offset = app.isPackaged ? 1 : 2
const url = argv.find((arg, i) => i >= offset && arg.startsWith(prefix))
if (url) handleUrl(url)
}
// 解析Url
function handleUrl(urlStr) {
// myapp:?a=1&b=2
const urlObj = new URL(urlStr);
const {searchParams} = urlObj;
console.log(urlObj.query); // -> a=1&b=2
console.log(searchParams.get('a')); // -> 1
console.log(searchParams.get('b')); // -> 2
// 根据需要做其他事情
}
}