Gradle Pluginでresourcesディレクトリからファイルを読み込む

いままではこういう風に書いていたんだけど

public MyPlugin extends Plugin<Project> {
  @Override
  void apply(Project project) {
    URL url = ClassLoader.getResources("resource.file")
    assert url != null // fail
  }
}

返ってくるURLはnullになってしまう。

こう書けばOK

public MyPlugin extends Plugin<Project> {
  @Override
  void apply(Project project) {
    URL url = Thread.currentThread().getContextClassLoader().getResource("resource.file")
    assert url != null
  }
}

ぼくのびるどはにゃあとなくプラグインを作りました

前回「ぼくのびるどはにゃあとなく」というタイトルで、ビルド完了したことを開発者に知らせるテクニックを紹介しました。

ぼくのビルドはにゃあとなく | 明日の鍵
http://tomorrowkey.hatenablog.jp/entry/2014/05/15/000000

なかなか評判がよさそうだったので、導入の敷居を下げるべくGradle Pluginにしてmaven centralにアップロードしました。

ソースコード

tomorrowkey/notifier-plugin
https://github.com/tomorrowkey/notifier-plugin

導入方法

詳しくはGithubのREADMEをご覧ください。

/build.gradle

プロジェクトのルートディレクトリのbuild.gradleにプラグインの参照を追加します。

apply plugin: 'notifier-plugin'

/app/build.gradle

ビルドするモジュールのbuild.gradleにプラグインを適用します。

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'jp.tomorrowkey.gradle.notifier:notifier-plugin:0.0.1'
    }
}

/notifier.groovy

どのような通知を使用するかはnotifier.groovy というファイルをプロジェクトのルートディレクトリに作成してください。 人によって通知方法は異なると思うので、このファイルは.gitignoreに追加すると、個別に設定できていいんじゃないでしょうか。

voice {
    enabled = false
    name = 'Alex'
}
 
notificationCenter {
    enabled = true
}
 
sound {
    enabled = true
    url='file:///Users/tomorrowkey/Desktop/meow.mp3'
}

助かりました

今回初めてGradle Pluginを作りました。 @__gfx__ さんのGradle Plugin Templateを使うことによって爆速で開発できました! ありがとうございます!

gfx/gradle-plugin-template
https://github.com/gfx/gradle-plugin-template

また、今回初めてmaven centralへのアップロードに挑戦しました! Yokomarkさんのこの記事のおかげで爆速でアップロードできました! ありがとうございます!

Java - Android のライブラリプロジェクトを爆速で Maven Central にデプロイする - Qiita
http://qiita.com/KeithYokoma/items/e9ee24e7f6a62623f2fb

ぼくのビルドはにゃあとなく

potatotips7で「ぼくのビルドはにゃあとなく」というタイトルでLTしました。

私以外の発表スライドはこちらから見れます... potatotips 7 · potatotips/potatotips Wiki
https://github.com/potatotips/potatotips/wiki/potatotips-7

http://www.slideshare.net/tomorrowkey/ss-34718053

時間がない人向けに簡単に説明すると

Gradleビルドの完了をフックして、ネコの鳴き声を再生するというデモでした。 これを使えばいつもマルチタスクで忙しいあなたもビルド完了に気づくことができます!

android.applicationVariants.all { variant ->
  if (variant.install != null) {
    variant.install.doLast {
      String url = "http://example.com/meow.mp3";
      String path = "${project.buildDir}/finish_sound"
 
      def file = new File(path)
      if(!file.exists()) {
          new URL(url).withInputStream { input ->
          file.bytes = input.bytes
        }
      }
      
      ['afplay', path].execute()
    }
  }
}

※ネコの鳴き声は別途ダウンロードしてきてください。

ネコの鳴き声が嫌だったらビープ音にすることもできるので、職場でネコの鳴き声が聞こえるなんて恥ずかしい!!って人でも安心です。

ぜひご活用ください。

LOG_TAGを生成するプラグインを作りました

LOG_TAG フィールドを生成するAndroid Studio用のプラグインを作りました。

JetBrains Plugin Repository :: Inject LOG_TAG Plugin
http://plugins.jetbrains.com/plugin/7393?pr=androidstudio

初めて作ったプロダクトが公開されるってとてもテンションあがりますよね!
本当は2週間前には完成していたのですがjetbrains.com への登録や、プラグインの登録や、実際にIntelliJ IDEAから見えるようになるまでの時間などで、作りました!って言えてませんでした。やっと吐き出せた感じです。

目次

LOG_TAGって?

Androidアプリを作っていてログ出力するときにString型のTagを渡す必要があります。
人によって使用する値は違いますが、私はクラスの名前を使用します。

public class User {
 
    // これがLOG_TAG
    private static final String LOG_TAG = User.class.getSimpleName();
 
    private String mName;
 
    private int mAge;
 
    public User(String name, int age) {
        mName = name;
        mAge = age;
    }
 
    @Override
    public String toString() {
        return mName + " is " + mAge;
    }
 
    public void dump() {
 
        // こういう風に使います。
        Log.d(LOG_TAG, "name=" + mName);
        Log.d(LOG_TAG, "age=" + mAge);
    }
}

毎回クラス名を入力するのは面倒なので、クラスの定義のすぐ下にLOG_TAGという定数を定義して、それを使うようにしています。
このプラグインはLOG_TAGを生成するために作りました。

インストール方法

このプラグインはIndelliJ IDEAとAndroid Studioで使用することができます。

PreferenceのPluginsを表示します。

f:id:tomorrowkey:20150425152751p:plain

[Browse repositories...] を押すとJetBrains Plugins Repositoy に登録されているプラグインが表示されます。

f:id:tomorrowkey:20150425154804p:plain

右上の検索ボックスに"LOG_TAG"と入力するとプラグインが表示されます。

f:id:tomorrowkey:20150425152811p:plain

プラグインを選択した状態で左上の"Download and Install Plugin"ボタンを押せばインストールすることができます。

使い方

class内にキャレットを起きます。
f:id:tomorrowkey:20150425152923p:plain

メニューから[Code] > [Generate] を選択します。キーマップがMac OS X 10.05+であればショートカットはCommand+Nです。 f:id:tomorrowkey:20150425152943p:plain

[Inject LOG-TAG]を選択します。 f:id:tomorrowkey:20150425153001p:plain

コードが自動的に生成されます。 f:id:tomorrowkey:20150425153019p:plain

自動的にインデントしてくれませんが、その辺はフォーマッタに任せます。

ソースコード

ソースコードGitHubに公開しました。

tomorrowkey/InjectLogTagPlugin
https://github.com/tomorrowkey/InjectLogTagPlugin

バグ報告や追加機能の提案はこちらにお願いします。
Issues · tomorrowkey/InjectLogTagPlugin
https://github.com/tomorrowkey/InjectLogTagPlugin/issues

Plugin SDKにソースコードをアタッチする

プラグインを作るための環境構築を紹介したページにはIntelliJソースコードSDKにアタッチするという項目があります。

Check out the sources of IntelliJ IDEA Community Edition as described in Check Out & Build Community Edition

In the Sourcepath tab of the SDK settings, press the "Add..." button and specify the directory > into which you have checked out the sources of the Community Edition

Android StudioSDKに設定した場合は、Android Studioソースコードを参照したいので、その方法を調べました。

ソースコードを参照してみる

ソースコードをアタッチしていない状態でソースコードを参照してみます。

このプロジェクトは前回作ったサンプルコードです。

f:id:tomorrowkey:20150425115147p:plain

Notifications.Bus.notify()の実装がどうなっているのか参照してみましょう。
notify()と書かれたところにキャレットを合わせた状態で、

[右クリック] > [Go to] > [Declaration (Command+B)]

を選択します。

f:id:tomorrowkey:20150425114928p:plain

Notificationsクラスが表示されましたが、インターフェイスのみで実装は見ることはできません。(デコンパイラをインストールしていたら見れるかもしれません)
今回のゴールは、この実装が見れるようになることです。

Android Studioソースコードのダウンロード

SDKにアタッチするためのソースコードをダウンロードします。
Android Studioソースコードはここで見ることができます。

platform/tools/idea - Git at Google
https://android.googlesource.com/platform/tools/idea/

以下のコマンドを実行することによりソースコードをダウンロードできます。

git clone https://android.googlesource.com/platform/tools/idea

そんなに大きくないので5分ほどあればダウンロード完了します。

ソースコードをアタッチする

プラグイン開発に使用するIntelliJを起動します。

f:id:tomorrowkey:20150425115022p:plain

このような画面になっていると思います。
プロジェクトが開かれている場合は[File] > [Close Project]をしてこの画面を表示してください。

Project Structureを開きます。

[Configure] > [Project Defaults] > [Project Structure]

IDEA AI-133.988757 を選択している状態で、[Edit...]ボタンを押します。

f:id:tomorrowkey:20150425115042p:plain

[Sourcepath]を選択すると以下のような画面になります。

f:id:tomorrowkey:20150425115234p:plain

[+]ボタンを押した後に、先程ダウンロードしたAndroid Studioソースコードの場所を指定します。
これで設定完了です。

ソースコードを参照する

最初と同じようにNotifications.Bus.notify() の実装を見てみましょう。

f:id:tomorrowkey:20150425115127p:plain

無事実装を見ることができました。

IntelliJ Pluginの実行でAndroid Studioを起動する方法

Android Studio向けにプラグインを作ろうと思いますが、IntelliJプラグインを作り実行するとIntelliJが起動してしまいます。
Android StudioIntelliJをベースに作られたIDEですが、意外と互換性のない部分もあり、Android Studio向けにプラグインを作るのであれば、実行されるのはAndroid Studioであった方が嬉しいですよね。
今回はどうやったらPluginをAndroid Studioで起動することができるか調べてみました。

※普通のIntelliJ Pluginの作り方はこちら

目次

SDKの追加

Project Structureを表示します。

f:id:tomorrowkey:20150425113712p:plain

IntelliJ Plugin開発をしたことがあるのであれば、このようになっていると思います。
IDEA IC-133.696 はIntelliJ用のSDKなので、Android Studio用のSDKを追加します。
[New...] > [IntelliJ Platform Plugin SDK]を選択します。
IntelliJ Pluginを作る場合はIntelliJのアプリケーションを選択しましたが、Android Studio Pluginを作るときにはAndroid Studioのアプリケーションを選択します。
OSXであれば/Applications/Android Studio.app です。

するとJavaのバージョンを選択するダイアログが表示されます。

f:id:tomorrowkey:20150425113906p:plain

ここでは必ず1.6を選択してください。
Java 1.7(つまりJava7)でコンパイルしたプラグインAndroid Studioでは使えません。
以下の様なエラーが発生します。

Unsupported major.minor version 51.0 · Issue #2 · ligi/GradleDependenciesHelperPlugin
https://github.com/ligi/GradleDependenciesHelperPlugin/issues/2

OKボタンを押すと無事SDKが追加されます。

f:id:tomorrowkey:20150425114219p:plain

IDEA IA~ というSDKが追加されていればOKです。

プロジェクトの作成

プロジェクト作成時には、Android Studio用のSDKを選択します。

f:id:tomorrowkey:20150425114300p:plain

プラグインの作成

適当にプラグインを作ります。

f:id:tomorrowkey:20150425114404p:plain

実行設定

IntelliJ Pluginを作る時と同様に新しい実行設定を作成します。
ここでAndroid Studioが起動するように実行オプションを追記します。

f:id:tomorrowkey:20150425114448p:plain

"VM Options" に以下の新しいオプションを追加します。

-Didea.platform.prefix=AndroidStudio

これを忘れると何食わぬ顔でIntelliJが起動するので注意しましょう。

実行

準備は整ったので実行します。

f:id:tomorrowkey:20150425114527p:plain

無事Android Studioが起動し、プラグインも正常に動作しました。

IntelliJ IDEA Pluginの作り方

IntelliJ PluginのHello, World.ということで、Hello Pluginというプラグインを作ってみましょう。
ボタンを押すとHello!というNotificationが表示されるプラグインです。

目次

  • IntelliJ IDEAのダウンロード
  • SDKの設定
  • プロジェクトの作成
  • Actionの作成
  • Notificationの表示
  • 実行設定
  • プラグインの実行
  • Tips

IntelliJ IDEAのダウンロード

Android StudioIntelliJ IDEAをベースとしたIDEです。
Android Studioではプラグインを作ることができないので、IntelliJ IDEAを使います。

使用するIntelliJのライセンス形態は以下のリンクが詳しいです。

IntelliJ IDEA製品群、ライセンス形態について #jbugj
http://www.slideshare.net/yusukey/intellij-idea-jbugj

03日目 IntelliJの購入方法 #intellij - marsのメモ
http://d.hatena.ne.jp/masanobuimai/20121203

プラグインの開発はIntelliJ IDEA Community Editionでも可能です。 ダウンロードサイトはこちらです。

IntelliJ IDEA :: Download Latest Version of IntelliJ IDEA
http://www.jetbrains.com/idea/download/index.html

今回は以下のバージョンを使います。
IntelliJ IDEA 13.0.2 Build #IC 133.696

インストールは特に迷うことなくすんなりできると思います。

SDKの設定

インストールが完了し、初めて起動するとこのような画面が表示されます。
f:id:tomorrowkey:20150425110937p:plain

まずはSDKの設定を行います。
[Configure] > [Project Defaults] > [Project Structure] を開くとSDK設定画面になります。

f:id:tomorrowkey:20150425110956p:plain

Project SDKがNo SDKとなっているので、[New...] > [IntelliJ Platform Plugin SDK]を選択して新しくSDKを設定します。
ファインダーが表示さるので、"IntelliJ IDEA 13 CE.app"を選択します。

f:id:tomorrowkey:20150425111014p:plain

SDKの設定が完了しました。

プロジェクトの作成

f:id:tomorrowkey:20150425111034p:plain

早速[Create New Project]からプラグインプロジェクトを作成しましょう。

f:id:tomorrowkey:20150425111049p:plain

1つずつ入力していきましょう。
プラグインを作るのでプロジェクトの種類は"IntelliJ Platform Plugin"を選択します。
Project nameには"HelloPlugin"と入力します。
Project locationはプロジェクトを置いておきたい適当な場所を指定しましょう。
Project SDKには先ほど設定したSDKを指定します。

f:id:tomorrowkey:20150425111118p:plain

[Finish]を押すとプロジェクトが作成されます。

f:id:tomorrowkey:20150425111135p:plain

Actionの作成

プラグインのエントリポイントはActionです。とりあえずActionを作成しましょう。 /HelloPlugin/src ディレクトリを選択した状態で[File] > [New...] > [Action] を選択します。

f:id:tomorrowkey:20150425111154p:plain

たくさんの入力項目が表示されました。
1つずつ埋めていきましょう。

f:id:tomorrowkey:20150425111219p:plain

Action IDプラグインを一意に識別できる値を入力します。"HelloPluginAction"と入力します。
Class Name にはActionクラスを継承したクラスの名前を入力します。パッケージ名+クラス名(例えばcom.example.HelloPluginActionなど)と入力したいところですが、そう入力するとOKボタンを押せないのでパッケージ名は省略して"HelloPluginAction"と入力します。あとでこの値は変更できます。
Name にはActionの名前を入力します。"Hello Plugin"と入力します。
Groups は"Tools Menu"を選択します。これを選択するとToolsメニューに"Hello Plugin"という項目が追加されます。
このアクションはメニューから起動することができますが、Keyboard Shortcutsでショートカットを設定することにより、簡単に起動することができます。"Command + Shift + H"を設定しました。

f:id:tomorrowkey:20150425111256p:plain

アクションが作成されました。

Notificationの表示

ユーザがPluginの機能を呼び出すと、ActionクラスのactionPerformedメソッドが呼ばれます。
Hello PluginはActionが呼ばれるとNotificationが表示されるプラグインなので、ここにNotificationを表示するコードを書きましょう。

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 HelloPluginAction extends AnAction {
    public void actionPerformed(AnActionEvent e) {
        String groupDisplayId = "HelloPlugin";
        String title = "Hello";
        String content =  "Hello World!";
        NotificationType notificationType = NotificationType.INFORMATION;
 
        Notification notification = new Notification(groupDisplayId, title, content, notificationType);
        Notifications.Bus.notify(notification);
    }
}

Notificationオブジェクトを作成し、Notifications.Bus#notify()を呼び出すことでNotificationが表示されます。 これでHello Pluginの完成です。

実行設定

プラグインを実行するには[Run] > [Run...] > [Edit Configurations...] を選択し、実行の設定をします。

f:id:tomorrowkey:20150425111515p:plain

左上の[+] > [Plugin]を選択して新しく実行設定を作成します。

f:id:tomorrowkey:20150425111531p:plain

Nameに実行設定の名前を入力します。
Use classpath of moduleにHelloPluginが選択されていることを確認します。

f:id:tomorrowkey:20150425111554p:plain

これで実行設定が完了しました。
早速実行してみましょう。

プラグインの実行

[Run]から先ほど作成した設定を選択するとプラグインが実行されます。
いままで使っていたIntelliJとは別の新しいIntelliJが起動します。

f:id:tomorrowkey:20150425111626p:plain

プラグインの動作確認するにはプロジェクトが必要なので、適当なプロジェクトを開きます。

プロジェクトを開いた状態でおもむろにメニューのToolsを開くと"Hello Plugin"というメニューがあります。
どうやらインストールには成功しているようです。

f:id:tomorrowkey:20150425111650p:plain

"Hello Plugin"を選択するとノーティフィケーションが表示されました。
表示されている内容はtitleとcontentです。

f:id:tomorrowkey:20150425111705p:plain

さらにショートカットから呼び出しもやってみましょう。
Actionを作るときに指定した"Command + Shift + H"を押してみますが、ノーティフィケーションは表示されません。
もう一度メニューを見てみるとショートカットの表示が"Shift + Ctrl + H"になっています。(バグか?)
改めて"Shift + Ctrl + H"を押すと無事ノーティフィケーションが表示されます。

Tips

プラグインの名前を設定する

[Preferences] > [Plugins]を開くとプラグイン一覧が表示されます。

f:id:tomorrowkey:20150425111723p:plain

さっき作ったプラグインはというと"Plugin display name here"という名前になっています。
プラグインの名前は別で設定する必要がありそうです。

/META-INF/plugin.xml というファイルを開くとプラグインの名前などを設定できます。

<idea-plugin version="2">
  <id>com.yourcompany.unique.plugin.id</id>
  <name>Plugin display name here</name>
  <version>1.0</version>
  <vendor email="support@yourcompany.com" url="http://www.yourcompany.com">YourCompany</vendor>
 
  <description><![CDATA[
      Enter short description for your plugin here.<br>
      <em>most HTML tags may be used</em>
    ]]></description>
 
  <change-notes><![CDATA[
      Add change notes here.<br>
      <em>most HTML tags may be used</em>
    ]]>
  </change-notes>
 
  ...
 
</idea>

nameタグにプラグインの名前を設定します。
venderタグやdescriptionタグなども適切な文言を設定するとよいでしょう。

Actionのパッケージを変更する

さきほど作ったHello Pluginではデフォルトパッケージを使っていました。
そのままでは気持ち悪いので、適当なパッケージに変更してみます。 名前を設定したときと同じく/META-INF/plugin.xmlを開きます。

<idea-plugin version="2"> 
  ...
 
  <actions>
    <!-- Add your actions here -->
      <action id="HelloPluginAction" class="HelloPluginAction" text="Hello Plugin">
          <add-to-group group-id="ToolsMenu" anchor="first"/>
          <keyboard-shortcut keymap="$default" first-keystroke="shift meta H"/>
      </action>
  </actions>
 
</idea-plugin>

actionタグのclass属性に実行するアクション名が指定されています。
クラスのパッケージを変更して、この値を変更すればよさそうです。

ショートカットを変更する

これもまた同じく/META-INF/plugin.xmlに設定があります。

<idea-plugin version="2"> 
  ...
 
  <actions>
    <!-- Add your actions here -->
      <action id="HelloPluginAction" class="HelloPluginAction" text="Hello Plugin">
          <add-to-group group-id="ToolsMenu" anchor="first"/>
          <keyboard-shortcut keymap="$default" first-keystroke="shift meta H"/>
      </action>
  </actions>
 
</idea-plugin>

keyboard-shortcutタグのfirst-keystroke属性を変更すればショートカットを変更できます。

参考にしたリンク

PluginDevelopment - IntelliJ IDEA - Confluence
http://confluence.jetbrains.com/display/IDEADEV/PluginDevelopment

IntelliJ IDEA: GoogleSearch Plugin for IntelliJ IDEA
http://www.jetbrains.com/idea/training/demos/google_search.html

IntelliJ IDEAのプラグイン開発 - North Ground
http://kxbmap.hatenablog.com/entry/20111102/1320169073

ツイートするIntelliJプラグインを作ったよ - ギークに憧れて
http://hotchemi.hateblo.jp/entry/2013/01/07/013344

IntelliJ IDEAのプラグインを作ろう! - Qiita
http://qiita.com/Vexus2/items/e04a21f00e467b7ac8ad