初めてのAndroid Studioプラグイン開発入門

2014年末に、[Android Material Design Icon Generator](https://github.com/konifar/android-material-design-icon-generator-plugin)というAndroidStudioのプラグインを初めて作ってみました。

![Material_Icon_Generator.png](https://qiita-image-store.s3.amazonaws.com/0/15267/51e57827-b824-b938-718d-e058efd8aa09.png "Material_Icon_Generator.png")

Googleの公開してる[material design icons](https://github.com/google/material-design-icons)のアイコンを簡単にリソースに配置できるだけのプラグインなのですが、プラグイン開発の流れは掴めたので手順を残しておきます。

Android StudioはIntelliJをベースにしているので、[IntelliJ IDEAのプラグインを作ろう！](http://qiita.com/Vexus2/items/e04a21f00e467b7ac8ad)がとても参考になりました。


#InteliJをインストール
Android Studioにはプラグイン開発用のプロジェクト作成メニューがありません（2014/01/10時点）。なので、開発にはIntelliJをインストールする必要があります。
[ダウンロードページ](https://www.jetbrains.com/idea/download/index.html)からダウンロードしてインストールしましょう。無償版のCommunity Edition FREEでも問題ないです。

#プロジェクトを作成
インストールが完了したらIntelliJを起動します。
Create New Projectをクリックします。

![Welcome_to_IntelliJ_IDEA.png](https://qiita-image-store.s3.amazonaws.com/0/15267/62134025-f20c-7477-8105-66596abb43a3.png "Welcome_to_IntelliJ_IDEA.png")

`IntelliJ Platform Plugin`を選択します。

![New_Project.png](https://qiita-image-store.s3.amazonaws.com/0/15267/b7d7a251-3d81-ceac-3782-e774022f1fbe.png "New_Project.png")

ここで気をつけなければならないのは、 **Project SDK** のバージョンです。Android StudioをJava1.6で動かしている場合もあるので、ここでJava1.7以上を選択してしまうと完成後にいざAndroid Studioにインストールしたらクラッシュするという悲しいことになります。

Java1.7以上になっている場合は、右側の`New`からJava1.6を選択してください。Macであれば、おそらく`/System/Library/Java/JavaVirtualMachines/1.6.0.jdk`にインストールされていると思います。もしなければインストールしましょう。
完了したらNextをクリックします。

![New_Project.png](https://qiita-image-store.s3.amazonaws.com/0/15267/ffee56a9-ddf8-559c-aeac-0c6862149b0b.png "New_Project.png")

プロジェクト名と保存場所を入力します。個人的には、後で変更するの面倒なので最初からちゃんと考えてつけたほうがいいと思います。

![New_Project.png](https://qiita-image-store.s3.amazonaws.com/0/15267/ab545c2a-220d-6edd-4cf7-50dcfa2ed19b.png "New_Project.png")

Finishをクリックすれば、プロジェクト作成完了です。

#plugin.xmlを編集
まずは`plugin.xml`を変更しましょう。これは`AndroidManifest.xml`のようなもので、Actionを定義したり、プラグインをインストールするときの説明文を記述したりするのに使います。

例えばこんな感じで記述すると

```plugin.xml
<idea-plugin version="2">
    <!-- 一意なid。パッケージと同じにしておけば問題ないです。 -->
    <id>com.konifar.material_icon_generator</id>
    <!-- ①名前 -->
    <name>Android Material Design Icon Generator</name>
    <!-- ②バージョン -->
    <version>1.0</version>
    <!-- ③連絡先メールアドレス、④サイトURL、⑤ベンダー名 -->
    <vendor email="yahpeycoy0403@gmail.com" url="https://github.com/konifar/android-material-design-icon-generator-plugin">Android Material Design Icon Generator</vendor>
    <!-- ⑥説明 -->
    <description><![CDATA[
      Android Studio & IntelliJ Plugin for Material Design Icon.<br> This plugin help you to set material design icon in your app resources.
      ]]></description>
    <!-- ⑦Change notes -->
    <change-notes><![CDATA[
      First version released.
    ]]>
    </change-notes>
    ...
</idea-plugin>
```

インストールする画面こんな感じになります。

![Browse_Repositories.png](https://qiita-image-store.s3.amazonaws.com/0/15267/eb5eb06e-567e-dbb6-9dea-dc52bbc8f333.png "Browse_Repositories.png")

後からでも編集できますが、どういうプラグインを作るのか明確にするためにも先に書いておく方がいいかなと思います。

#Actionを作成
プラグインは、何かのアクションごとに開発します。例えば、コードのGenerateメニューを開いた時、ツールバーのアイコンをクリックした時といった具合です。
自分の場合は、FileのNewメニューを開いた時にMaterialDesignIconを作成するメニューを増やしたかったので、そのためのアクションを作りました。

![FilterComboBox_java_-__MaterialDesignIconGeneratorPlugin__-_HelloPlugin_-____IdeaProjects_HelloPlugin_.png](https://qiita-image-store.s3.amazonaws.com/0/15267/9f587ea9-d2ed-eda5-9472-09834aa54b22.png "FilterComboBox_java_-__MaterialDesignIconGeneratorPlugin__-_HelloPlugin_-____IdeaProjects_HelloPlugin_.png")


例として、これと同じアクションの作成手順を説明します。

まず`File > New > Action`をクリックします。

![FilterComboBox_java_-__MaterialDesignIconGeneratorPlugin__-_HelloPlugin_-____IdeaProjects_HelloPlugin_.png](https://qiita-image-store.s3.amazonaws.com/0/15267/7d09e9de-54fe-68e0-f863-2152bf6c022d.png "FilterComboBox_java_-__MaterialDesignIconGeneratorPlugin__-_HelloPlugin_-____IdeaProjects_HelloPlugin_.png")


入力フォームが現れるので入力していきます。

![New_Action.png](https://qiita-image-store.s3.amazonaws.com/0/15267/61d1c859-2382-3c58-e54f-f493c18d1326.png "New_Action.png")

各項目についてざっくり説明します。

| 項目 | 説明 |
|:-----------|:------------|
| Action ID | Actionごとに一意なIDです。一意であれば何でも大丈夫ですが、アクションの内容がわかりやすいIDにしておくのがよいです。 |
| Class Name | 作成するクラス名です。実はこの段階では`com.konifar.Hoge`のようにパッケージ名を指定することはできません。ルートに作られるので、パッケージは後で変更しましょう。 |
| Name | 名前です。`plugin.xml`に自動記述された時にわかりやすいように名前をつけておきましょう。 |
| Description | 説明です。後で見てわかるように簡単に説明を書いておきましょう。と言っても、正直小さなプラグインであればそこまで神経質にならなくてもいいと思います。 |
| Groups | **ここがキモです。** プラグインのアクションの起点となるグループです。例えば、ツールバーの`Build`メニューに何か加えたいのであれば`BuildMenu(Build)`、Newのグループに何か加えたいのであれば`NewGroup(New)`を選択します。どのGroupsがAndroidStudio内のどの部分なのかという情報は一応[ここ](http://keithlea.com/idea-actions/)にあります。ただ詳しくまとまってはいないので、[IntelliJ IDEA Plugin Development](https://confluence.jetbrains.com/display/IDEADEV/PluginDevelopment)のページを色々探して決めるしかなさそうです。。。僕も[このスレッド](https://devnet.jetbrains.com/thread/247161)を見て発見しました。または、同じようなアクションのプラグインのコードが公開されていればそれを参考にするのがよいです。 |
| Actions | 選択したGroupsの中でさらに小項目を指定したい場合はActionを選択します。自分の場合はGroupsだけの指定でよかったのでここは選択しませんでした。 |
| Anchor | メニューの並び順です。新しく作るアクションを一番下に表示するか、一番上に表示するかを決めます。Lastにすると一番下に表示されます。![FilterComboBox_java_-__MaterialDesignIconGeneratorPlugin__-_HelloPlugin_-____IdeaProjects_HelloPlugin_.png](https://qiita-image-store.s3.amazonaws.com/0/15267/9f587ea9-d2ed-eda5-9472-09834aa54b22.png "FilterComboBox_java_-__MaterialDesignIconGeneratorPlugin__-_HelloPlugin_-____IdeaProjects_HelloPlugin_.png") |
| Keyboard Shortcuts | 2つまでショートカットキーを設定できます。後でも編集できますので、とりあえず設定しなくていいかもしれません。 |

入力したら、OKボタンを押すと作成されます。
作成すると、`plugin.xml`に自動記述されます。

```plugin.xml
    <actions>
        <!-- Add your actions here -->
        <action id="MaterialDesignIconGenerateAction"
                class="MaterialDesignIconGenerateAction"
                text="Material design icon" description="Material design icon">
            <add-to-group group-id="NewGroup" anchor="last"/>
            <keyboard-shortcut keymap="$default" first-keystroke="ctrl alt M"/>
        </action>
    </actions>
```

Groupにもよりますが、アイコンを設定したい場合は`<action>`に`icon`属性を追加します。

```plugin.xml
<action id="MaterialDesignIconGenerateAction"
    class="MaterialDesignIconGenerateAction"
    text="Material design icon"
    description="Material design icon"
    icon="/resources/menu_icon.png"> 
    <!-- ↑これ。iconはsrc/resource/menu_icon.pngを配置しておきます。 -->
    ...
</action>
```

#Actionクラスに処理を記述
Actionを実行した時の処理はプラグインによって違って何とも言いづらいので、簡単に概要とトラブルシューティングを書いておきます。

###Actionクラスの実装
基本は、Actionクラスの`actionPerformed`メソッドを実装するだけです。

```java
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;

public class MaterialDesignIconGenerateAction extends AnAction {

    /**
     * @param event Action event
     */
    public void actionPerformed(AnActionEvent event) {
        // ここに処理を書く。以下はHelloWorldのNotificationを出すコード
        Notifications.Bus.notify(
        new Notification("group", "Hello World Title", "Hello World Content", NotificationType.INFORMATION));
    }

}
```

上のコードでアクションを実行すると、右上にNotificationが出ます。

![MainActivity_java_-__app__-_MyApplication_-____IdeaProjects_MyApplication_.png](https://qiita-image-store.s3.amazonaws.com/0/15267/69826dec-d719-0d38-9e58-035fce465502.png "MainActivity_java_-__app__-_MyApplication_-____IdeaProjects_MyApplication_.png")

###ダイアログなど画面を作りたい場合
swingのコンポーネントで実装します。なので、調べる時はswingについて調べた方がたくさん情報が出てくるかもしれません。
または、自分が作りたいものと似たプラグインのコードを探して参考にするのも有効です。自分は[android-holo-colors-idea-plugin](https://github.com/jeromevdl/android-holo-colors-idea-plugin)のダイアログ部分をかなり参考にしながら作りました。

あとはStackOverFlowですね。。。下記は調べて解決しました。

* [JLabelを使って画像を表示する](http://www.javadrive.jp/tutorial/jlabel/index6.html)
* [JComboBoxから選択中の項目を取得する](http://stackoverflow.com/questions/15928314/obtain-currently-highlighted-item-from-jcombobox-popup-not-selected-item)
* [JLabelをリンクテキストにする](http://www.dzone.com/snippets/jlabel-link-open-browser-form)
* [jarにした時にプロジェクト内のxmlファイルを読み込めない問題の対処](http://stackoverflow.com/questions/14089146/file-loading-by-getclass-getresource)


その他、参考になる情報は[IntelliJ IDEAプラグインの開発 - 有用な情報とリンク集](http://d.hatena.ne.jp/fuzzhead/20120729/p1)に詳しくまとまっていますので参考にどうぞ。

###参考になるかもしれないプラグインのGithubリポジトリ
もしかしたら参考になるかもしれないプラグインのリポジトリです。プラグイン名で検索すればもっと出てくると思います。

####エディタのUtility
* [otto-intellij-plugin](https://github.com/square/otto-intellij-plugin)
* [dagger-intellij-plugin](https://github.com/square/dagger-intellij-plugin)

####コードジェネレータ
* [android-parcelable-intellij-plugin](https://github.com/mcharmas/android-parcelable-intellij-plugin)
* [android-sqlite-model-generator-plugin](https://github.com/sromku/android-sqlite-model-generator-plugin)

####ダイアログ、ファイルダウンロード、ローカルファイル読み込み
* [android-holo-colors-idea-plugin](https://github.com/jeromevdl/android-holo-colors-idea-plugin)
* [Android Material Design Icon Generator](https://github.com/konifar/android-material-design-icon-generator-plugin)

###プラグインの実行
Actionを実装しながら、プラグインを実行して動作を確認します。やり方は普通のプロジェクトの実行とほとんど変わらないです。
実行ボタンを押すと、プラグインがインストールされた別のIntelliJが立ち上がるので、実際に動かして確認します。

![MaterialDesignIconGenerateDialog_java_-__MaterialDesignIconGeneratorPlugin__-_HelloPlugin_-____IdeaProjects_HelloPlugin__と_IntelliJ_IDEAのプラグインを作ろう！_-_Qiita.png](https://qiita-image-store.s3.amazonaws.com/0/15267/30f8f3f3-a9d8-0b1c-f889-64ca6e04bbc8.png "MaterialDesignIconGenerateDialog_java_-__MaterialDesignIconGeneratorPlugin__-_HelloPlugin_-____IdeaProjects_HelloPlugin__と_IntelliJ_IDEAのプラグインを作ろう！_-_Qiita.png")

#プラグインの公開
ローカルで実装が完成したら、他の人もインストールできるように公開の準備をします。

###jarの作成
作成したプラグインをjarにします。
`Build > Prepare Plugin Module ~`をクリックすると、プロジェクトルートにjarが作成されます。

![Build.png](https://qiita-image-store.s3.amazonaws.com/0/15267/c98521a2-eeed-622c-3c98-689f9d3f23aa.png "Build.png")

jarにした後、念のため`Preference > Plugins > Install plugin from disk...`からインストールして正常に動作するか確かめておいた方がいいと思います。

![Preferences.png](https://qiita-image-store.s3.amazonaws.com/0/15267/32ae486d-cf29-ac0b-45ee-2335f7a8caaa.png)

###JetBrains Accountの作成
公開するにはJetBrains Accountが必要なので、[こちら](https://account.jetbrains.com/login)からSignUpしましょう。

###プラグインのアップロード
アカウントが作成できたら、[IntelliJ Plugin Repository](https://plugins.jetbrains.com/)を開いて右上の`Add new plugin`をクリックします。ログインしていなければログインしておいてください。

![JetBrains_Plugin_Repository.png](https://qiita-image-store.s3.amazonaws.com/0/15267/b0bb98ac-53ac-1f0a-97d0-333d5be41ace.png "JetBrains_Plugin_Repository.png")

カテゴリを選んで、先ほど作ったjarを選択し、`Upload new plugin`をクリックします。

![JetBrains_Plugin_Repository.png](https://qiita-image-store.s3.amazonaws.com/0/15267/2a387183-188c-22e8-7c41-bc0153b09c26.png "JetBrains_Plugin_Repository.png")

ここで選んだカテゴリは、プラグインのリポジトリに表示されます。

![Browse_Repositories.png](https://qiita-image-store.s3.amazonaws.com/0/15267/6e20bc02-57d7-61b0-6d9d-a477649f4530.png "Browse_Repositories.png")

###プラグインの情報を入力
jarのアップロードが完了すると、情報を入力するフォームが開きます。基本情報は`plugin.xml`に書いてあるのですが、ライセンスやコードのURLを明記しておきます。

![JetBrains_Plugin_Repository.png](https://qiita-image-store.s3.amazonaws.com/0/15267/31b694d1-5469-dbc2-a5ce-1e349f6bf4c7.png "JetBrains_Plugin_Repository.png")

ライセンスは、GithubリポジトリのReadMeに記述しておくのが一番楽だと思います。
Download URLはGithubリポジトリのURLでいいはずです。Issueをうまく使うなら、Forumの項目にはIssueのURLを書いておいてもいいかもしれません。

入力できたらSaveをクリックすればOKです。

###承認を待つ
マイページを開くと、アップロードしたプラグインが表示されているはずです。

![JetBrains_Plugin_Repository.png](https://qiita-image-store.s3.amazonaws.com/0/15267/b2d1811d-5d75-3db5-8792-feca394f9c3a.png "JetBrains_Plugin_Repository.png")

中を見てみると、ステータスが`Wait for approve`になっていると思います。

![JetBrains_Plugin_Repository____Android_Material_Design_Icon_Generator.png](https://qiita-image-store.s3.amazonaws.com/0/15267/07f25eac-3265-1cb0-8015-cfe1c2491b33.png "JetBrains_Plugin_Repository____Android_Material_Design_Icon_Generator.png")


JetBrainsの中の人が承認してくれるのを気長に待ちましょう。自分は年末2014/12/31に提出したからか、承認されるのに10日くらいかかりましたが、2〜3日で承認されるのが一般的みたいです。

内容を編集したい時は、`Update plugin`から変更できます。
承認されるとこんな感じになります。

![JetBrains_Plugin_Repository____Android_Material_Design_Icon_Generator.png](https://qiita-image-store.s3.amazonaws.com/0/15267/a1949a1a-f665-656a-1bbc-65ba16fac444.png "JetBrains_Plugin_Repository____Android_Material_Design_Icon_Generator.png")

#まとめ
プラグイン作成は思っているよりハードルは高くないです。ただ、情報が散らばっているのでハマった時に調べるのが少し面倒です。この辺はJetBrainsの公式ページがもう少し頑張ってほしいところです。。。

自分が欲しいプラグイン作るとAndroid Studioがより便利になって楽しいので、興味があれば試してみてください。何かあれば[@konifar](https://twitter.com/konifar)まで連絡をもらえれば、アドバイスできるかもしれないのでお気軽にどうぞ！