Help us understand the problem. What is going on with this article?

Electron+Macで「このアプリケーションで開く」に対応する

TL;DR

electron-builder を使用しているElectronアプリをmacOSの「このアプリケーションで開く」に対応させます。

さらに、アプリ内でファイルパスを受け取る方法も取り上げます。

4.png

行儀のいいエディターの挙動

特定の形式のファイルを編集するためのエディターをElectronで作る時など、特定のファイル形式と自作アプリケーションを関連づけたい時があると思います。

Macで動作する他のエディターの代表としてVisual Studio Codeを観察してみました。
以下のような挙動があることがわかります。

「このアプリケーションで開く」に表示される

1.png
VSCodeはJSONファイルの編集に対応しているので、FinderにてJSONファイルを右クリックすると、「このアプリケーションで開く」の一覧に現れます。

「推奨アプリケーション」で明るく表示される

2.png
「このアプリケーションで開く」メニューにて「その他…」を選ぶと、Macにインストールされているアプリケーション一覧が表示されます。選択対象を「推奨アプリケーション」にした場合、そのファイルに対応していないアプリケーションがグレーアウトします。VSCodeはJSONファイルの編集に対応しているので、VSCodeが明るく表示されています。

ファイルにアイコンが設定されている

JSONファイルに専用のアイコンが設定されています。
(余談ですが、上の画像にてJSONファイルに設定されているアイコンはVSCodeのものではなく、Adobe製品によるものだと思われます。)

ダブルクリックすると開く

当たり前ですが、ファイルアイコンをダブルクリックしたり、「このアプリケーションで開く」にてVSCodeを選択すると、VSCodeでそのファイルが開かれます。

これらの挙動はInfo.plistによるもの

世の多くのエディターが上にあげたものと同様の挙動をするにもかかわらず、あなたの作ったエディターは「このアプリケーションで開く」に現れませんし、「推奨アプリケーション」にてグレーアウトされると思います。

それは、Info.plist を正しく設定していないからです。

試しにVisual Studio CodeのInfo.plistを覗いてみましょう。
Finderからアプリケーション→Visual Studio Codeを右クリック→パッケージの内容を表示 です。

3.png

plist はプロパティリストの略だそうで、いろんな値が設定されています。
その中にDocument typesという項目があり、しっかりとJSONファイルも定義されています。

このDocument typesを適切に設定してあげることで、自作のアプリケーションも「このアプリケーションで開く」に対応させ、「推奨アプリケーション」に表示させることができます。

ビルド時にInfo.plistに項目を追記する

electron-builderには、このInfo.plistに項目を追記する機能が備わっています。

package.jsonに以下のように extendInfo の項目を追加します。

package.json(一部省略)
{
  "build": {
    "productName": "My Awesome Application",
    "appId": "com.wararyo.myawesomeapplication",
    "mac": {
      "icon": "build/icons/icon.icns",
      "extendInfo": {
        "CFBundleDocumentTypes":[
          {
            "CFBundleTypeExtensions": ["myextention"],
            "CFBundleTypeIconFile": "My Awesome Application.icns"
          }
        ]
      }
    }
  }
}

この例では、このアプリケーションが拡張子.myextentionのファイルに対応していると認識されるように記述します。ついでにアプリアイコンを割り当てています。

あとはいつものようにbuild、dmgファイルを開きインストールすれば、「このアプリケーションで開く」に現れています。

4.png

ちなみに私は.eclairconversationという拡張子を編集するためのアプリケーション Eclair Conversation Editorを作成しました。

第2引数にファイルパスは渡らない

Windowsにてファイルを開くときはファイルパスが第2引数に渡るので、以下のようなコードでパスを取得することができます。

index.js
//引数でファイル指定があったらそれを開く
if(process.argv.length > 1) {
  var p = process.argv[1];
  if(p.match(/\.[a-zA-Z]+$/)) load(p);
}

この方法はMacでは使えません。
Mac版のElectronにおいては起動時にopen-fileというイベントがappに対して渡るので、そこでファイルパスを取得します。
ファイルを開くとともにアプリケーションが起動する場合の他に、すでに起動しているアプリケーションでファイルを開く場合にもこのイベントが発行されます。

index.js
import { app } from 'electron'
app.on('open-file', (event,path) => {
  event.preventDefault();
  load(path);
});

ただし、ファイルを開くとともにアプリケーションが起動する場合、open-fileが発行されるタイミングではまだmainWindowが立ち上がっていないと思います。
そのときは一旦別の変数に退避させ、また別のタイミングでファイルを開く処理を行います。

これに関してはアプリケーションによって実装が異なってくるかと思います。参考に私のアプリケーションでの実装を貼っておきます。electron-vueを使用しています。

index.js
var mainWindow;

app.on('open-file', (event,path) => {
  event.preventDefault();
  if(mainWindow === void 0) process.openFile = path;
  else mainWindow.webContents.send("Load",path);
});

app.on('ready', () => {
  mainWindow = new BrowserWindow({
    height: 560,
    useContentSize: true,
    width: 680,
    webPreferences: {
      nodeIntegration: true
    }
  })
  mainWindow.loadURL(winURL)
  mainWindow.on('closed', () => {
    mainWindow = null
  })
});
App.vue
<script>
const electron = require('electron');
const { ipcRenderer } = require('electron');
const remote = electron.remote;

export default {
   mounted(){
      //引数でファイル指定があったらそれを開く
      if(remote.process.argv.length > 1) {
        var p = remote.process.argv[1];
        if(p.match(/\.[a-zA-Z]+$/)) this.load(p);
      }

      //Macでファイル指定があったらそれを開く
      if(remote.process.openFile !== void 0) {
        if(remote.process.openFile.match(/\.[a-zA-Z]+$/)) this.load(remote.process.openFile);
      }
      ipcRenderer.on('Load',(event,path) => this.load(path));
   }
}
</script>
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした