デバイスアクセス
Chromium ベースのブラウザのように、Electron はウェブ API を介してデバイスハードウェアへのアクセスを提供します。 ほとんどの場合これらの API はブラウザと同じように動作しますが、いくつかの違いを考慮しなければなりません。 Electronとブラウザの主な違いは、デバイスアクセスが要求されたときに起きることです。 ブラウザでは、ユーザーにポップアップが表示され、ユーザーは個々のデバイスにアクセスを許可できます。 Electron API では、デバイスを自動選択したり開発者が作成したインターフェースを介してユーザーにデバイス選択を促したりするために、開発者が利用できる API を提供しています。
#
ウェブ Bluetooth APIウェブ Bluetooth API は、Bluetooth デバイスとの通信に利用できます。 この API を Electron で使用するには、開発者がデバイスリクエストに関連する webContents の select-bluetooth-device
イベント をハンドリングする必要があります。
#
サンプルこの例では、Test Bluetooth
ボタンがクリックされたときに最初に利用可能な Bluetooth デバイスを自動的に選択する、Electron のアプリケーションを示しています。
- index.html
- main.js
- renderer.js
<!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>
const {app, BrowserWindow} = require('electron')const path = require('path')
function createWindow () { const mainWindow = new BrowserWindow({ width: 800, height: 600 })
mainWindow.webContents.on('select-bluetooth-device', (event, deviceList, callback) => { event.preventDefault() if (deviceList && deviceList.length > 0) { callback(deviceList[0].deviceId) } })
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()})
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)
#
WebHID APIWebHID API は、キーボードやゲームパッドなどの HID デバイスのアクセスに利用できます。 Electron は、WebHID API と連携するためにいくつかの API を提供しています。
- Session の
select-hid-device
イベント は、navigator.hid.requestDevice
が呼び出された時に HID デバイスを選択するために利用できます。 さらに Session のhid-device-added
とhid-device-removed
イベントは、navigator.hid.requestDevice
の処理中におけるデバイスの接続や除去のハンドリングに使用できます。 ses.setDevicePermissionHandler(handler)
は、先にnavigator.hid.requestDevice
を介して許可の呼び出しをせずとも、デバイスへのデフォルトの権限を提供するために利用できます。 また、Electron のデフォルトの動作では、付与されたデバイスの権限を対応する WebContents が有効の間だけ保存します。 より長期間の保存が必要な場合、開発者は付与されたデバイスのパーミッションを保存し (select-hid-device
イベントを処理するときなど)、setDevicePermissionHandler
でそのストレージから読み出しできます。ses.setPermissionCheckHandler(handler)
を使うと、特定オリジンの HID アクセスを無効にできます。
#
ブロックリストデフォルトでは、Electron は Chromium が使用する ブロックリスト と同じものを採用しています。 この動作を無効にしたい場合は、以下のように disable-hid-blocklist
フラグで設定できます。
app.commandLine.appendSwitch('disable-hid-blocklist')
#
サンプルこの例では、ses.setDevicePermissionHandler(handler)
を通じて HID デバイスを自動選択する Electron アプリケーションを示しています。Test WebHID
ボタンがクリックされると、Session の select-hid-device
イベントを通じて HID デバイスを自動選択します。
- index.html
- main.js
- renderer.js
<!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>
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) => { event.preventDefault() if (details.deviceList && details.deviceList.length > 0) { callback(details.deviceList[0].deviceId) } })
mainWindow.webContents.session.on('hid-device-added', (event, device) => { console.log('hid-device-added FIRED WITH', device) })
mainWindow.webContents.session.on('hid-device-removed', (event, device) => { console.log('hid-device-removed FIRED WITH', device) })
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()})
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)
#
Web シリアル APIWeb シリアル API を使用すると、シリアルポートや USB、Bluetooth で接続されたシリアルデバイスにアクセスできます。 この API を Electron で使用するには、開発者がシリアルポートのリクエストに関する Session の select-serial-port
イベント をハンドリングする必要があります。
Web シリアル API の利用にあたって更にいくつかの API があります。
- Session の
serial-port-added
とserial-port-removed
イベントは、navigator.serial.requestPort
の処理中におけるデバイスの接続や除去のハンドリングに使用できます。 ses.setPermissionCheckHandler(handler)
を使うと、特定オリジンのシリアルアクセスを無効にできます。
#
サンプルこの例で示している Electron アプリケーションは、Test Web Serial
ボタンがクリックされたときに、Session の select-serial-port
イベント を通して最初に利用可能な Arduino Uno シリアルデバイスを (接続されている場合は) 自動選択します。
- index.html
- main.js
- renderer.js
<!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>
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) => { event.preventDefault() if (portList && portList.length > 0) { callback(portList[0].portId) } else { callback('') //Could not find any matching devices } })
mainWindow.webContents.session.on('serial-port-added', (event, port) => { console.log('serial-port-added FIRED WITH', port) })
mainWindow.webContents.session.on('serial-port-removed', (event, port) => { console.log('serial-port-removed FIRED WITH', port) })
mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => { if (permission === 'serial' && details.securityOrigin === 'file:///') { return true } })
mainWindow.webContents.session.setDevicePermissionHandler((details) => { if (details.deviceType === 'serial' && details.origin === 'file://') { return true } }) 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()})
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)