Liens profonds
Vue d'ensemble
Ce guide vous guidera afin que puissiez configurer votre application Electron en tant que gestionnaire par défaut d'un protocole spécifique.
À la fin de ce tutoriel, votre application sera configurée pour intercepter et gérer toutes les URL commençant par un protocole spécifique. Pour cet exemple, le protocole utilisé sera "electron-fiddle://
".
Exemples
Processus principal (main.js)
Importons tout d'abord, depuis electron
, les modules requis. Ces modules aident à gérer le cycle de notre application et à créer une fenêtre de navigateur native.
const { app, BrowserWindow, shell } = require('electron')
const path = require('node:path')
Ensuite, nous allons procéder à l’enregistrement de notre application comme gestionnaire de tous les protocoles "electron-fiddle://
« .
if (process.defaultApp) {
if (process.argv.length >= 2) {
app.setAsDefaultProtocolClient('electron-fiddle', process.execPath, [path.resolve(process.argv[1])])
}
} else {
app.setAsDefaultProtocolClient('electron-fiddle')
}
Nous allons maintenant définir la fonction chargée de la création de notre fenêtre de navigateur et charger le fichier index.html
de notre application.
let mainWindow
const createWindow = () => {
// Création de la BrowserWindow.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
mainWindow.loadFile('index.html')
}
Dans l'étape suivante , nous allons créer notre BrowserWindow
et dire à notre application comment gérer un événement venant d'un lien vers un protocole externe.
Ce code sera différent sur Windows et Linux par rapport à MacOS. Cela est dû au fait que les deux plateformes émettent l'événement second-instance
plutôt que l'événement open-url
et Windows nécessitant du code supplémentaire pour ouvrir le contenu du lien de protocole dans la même instance Electron. Pour en savoir plus à ce sujet vous pouvez lire ici.
Code Windows et Linux :
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
app.quit()
} else {
app.on('second-instance', (event, commandLine, workingDirectory) => {
// quelqu'un a essayé d'exécuter une deuxième instance, on doit donc donner le focus à la fenêtre.
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore()
mainWindow.focus()
}
// la variable commandLine est un tableau de chaine de caractères dans lequel le dernier élément est l'url du lien profond
dialog.showErrorBox('Welcome Back', `You arrived from: ${commandLine.pop()}`)
})
// Création de mainWindows, chargement du reste de l'application, etc...
app.whenReady().then(() => {
createWindow()
})
}
Code MacOS :
// Cette méthode sera appelée quant Electron aura fini
// de s'initialiser et sera prêt à créer des fenêtres de navigation.
// Certaines APIs peuvent être utilisées uniquement quant cet événement est émit.
app.whenReady().then(() => {
createWindow()
})
// gestion du protocole. Dans ce cas, nous choisissons d’afficher une boîte d’erreur.
app.on('open-url', (event, url) => {
dialog.showErrorBox('Content de vous revoir ', `Vous venez de: ${url}`)
})
Enfin, nous ajouterons du code supplémentaire pour gérer la fermeture de notre application par l'utilisateur.
// Quitter lorsque toutes les fenêtres sont fermées, sauf sur macOS. Là, il est courant
// pour les applications et leur barre de menus de rester actives jusqu’à ce que l’utilisateur quitte
// explicitement avec Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
Notes importantes
Empaquetage
Sous macOS et Linux, cette fonctionnalité ne fonctionnera que si votre application est empaquetée. Cela ne fonctionne pas lorsque vous le lancez en développement à partir de la ligne de commande. Lorsque vous empaquetez votre application, vous devrez vous assurer que les fichiers Info.plist
sur macOS ou .desktop
sur Linux ont bien été mis à jour pour inclure le nouveau gestionnaire de protocole. Certains des outils d'Electron pour regrouper et distribuer des applications gèrent cela pour vous.
Electron Forge
If you're using Electron Forge, adjust packagerConfig
for macOS support, and the configuration for the appropriate Linux makers for Linux support, in your Forge configuration (please note the following example only shows the bare minimum needed to add the configuration changes):
{
"config": {
"forge": {
"packagerConfig": {
"protocols": [
{
"name": "Electron Fiddle",
"schemes": ["electron-fiddle"]
}
]
},
"makers": [
{
"name": "@electron-forge/maker-deb",
"config": {
"mimeType": ["x-scheme-handler/electron-fiddle"]
}
}
]
}
}
}
Electron Packager
Prise en charge de macOS :
Si vous utilisez l'API d'Electron Packager, l'ajout du support des gestionnaires de protocoles s'effectue de la même manière qu'avec Electron Forge, excepté que protocols
fait partie des options de Packager passées à la fonction packager
.
const packager = require('@electron/packager')
packager({
// ...other options...
protocols: [
{
name: 'Electron Fiddle',
schemes: ['electron-fiddle']
}
]
}).then(paths => console.log(`SUCCESS: Created ${paths.join(', ')}`))
.catch(err => console.error(`ERROR: ${err.message}`))
Si vous utilisez le CLI d’Electron Packager, utilisez les indicateurs --protocol
et --protocol-name
. Par exemple :
npx electron-packager . --protocol=electron-fiddle --protocol-name="Electron Fiddle"
Conclusion
Après avoir démarré votre application Electron, vous pouvez entrer une URL dans votre navigateur qui contient le protocole personnalisé, comme par exemple "electron-fiddle://open"
et observer que l’application répondra et affichera une boîte de dialogue d’erreur.
- main.js
- preload.js
- index.html
- renderer.js
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, shell, dialog } = require('electron/main')
const path = require('node:path')
let mainWindow
if (process.defaultApp) {
if (process.argv.length >= 2) {
app.setAsDefaultProtocolClient('electron-fiddle', process.execPath, [path.resolve(process.argv[1])])
}
} else {
app.setAsDefaultProtocolClient('electron-fiddle')
}
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
app.quit()
} else {
app.on('second-instance', (event, commandLine, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore()
mainWindow.focus()
}
dialog.showErrorBox('Welcome Back', `You arrived from: ${commandLine.pop().slice(0, -1)}`)
})
// Create mainWindow, load the rest of the app, etc...
app.whenReady().then(() => {
createWindow()
})
app.on('open-url', (event, url) => {
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
})
}
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
mainWindow.loadFile('index.html')
}
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
// Handle window controls via IPC
ipcMain.on('shell:open', () => {
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
const pagePath = path.join('file://', pageDirectory, 'index.html')
shell.openExternal(pagePath)
})
const { contextBridge, ipcRenderer } = require('electron/renderer')
contextBridge.exposeInMainWorld('shell', {
open: () => ipcRenderer.send('shell:open')
})
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>app.setAsDefaultProtocol Demo</title>
</head>
<body>
<h1>App Default Protocol Demo</h1>
<p>The protocol API allows us to register a custom protocol and intercept existing protocol requests.</p>
<p>These methods allow you to set and unset the protocols your app should be the default app for. Similar to when a
browser asks to be your default for viewing web pages.</p>
<p>Open the <a href="https://www.electronjs.org/docs/latest/api/protocol">full protocol API documentation</a> in your
browser.</p>
-----
<h3>Demo</h3>
<p>
First: Launch current page in browser
<button id="open-in-browser" class="js-container-target demo-toggle-button">
Click to Launch Browser
</button>
</p>
<p>
Then: Launch the app from a web link!
<a href="electron-fiddle://open">Click here to launch the app</a>
</p>
----
<p>You can set your app as the default app to open for a specific protocol. For instance, in this demo we set this app
as the default for <code>electron-fiddle://</code>. The demo button above will launch a page in your default
browser with a link. Click that link and it will re-launch this app.</p>
<h3>Packaging</h3>
<p>This feature will only work on macOS when your app is packaged. It will not work when you're launching it in
development from the command-line. When you package your app you'll need to make sure the macOS <code>plist</code>
for the app is updated to include the new protocol handler. If you're using <code>@electron/packager</code> then you
can add the flag <code>--extend-info</code> with a path to the <code>plist</code> you've created. The one for this
app is below:</p>
<p>
<h5>macOS plist</h5>
<pre><code>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>electron-api-demos</string>
</array>
<key>CFBundleURLName</key>
<string>Electron API Demos Protocol</string>
</dict>
</array>
<key>ElectronTeamID</key>
<string>VEKTX9H2N7</string>
</dict>
</plist>
</code>
</pre>
<p>
<!-- You can also require other files to run in this process -->
<script src="./renderer.js"></script>
</body>
</html>
// This file is required by the index.html file and will
// be executed in the renderer process for that window.
// All APIs exposed by the context bridge are available here.
// Binds the buttons to the context bridge API.
document.getElementById('open-in-browser').addEventListener('click', () => {
window.shell.open()
})