如何实现从网页一键启动你的 Electron 桌面应用(zxjapp://)

发布于:2025-05-20 ⋅ 阅读:(16) ⋅ 点赞:(0)

在现代桌面应用开发中,Electron 凭借其跨平台能力和前端友好的特性,受到了越来越多开发者的青睐。但你是否想过,如何让用户从网页上一键启动你本地的 Electron 应用?比如像某些云盘客户端那样,点击网页上的按钮就能直接唤起桌面程序?

本文将手把手教你如何通过自定义协议(URL Scheme)的方式,实现从网页一键唤醒你的 Electron 应用 —— zxjapp://


在这里插入图片描述

我们希望达到的效果是:

  • 在网页中放置一个按钮;
  • 用户点击后尝试打开本地安装的 Electron 应用;
  • 如果未安装,则提示用户下载;
  • 支持 Windows 和 macOS 平台;
  • 可扩展:未来可支持传参、深度链接等功能。

二、实现原理概述

要实现网页调起本地应用,核心在于 注册一个自定义的 URL 协议,例如 zxjapp://,然后让系统知道这个协议应该由我们的 Electron 应用来处理。

Electron 提供了 app.setAsDefaultProtocolClient() 方法,可以让我们轻松地为指定协议设置默认处理程序。


三、具体实现步骤

1. 修改主进程代码(main.js)

首先,在你的 Electron 主进程文件中添加如下代码,用于注册协议和监听请求。

const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');

let mainWindow;

function createWindow() {
    mainWindow = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            preload: path.join(__dirname, 'preload.js'),
            contextIsolation: true,
            enableRemoteModule: false,
            nodeIntegration: false
        }
    });

    mainWindow.loadFile('index.html');

    // 打开开发者工具(可选)
    // mainWindow.webContents.openDevTools();

    mainWindow.on('closed', () => {
        mainWindow = null;
    });
}

// 注册 zxjapp:// 协议
if (require('electron-squirrel-startup')) return;

const gotTheLock = app.requestSingleInstanceLock();

if (!gotTheLock) {
    app.quit();
} else {
    app.on('second-instance', (event, commandLine, workingDirectory) => {
        if (mainWindow) {
            if (mainWindow.isMinimized()) mainWindow.restore();
            mainWindow.focus();
        }
    });

    app.whenReady().then(() => {
        createWindow();

        // 设置默认协议处理器
        const protocol = require('electron').protocol;
        protocol.registerSchemesAsPrivileged([
            { scheme: 'zxjapp', privileges: { bypassCSP: true } }
        ]);

        app.setAsDefaultProtocolClient('zxjapp');

        app.on('activate', () => {
            if (BrowserWindow.getAllWindows().length === 0) createWindow();
        });
    });
}

app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit();
});

⚠️ 注意:如果你使用的是 electron-builder 打包,确保 package.json 中配置了 appId,否则协议可能无法正确注册。

{
  "build": {
    "appId": "com.zxj.app"
  }
}

2. 处理协议调用(可选增强体验)

为了能在应用被调用时做一些事情,比如显示某个页面或传递参数,我们可以监听 open-url 事件:

app.on('will-finish-launching', () => {
    app.on('open-url', (event, url) => {
        event.preventDefault();
        console.log('收到协议调用:', url);

        if (mainWindow) {
            mainWindow.webContents.send('protocol-url', url);
        }
    });
});

并在渲染进程中监听这个事件:

const { ipcRenderer } = require('electron');

ipcRenderer.on('protocol-url', (event, url) => {
    alert('收到协议地址: ' + url);
    // 可以解析并跳转到特定页面
});

3. 网页端添加触发按钮

现在我们在网页中添加一个按钮,点击后尝试打开 zxjapp:// 协议。

// 打开绑卡APP
const openDesktopApp = () => {
	// 创建一个隐藏的iframe来尝试打开应用
	const iframe = document.createElement('iframe');
	iframe.style.display = 'none';
	document.body.appendChild(iframe);

	// 设置超时时间
	const timeout = 2000;
	const startTime = Date.now();

	// 尝试打开应用
	iframe.src = 'runbayun://';

	// 监听页面可见性变化
	document.addEventListener('visibilitychange', function handler() {
		if (document.hidden) {
			// 如果页面隐藏,说明应用已安装并成功打开
			document.removeEventListener('visibilitychange', handler);
			document.body.removeChild(iframe);
			return;
		}

		// 如果超时且页面仍然可见,说明应用未安装
		if (Date.now() - startTime > timeout) {
			document.removeEventListener('visibilitychange', handler);
			document.body.removeChild(iframe);
			ElMessage.warning('请先安装润吧云桌面应用');
		}
	});
};

四、注意事项与常见问题

1. Windows 注册表自动写入

Electron 的 setAsDefaultProtocolClient() 方法会在 Windows 上自动修改注册表项,使 zxjapp:// 关联到你的应用。无需手动编辑注册表。

2. macOS 下需要沙盒权限

如果你的应用启用了沙盒(macOS App Sandbox),你需要在 entitlements.plist 文件中添加如下权限:

<key>com.apple.security.protocol-messaging</key>
<true/>

网站公告

今日签到

点亮在社区的每一天
去签到