Everyone has probably encountered this situation at least a few times in their lifetime:
You're browsing the web and come across a file or link you want to open in an app on your computer.
Your browser will prompt you to make sure it's okay with a nice message like this:
This is incredibly useful, and allows users to have a seamless workflow of going straight to your app.
Electron app -> browser
We have been working tirelessly on new features for Swach, and one of those new features was the ability to share palettes with other users and view them online.
The sharing aspect was trivial. We used Electron's shell
module which provides an openExternal
method that we used to generate a link with query params to pass the palette data to swach.io.
Browser -> Electron app
Going the other direction, with deep links, proved much harder, however. Electron does support using deep links and custom protocols out of the box with setAsDefaultProtocolClient, but opening these custom protocol links requires a much different setup for different platforms.
macOS
On macOS there is a special open-url event that is supported, which makes things fairly straightforward.
We can set our app as the default protocol client, and then use open-url
to handle importing our data.
Note: You can replace custom
with whatever you want to name your custom protocol.
let deeplinkingUrl;
app.setAsDefaultProtocolClient('custom');
app.on('open-url', function (event, url) {
event.preventDefault();
deeplinkingUrl = url;
});
We will also need to add these custom protocols to our plist
. If you are using electron-forge or electron-builder, you can add this to your config.
electron-forge
packagerConfig: {
protocols: [
{
protocol: 'custom',
name: 'custom',
schemes: 'custom'
}
]
}
electron-builder
"build": {
"protocols": [
{
"name": "custom",
"schemes": [
"custom"
]
}
]
}
Windows
On Windows, the open-url
event is not supported, and instead Electron will try to open a new instance of your application.
We will have to catch this and focus our existing application instead. We also have to modify setAsDefaultProtocolClient
to support running in dev mode in Windows.
if (isDev && process.platform === 'win32') {
// Set the path of electron.exe and your app.
// These two additional parameters are only available on windows.
// Setting this is required to get this working in dev mode.
app.setAsDefaultProtocolClient('custom', process.execPath, [
resolve(process.argv[1])
]);
} else {
app.setAsDefaultProtocolClient('custom');
}
// Force single application instance
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
return;
} else {
app.on('second-instance', (e, argv) => {
if (process.platform !== 'darwin') {
// Find the arg that is our custom protocol url and store it
deeplinkingUrl = argv.find((arg) => arg.startsWith('custom://'));
}
if (myWindow) {
if (myWindow.isMinimized()) myWindow.restore();
myWindow.focus();
}
});
}
Final Result
Our final result is something like this:
let deeplinkingUrl;
if (isDev && process.platform === 'win32') {
// Set the path of electron.exe and your app.
// These two additional parameters are only available on windows.
// Setting this is required to get this working in dev mode.
app.setAsDefaultProtocolClient('custom', process.execPath, [
resolve(process.argv[1])
]);
} else {
app.setAsDefaultProtocolClient('custom');
}
app.on('open-url', function (event, url) {
event.preventDefault();
deeplinkingUrl = url;
});
// Force single application instance
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
return;
} else {
app.on('second-instance', (e, argv) => {
if (process.platform !== 'darwin') {
// Find the arg that is our custom protocol url and store it
deeplinkingUrl = argv.find((arg) => arg.startsWith('custom://'));
}
if (myWindow) {
if (myWindow.isMinimized()) myWindow.restore();
myWindow.focus();
}
});
}
For a good example of supporting deep linking / custom protocols on both macOS and Windows, check out this example app.
Top comments (0)