類似基于 Chromium 的瀏覽器一樣, Electron 也提供了通過 web API 訪問設備硬件的方法。 大部分接口就像在瀏覽器調(diào)用的 API 一樣,但有一些差異需要考慮到。 Electron和瀏覽器之間的主要區(qū)別是請求訪問設備時發(fā)生的情況。 在瀏覽器中,用戶可以在彈出窗口中允許訪問單獨的設備。 在 Electron API中,提供了可供開發(fā)者自動選擇設備或提示用戶通過開發(fā)者創(chuàng)建的接口選擇設備。
Web Bluetooth API
Web Bluetooth API 可以被用來連接藍牙設備。 為了在 Electron 中使用此 API , 開發(fā)者將需要在 webContent 處理 select-bluetooth-device
事件 ,從而與設備請求相關聯(lián)。
此外, ses.setBluetoothPairingHandler(handler)
方法可以被用來處理藍牙設備配對, 這在 Windows 或 Linux 下進行額外的引腳校驗時很有效.
示例
這個示例演示了一個 Electron 應用程序,當點擊了 Test Bluetooth
按鈕時,它會自動選擇第一個可用的藍牙設備。
main.js |
preload.js |
index.html |
renderer.js |
const {app, BrowserWindow, ipcMain} = require('electron')
const path = require('path')
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()
if (deviceList && deviceList.length > 0) {
callback(deviceList[0].deviceId)
}
})
// Listen for a message from the renderer to get the response for the Bluetooth pairing.
ipcMain.on('bluetooth-pairing-response', (event, response) => {
bluetoothPinCallback(response)
})
mainWindow.webContents.session.setBluetoothPairingHandler((details, callback) => {
bluetoothPinCallback = callback
// Send a message to the renderer to prompt the user to confirm the pairing.
mainWindow.webContents.send('bluetooth-pairing-request', details)
})
mainWindow.loadFile('index.html')
}
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
|
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
bluetoothPairingRequest: (callback) => ipcRenderer.on('bluetooth-pairing-request', callback),
bluetoothPairingResponse: (response) => ipcRenderer.send('bluetooth-pairing-response', response)
})
|
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>Web Bluetooth API</title>
</head>
<body>
<h1>Web Bluetooth API</h1>
<button id="clickme">Test Bluetooth</button>
<p>Currently selected bluetooth device: <strong id="device-name""></strong></p>
<script src="./renderer.js"></script>
</body>
</html>
|
async function testIt() {
const device = await navigator.bluetooth.requestDevice({
acceptAllDevices: true
})
document.getElementById('device-name').innerHTML = device.name || `ID: ${device.id}`
}
document.getElementById('clickme').addEventListener('click',testIt)
window.electronAPI.bluetoothPairingRequest((event, details) => {
const response = {}
switch (details.pairingKind) {
case 'confirm': {
response.confirmed = confirm(`Do you want to connect to device ${details.deviceId}?`)
break
}
case 'confirmPin': {
response.confirmed = confirm(`Does the pin ${details.pin} match the pin displayed on device ${details.deviceId}?`)
break
}
case 'providePin': {
const pin = prompt(`Please provide a pin for ${details.deviceId}.`)
if (pin) {
response.pin = pin
response.confirmed = true
} else {
response.confirmed = false
}
}
}
window.electronAPI.bluetoothPairingResponse(response)
})
|
DOCS/FIDDLES/FEATURES/WEB-BLUETOOTH (22.0.2)
Open in Fiddle
WebHID API
WebHID API 可以用于訪問HID 設備,例如 鍵盤和游戲機。 Electron 提供了幾個使用 WebHID API的接口:
- 調(diào)用
navigator.hid.requestDevice
并選擇高清設備,將觸發(fā)會話內(nèi)的 select-hid-device
事件 在處理 select-hid-device
事件期間, hid-device-added
和 hid-device-removed
兩種 Session 事件可以被用來處理設備插拔. 注意:這些事件只會在調(diào)用 select-hid-device 的回調(diào)之前觸發(fā)。它們不打算用作通用 hid 設備偵聽器。
- 在第一次調(diào)用
navigator.hid.requestDevice
前, 可以通過 ses.setDevicePermissionHandler(handler)
給予設備默認權限, 此外,Electron 的默認行為是在相應的 WebContents 的生命周期內(nèi)存儲授予的設備權限。如果需要更長期的存儲,開發(fā)人員可以存儲設備許可信息(比如: 在處理 select-hid-device
事件時),
然后通過 setDevicePermissionHandler
從存儲的信息中讀取
ses.setPermissionCheckHandler(handler)
可以用于禁用特定來源的 HID 訪問。
阻止列表
默認情況下,Electron 使用與 Chromium 相同的 blocklist 如果您想要覆蓋此行為,您可以通過設置 disable-hid-blocklist
標志來做到這一點:
app.commandLine.appendSwitch('disable-hid-blocklist')
示例
這個示例演示了,當 Test WebHID
按鈕被點擊后,一個Electron 應用將通過 ses.setDevicePermissionHandler(handler)
和 select-hid-device
會話事件 自動選擇 HID 設備
main.js |
index.html |
renderer.js |
const {app, BrowserWindow} = require('electron')
const path = require('path')
function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600
})
mainWindow.webContents.session.on('select-hid-device', (event, details, callback) => {
//Add events to handle devices being added or removed before the callback on
//`select-hid-device` is called.
mainWindow.webContents.session.on('hid-device-added', (event, device) => {
console.log('hid-device-added FIRED WITH', device)
//Optionally update details.deviceList
})
mainWindow.webContents.session.on('hid-device-removed', (event, device) => {
console.log('hid-device-removed FIRED WITH', device)
//Optionally update details.deviceList
})
event.preventDefault()
if (details.deviceList && details.deviceList.length > 0) {
callback(details.deviceList[0].deviceId)
}
})
mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
if (permission === 'hid' && details.securityOrigin === 'file:///') {
return true
}
})
mainWindow.webContents.session.setDevicePermissionHandler((details) => {
if (details.deviceType === 'hid' && details.origin === 'file://') {
return true
}
})
mainWindow.loadFile('index.html')
}
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
|
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>WebHID API</title>
</head>
<body>
<h1>WebHID API</h1>
<button id="clickme">Test WebHID</button>
<h3>HID devices automatically granted access via <i>setDevicePermissionHandler</i></h3>
<div id="granted-devices"></div>
<h3>HID devices automatically granted access via <i>select-hid-device</i></h3>
<div id="granted-devices2"></div>
<script src="./renderer.js"></script>
</body>
</html>
|
async function testIt() {
const grantedDevices = await navigator.hid.getDevices()
let grantedDeviceList = ''
grantedDevices.forEach(device => {
grantedDeviceList += `<hr>${device.productName}</hr>`
})
document.getElementById('granted-devices').innerHTML = grantedDeviceList
const grantedDevices2 = await navigator.hid.requestDevice({
filters: []
})
grantedDeviceList = ''
grantedDevices2.forEach(device => {
grantedDeviceList += `<hr>${device.productName}</hr>`
})
document.getElementById('granted-devices2').innerHTML = grantedDeviceList
}
document.getElementById('clickme').addEventListener('click',testIt)
|
DOCS/FIDDLES/FEATURES/WEB-HID (22.0.2)
Open in Fiddle
Web Serial API
Web Serial API 可以被用來訪問串口設備比如 USB 或藍牙。 為了在 Electron 中使用這個 API, 開發(fā)者需要先定義關聯(lián)在串口請求中的 select-serial-port
會話事件 .
有幾個額外的 API 用于與 Web Serial API 合作:
示例
這個示例項目既演示了一個 Electron 應用通過 ses.setDevicePermissionHandler(handler)
自動選擇串口設備,又演示了當 Test Web Serial
按鈕被點擊后,通過 select-serial-port
event on the Session 選擇第一個可用的(若已連接) Arduino Uno 串口設備的流程。
main.js |
index.html |
renderer.js |
const {app, BrowserWindow} = require('electron')
const path = require('path')
function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600
})
mainWindow.webContents.session.on('select-serial-port', (event, portList, webContents, callback) => {
//Add listeners to handle ports being added or removed before the callback for `select-serial-port`
//is called.
mainWindow.webContents.session.on('serial-port-added', (event, port) => {
console.log('serial-port-added FIRED WITH', port)
//Optionally update portList to add the new port
})
mainWindow.webContents.session.on('serial-port-removed', (event, port) => {
console.log('serial-port-removed FIRED WITH', port)
//Optionally update portList to remove the port
})
event.preventDefault()
if (portList && portList.length > 0) {
callback(portList[0].portId)
} else {
callback('') //Could not find any matching devices
}
})
mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
if (permission === 'serial' && details.securityOrigin === 'file:///') {
return true
}
return false
})
mainWindow.webContents.session.setDevicePermissionHandler((details) => {
if (details.deviceType === 'serial' && details.origin === 'file://') {
return true
}
return false
})
mainWindow.loadFile('index.html')
mainWindow.webContents.openDevTools()
}
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
|
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>Web Serial API</title>
<body>
<h1>Web Serial API</h1>
<button id="clickme">Test Web Serial API</button>
<p>Matching Arduino Uno device: <strong id="device-name""></strong></p>
<script src="./renderer.js"></script>
</body>
</html>
|
async function testIt() {
const filters = [
{ usbVendorId: 0x2341, usbProductId: 0x0043 },
{ usbVendorId: 0x2341, usbProductId: 0x0001 }
];
try {
const port = await navigator.serial.requestPort({filters});
const portInfo = port.getInfo();
document.getElementById('device-name').innerHTML = `vendorId: ${portInfo.usbVendorId} | productId: ${portInfo.usbProductId} `
} catch (ex) {
if (ex.name === 'NotFoundError') {
document.getElementById('device-name').innerHTML = 'Device NOT found'
} else {
document.getElementById('device-name').innerHTML = ex
}
}
}
document.getElementById('clickme').addEventListener('click',testIt)
|
DOCS/FIDDLES/FEATURES/WEB-SERIAL (22.0.2)
Open in Fiddle
更多建議: