与普通浏览器类似,Electron 也支持访问设备硬件。本文介绍如何在 Electron 中使用 Web Bluetooth API 连接蓝牙设备,并提供一个简单的示例。
Electron 与浏览器的区别
在浏览器中,用户通过弹窗选择设备,而在 Electron 中,开发者可以自定义设备选择逻辑。例如,自动选择特定设备或通过自定义界面让用户选择。
Web Bluetooth API
Web Bluetooth API 允许连接蓝牙设备。在 Electron 中,开发者需要处理以下内容:
1. 设备选择事件:通过监听 select-bluetooth-device 事件来选择设备。
2. 蓝牙配对:通过 session.setBluetoothPairingHandler(handler) 方法处理配对请求。
提示:setBluetoothPairingHandler 在 Windows 或 Linux 系统中处理蓝牙 PIN 验证特别有用。
示例:自动选择蓝牙设备
以下代码展示了一个简单的 Electron 应用,当用户点击按钮时,会自动选择名为 test 的蓝牙设备。
main.js
const { app, BrowserWindow, ipcMain } = require('electron/main');
const path = require('node:path');
let bluetoothPinCallback;
let selectBluetoothCallback;
function createWindow() {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'), // 预加载文件路径
},
});
// 监听蓝牙设备选择事件
mainWindow.webContents.on('select-bluetooth-device', (event, deviceList, callback) => {
event.preventDefault(); // 阻止默认设备选择行为
selectBluetoothCallback = callback; // 保存回调函数
const result = deviceList.find((device) => device.deviceName === 'test'); // 查找名为 "test" 的设备
if (result) {
callback(result.deviceId); // 返回设备 ID
} else {
// 未找到设备时的处理逻辑(可以等待设备开启或取消请求)
}
});
// 用户取消蓝牙请求时的逻辑
ipcMain.on('cancel-bluetooth-request', () => {
selectBluetoothCallback('');
});
// 处理蓝牙配对请求
ipcMain.on('bluetooth-pairing-response', (event, response) => {
bluetoothPinCallback(response); // 将用户的配对响应传递给回调
});
mainWindow.webContents.session.setBluetoothPairingHandler((details, callback) => {
bluetoothPinCallback = callback; // 保存回调函数
// 通知渲染进程,提示用户确认配对
mainWindow.webContents.send('bluetooth-pairing-request', details);
});
mainWindow.loadFile('index.html'); // 加载 HTML 页面
}
app.whenReady().then(() => {
createWindow();
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});
preload.js
暴露 IPC 通信接口给渲染进程。
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
onBluetoothPairingRequest: (callback) => ipcRenderer.on('bluetooth-pairing-request', callback),
sendBluetoothResponse: (response) => ipcRenderer.send('bluetooth-pairing-response', response),
cancelBluetoothRequest: () => ipcRenderer.send('cancel-bluetooth-request'),
});
renderer.js
管理用户界面逻辑。
document.getElementById('test-bluetooth').addEventListener('click', async () => {
try {
const device = await navigator.bluetooth.requestDevice({ acceptAllDevices: true });
console.log('Selected device:', device);
} catch (error) {
console.error('Error selecting Bluetooth device:', error);
}
});
window.electronAPI.onBluetoothPairingRequest((event, details) => {
const userConfirmed = confirm(`Pair with device ${details.deviceName}?`);
window.electronAPI.sendBluetoothResponse(userConfirmed ? '1234' : ''); // 模拟输入 PIN
});
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bluetooth Example</title>
</head>
<body>
<button id="test-bluetooth">Test Bluetooth</button>
<script src="renderer.js"></script>
</body>
</html>