本文代码参考自: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>

尝试打开

背景-LMLPHP

核心代码:

/**
 * 协议处理
 */
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
        // 根据需要做其他事情
    }

}

04-25 08:54