【问题标题】:Electron - How to create deep-linking on linuxElectron - 如何在 linux 上创建深度链接
【发布时间】:2021-04-24 18:04:37
【问题描述】:

我有一个 ElectronJS 项目,我在这个项目中使用了协议(深层链接)。它可以在 MacOS 和 Windows 上运行,但在 Linux 上我无法理解如何创建此协议。

我查看了 ElectronJS 文档以及网络上的问题等,但我不知道如何在 Linux 上初始化协议。正如我在 MacOS 和 Windows 上所取得的成功一样,我想要实现的只是一个与应用程序进行深度链接交互的协议。

适用于 MacOS 和 Windows 的代码:

// main.ts

// –– B ––– PROTOCOL HANDLER –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

ProtocolUtils.setDefaultProtocolClient();

// eslint-disable-next-line default-case
switch (process.platform) {
    case 'darwin':
        ProtocolUtils.setProtocolHandlerOSX();
        break;
    case 'win32':
        ProtocolUtils.setProtocolHandlerWin32();
        break;
}
// –– E ––– PROTOCOL HANDLER –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

// protocol.ts

export abstract class ProtocolUtils {
    /**
     * @description Create default protocole for call this app.
     *  Ex : in your browser => myapp://test
     */
    public static setDefaultProtocolClient(): void {
        if (!app.isDefaultProtocolClient('myapp')) {
            // Define custom protocol handler.
            // Deep linking works on packaged versions of the application!
            app.setAsDefaultProtocolClient('myapp');
        }
    }

    /**
     * @description Create logic (WIN32) for open url from protocol
     */
    public static setProtocolHandlerWin32(): void {
        // Force Single Instance Application on win32
        const gotTheLock = app.requestSingleInstanceLock();

        app.on('second-instance', (e: Electron.Event, argv: string[]) => {
            // Someone tried to run a second instance, we should focus our window.
            if (MainWindow.mainWindow) {
                if (MainWindow.mainWindow.isMinimized()) MainWindow.mainWindow.restore();
                MainWindow.mainWindow.focus();
            } else {
                MainWindow.openMainWindow(); // Open main windows
            }

            app.whenReady().then(() => {
                MainWindow.mainWindow.loadURL(this._getDeepLinkUrlForWin32(argv)); // Load URL in WebApp
            });
        });

        if (gotTheLock) {
            app.whenReady().then(() => {
                MainWindow.openMainWindow(); // Open main windows
                MainWindow.mainWindow.loadURL(this._getDeepLinkUrlForWin32()); // Load URL in WebApp
            });
        } else {
            app.quit();
        }
    }

    /**
     * @description Create logic (OSX) for open url from protocol
     */
    public static setProtocolHandlerOSX(): void {
        app.on('open-url', (event: Electron.Event, url: string) => {
            event.preventDefault();
            app.whenReady().then(() => {
                MainWindow.openMainWindow(); // Open main windows
                MainWindow.mainWindow.loadURL(this._getUrlToLoad(url)); // Load URL in WebApp
            });
        });
    }

    /**
     * @description Format url to load in mainWindow
     */
    private static _getUrlToLoad(url: string): string {
        // Ex: url = myapp://deep-link/test?params1=paramValue
        // Ex: Split for remove myapp:// and get deep-link/test?params1=paramValue
        const urlSplitted = url.split('//');
        // Generate URL to load in WebApp.
        // Ex: file://path/index.html#deep-link/test?params1=paramValue
        const urlToLoad = format({
            pathname: Env.BUILDED_WEBAPP_INDEX_PATH,
            protocol: 'file:',
            slashes: true,
            hash: `#${urlSplitted[1]}`,
        });

        return urlToLoad;
    }

    /**
    * @description Resolve deep link url for windows from process argv
    */
    private static _getDeepLinkUrlForWin32(argv?: string[]): string {
        let url: string;
        const newArgv: string[] = !isNil(argv) ? argv : process.argv;
        // Protocol handler for win32
        // argv: An array of the second instance’s (command line / deep linked) arguments
        if (process.platform === 'win32') {
            // Get url form precess.argv
            newArgv.forEach((arg) => {
                if (/myapp:\/\//.test(arg)) {
                    url = arg;
                }
            });

            if (!isNil(url)) {
                return this._getUrlToLoad(url); // Load URL in WebApp
            } else if (!isNil(argv) && isNil(url)) {
                throw new Error('URL is undefined');
            }
        }
    }
}

我不担心 macOS 和 windows,但在 linux 上,即使有以下行,协议也不存在: ProtocolUtils.setDefaultProtocolClient();谁负责创建myapp: //协议...

当我运行这个命令时:xdg-open myapp://deep-link/test?toto=titi 一个错误告诉我这个协议不存在

如果有人有我在 Linux 上配置的示例或者可以帮助我吗?

谢谢

【问题讨论】:

    标签: linux electron electron-builder


    【解决方案1】:

    好的,我找到了解决方案!

    首先,我们移除了 electron-forge 并将其替换为 electron-builder (cf doc)。

    然后在阅读了大量关于 Linux 上的深层链接的文档后,文档示例:

    我的解决方案是:

    # electron-builder.yml
    appId: com.myapp.myapp
    productName: myapp
    directories:
        output: out
    linux:
        icon: src/assets/icons/app/icon@256x256.png
        category: Utility
        mimeTypes: [x-scheme-handler/myapp] # Define MimeType
        desktop:                            # Define desktop elem
            exec: myapp %u                  # Define Exec
        target:
            - target: deb
              arch:
                  - x64
    
    

    所以我在这里用我的协议名称定义了 MimeType myapp 可以给出:

    myapp://toto?foo=bar

    在我的桌面文件中使用myapp %u 定义Exec,因为%u => 单个URL。本地文件可以作为文件:URL 或文件路径传递。(cf doc

    为了完成我的main.tsprotocol.utils.ts

    // main.ts
    
    
    // –– B ––– PROTOCOL HANDLER –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
    
    ProtocolUtils.setDefaultProtocolClient();
    
    switch (process.platform) {
        case 'darwin':
            ProtocolUtils.setProtocolHandlerOSX();
            break;
        case 'linux':
        case 'win32':
            ProtocolUtils.setProtocolHandlerWindowsLinux();
            break;
        default:
            throw new Error('Process platform is undefined');
    }
    // –– E ––– PROTOCOL HANDLER –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
    
    // protocol.utils.ts
    
    export abstract class ProtocolUtils {
        public static setDefaultProtocolClient(): void {
            if (!app.isDefaultProtocolClient('myapp')) {
                // Define custom protocol handler.
                // Deep linking works on packaged versions of the application!
                app.setAsDefaultProtocolClient('myapp');
            }
        }
    
        /**
         * @description Create logic (WIN32 and Linux) for open url from protocol
         */
        public static setProtocolHandlerWindowsLinux(): void {
            // Force Single Instance Application
            const gotTheLock = app.requestSingleInstanceLock();
    
            app.on('second-instance', (e: Electron.Event, argv: string[]) => {
                // Someone tried to run a second instance, we should focus our window.
                if (MainWindow.mainWindow) {
                    if (MainWindow.mainWindow.isMinimized()) MainWindow.mainWindow.restore();
                    MainWindow.mainWindow.focus();
                } else {
                    // Open main windows
                    MainWindow.openMainWindow();
                }
    
                app.whenReady().then(() => {
                    MainWindow.mainWindow.loadURL(this._getDeepLinkUrl(argv));
                });
            });
    
            if (gotTheLock) {
                app.whenReady().then(() => {
                    // Open main windows
                    MainWindow.openMainWindow();
                    MainWindow.mainWindow.loadURL(this._getDeepLinkUrl());
                });
            } else {
                app.quit();
            }
        }
    
        /**
         * @description Create logic (OSX) for open url from protocol
         */
        public static setProtocolHandlerOSX(): void {
            app.on('open-url', (event: Electron.Event, url: string) => {
                event.preventDefault();
                app.whenReady().then(() => {
                    if (!isNil(url)) {
                        // Open main windows
                        MainWindow.openMainWindow();
                        MainWindow.mainWindow.loadURL(this._getUrlToLoad(url));
                    } else {
                        this._logInMainWindow({ s: 'URL is undefined', isError: true });
                        throw new Error('URL is undefined');
                    }
                });
            });
        }
    
        /**
         * @description Format url to load in mainWindow
         */
        private static _getUrlToLoad(url: string): string {
            // Ex: url = myapp://deep-link/test?params1=paramValue
            // Ex: Split for remove myapp:// and get deep-link/test?params1=paramValue
            const splittedUrl = url.split('//');
            // Generate URL to load in WebApp.
            // Ex: file://path/index.html#deep-link/test?params1=paramValue
            const urlToLoad = format({
                pathname: Env.BUILDED_APP_INDEX_PATH,
                protocol: 'file:',
                slashes: true,
                hash: `#${splittedUrl[1]}`,
            });
    
            return urlToLoad;
        }
    
        /**
        * @description Resolve deep link url for Win32 or Linux from process argv
        * @param argv: An array of the second instance’s (command line / deep linked) arguments
        */
        private static _getDeepLinkUrl(argv?: string[]): string {
            let url: string;
            const newArgv: string[] = !isNil(argv) ? argv : process.argv;
            // Protocol handler
            if (process.platform === 'win32' || process.platform === 'linux') {
                // Get url form precess.argv
                newArgv.forEach((arg) => {
                    if (/myapp:\/\//.test(arg)) {
                        url = arg;
                    }
                });
    
                if (!isNil(url)) {
                    return this._getUrlToLoad(url);
                } else if (!isNil(argv) && isNil(url)) {
                    this._logInMainWindow({ s: 'URL is undefined', isError: true });
                    throw new Error('URL is undefined');
                }
            }
        }
    
    

    这是工作:D

    【讨论】:

    • 你能分享你的 MainWindow 逻辑吗?我的意思是,您与 protocolHandler 共享主窗口的方式
    猜你喜欢
    • 2021-05-30
    • 2017-01-10
    • 2020-10-21
    • 2016-07-08
    • 2016-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-13
    相关资源
    最近更新 更多