How to embed a mac app extension in an Electron app?
Asked Answered
I

2

10

I'm trying to embed a Finder Sync extension written in Swift in my app written with Electron. How can I manage to make them work together and communicate with each other? I have read the Apple documentation but it only explains how to add a target to a native application. I also noticed that I can manually inject the .appex compiled file (produced by XCode) in the application Plugins folder using electron builder. How can I develop and test the extension in XCode and embed it correctly in a custom Electron app? Any suggestion?

Thank you very much for any suggestion

Ilsa answered 10/8, 2017 at 11:30 Comment(10)
Have you tried simply copying and pasting your appex to the Plugins folder of your Electron app? As long as your extension is configured according to the documentation, it should launch alongside your main app (it may need to be signed to automatically launch). For testing, make sure your extension is visible and enabled in System Preferences -> Extensions. Then attach your debugger to your Finder Sync process in XCode.Dvandva
Yes! This method works fine if the .plist files are written accordingly as the extension starts correctly. The only question remaining is how to let the main application communicate with the extension if the documentation specifies that the only allowed method is to extend the FIFinderSync class in ObjectiveC/Swift. How can I raise a JS event inside an .appex extension?Ilsa
You will need to use some form of interprocess communication. I'm not familiar with the Electron API, but you should be able to use sockets to handle IPC: nodejs.org/api/net.html#net_class_net_socketDvandva
btw, if you're planning to implement context menus/badges for Windows Explorer as well as Finder, check out our cross-platform project Liferay Nativity: github.com/liferay/liferay-nativity. Linux support is limited and I haven't worked on it much lately, but it'll give you an example of using ports for IPC.Dvandva
@Dvandva your project sounds interesting. I think I will explore it a little bit. Can you provide an example on how to bridge your Liferay Nativity Finder Sync plugin to a node.js project? Thank youIlsa
We don't have node.js examples, but Java and C# are available. They communicate w/ the Finder/Explorer/Nautilus plugins via sockets. Take a look at the source if you want to build a similar node.js example.Dvandva
Thank you for the suggestion! I will give it a try!Ilsa
@Dvandva - copying the appex into Plugins folder in my Electron app does nothing for me - I'm missing something, but what?Bovill
@Dvandva - PlugIns not Plugins, and the package.json must have "extraFiles": ["PlugIns/"] in the "mac" section.Bovill
@TomAndraszek Do you see your Electron app in System Preferences -> Extensions -> Finder? Make sure it's checked. You should see a message in the console like "-[FinderSync init] launched from YourElectronApp/.../YourFinderSync.appex"Dvandva
B
6

Create PlugIns folder in your Electron root folder.

Copy the .appex file into PlugIns folder.

If you are using electron-builder, modify the package.json file - add: "extraFiles": ["PlugIns/"] in the "mac" section.

Build. The Contents of your app package will contain the PlugIns folder and your appex file inside, and the appex will get loaded into your app's process.

Bovill answered 23/2, 2018 at 6:10 Comment(5)
You are right. I've managed to implement this months ago. Maybe I will post a full answer too on how I did it so far.Ilsa
Basically you're inputs are right. At run time the only way I found to make the extension communicate with the Electron app has been implementing an IPC over the loopback interface using Socket.io. Practically, I implemented the sync extension in Swift, built it in an appex file and followed the steps you have mentioned in your answer to package it in Electron. Now I'm controlling it's behavior via Socket.io. It may be a workaround but, for now, it is working quite good. If you have found better solutions I am all ears! :)Ilsa
@MarcoMoschettini do mind sharing how you did it so far? (:Dredger
@MarcoMoschettini any chance you can share the way you do it?Excipient
Hi @MarcoMoschettini Can you please share the way you did it? Actually, we are not MAC developers, but need to work on it and we are helpless to achieve this, as we don't have any swift/objective c background. It will be really appreciable if you will share any minor details. Thank you so much in advance.Magnetism
S
0

How to embed a mac app extension in an Electron app?

I would compile it as an independent binary and include it in some dir to be executed from the electron app using child_process.execFile

You can use arguments when executing the binary with execFile, here is an example (using promise)

const util = require('util');
const execFile = util.promisify(require('child_process').execFile);
async function FinderSyncExtPlugin(ARGUMENTS) {
  const { stdout } = await execFile('YourBinary', ARGUMENTS);
  console.log(stdout);
}
FinderSyncExtPlugin(['argument1','argument2','...']);

You could then use the stdout to know the status/result of the requested operation.

Sissy answered 18/8, 2017 at 20:36 Comment(1)
It's not possible to compile the finder extension as an independent binary as it is automatically generated by Xcode alongisde the Swift/ObjC project using a different target. Your method would still work fine with a normal Command Line MacOS application but is not applicable to my specific situation...Ilsa

© 2022 - 2024 — McMap. All rights reserved.