Android Studio (IntelliJ IDEA) の Language Injection

Android Studio (およびそのベースとなっているIntelliJ IDEA)にはLanguage Injection というおもしろ機能があります。I/Oのセッションでも簡単に説明していた正規表現チェックの例を使ってみます。

まず、以下は(Javaのリファレンスにも載っているような)非常に簡単な正規表現チェックコードの例です。aが0回以上とbという文字列が含まれるかどうかチェックしています。

正規表現コード例
正規表現コード例

ここで正規表現(“a*b”)にカーソルを合わせて、Alt+Returnでポップアップメニューを表示し、Inject Language を選択……

Inject Language
Inject Language

さらにどんな言語の機能を差し込むのか選択が出るので、Regular Expression(正規表現)を選択します。

Inject RegExp
Inject RegExp

これで準備完了です。再度 Alt+Returnでポップアップメニューを呼び出すと、正規表現チェックのメニューが増えているかと思いますので、それを選択肢ます。

Check RegExp
Check RegExp

すると、正規表現をチェックするダイアログのようなものが表示されます。

正規表現チェッカ登場
正規表現チェッカ登場

ではここに正規表現とマッチしない文字列を入れてみます。

正規表現がマッチしなければ赤
正規表現がマッチしなければ赤

マッチしないので赤表示となります。次にマッチする文字列を入れます。

正規表現がマッチすれば緑
正規表現がマッチすれば緑

マッチするので緑に変わりました。

ということで、プログラム開発中に、テストを動かすまでも無く簡易に正規表現が意図通りに動作するものとなっているかを確認することができます。 (( ちゃんとテストコードも書くべきなのは当然です。 ))

もうここではこのLanguage Injectionを使わないぞと思ったら、取り除くこともできます。

不要になったらun-inject
不要になったらun-inject

ちょっとした機能ではありますが、これも開発効率アップに貢献してくれる機能の一つです。

Android Studio Tips

Google I/O 2013において、Androidの新しい開発環境である Android Studio が発表されました。これまでのEclipseを用いた環境からガラリと一新し、JetBrainsIntellIJ IDEA Community Editionをベースにしたものとなりました。

弊社ではすでにアプリ開発においてIntelliJ IDEA(の有償版であるUltimate Edition)を活用しており、非常に強力なコード開発補助機能に助けられています。Androidアプリ開発用に無償で公開されたAndroid Studioにおいても、その強力な支援機能は健在です。

Android Studio は現在バージョン0.1のEarly Access Preview版として公開されています。まだ正式版では無いためバグなども潜在しているものと思われます。しかし、正式版が公開された後のどこかでおそらくEclipse用のプラグインの提供も終了し、最新の開発環境はAndroid Studioに絞られるのではないかと予想されますので、出来るだけ今のうちからどういったものか知っておくことが望ましいでしょう。 ((しばらくはAndroid StudioとADTは並行して提供されるという噂あり))

インストール手順などについては、TechBoosterHow to Install “Android Studio” for Mac OSなど多数のサイトで紹介されていますので、本記事ではインストール手順などについては参照することにとどめ、Android Studioを使う上でのいくつかのTipsを、IntelliJ IDEA利用の経験から示したいと思います。

コード補完 (Java編)

IDEA系のIDEの強さの一つはなんといっても強力なコード補完です。たとえば、Androidアプリを書く際によく使用する例として getSystemService() を入力する場合の補完例を以下に示します。

completion8

“gSySer” という入力で、getSystemService() が補完候補として提示されています。メソッドに含まれる単語の頭一文字を入力して補完候補を出すCamelCase補完という機能を持っているIDEは多いですが、Android Studioの補完はそれよりも柔軟に対応してくれます。この例では、”System”を飛ばして “gSer” と入力した場合でも getSystemService()が補完候補として提示されます。

ただし、補完候補の提示には若干のクセがありますので、出てほしいものが出てきてくれない場合があります。たとえば、アプリケーションを新規作成した状態で、SharedPreferences の変数を宣言しようとした場合、以下のような状態なります。

completion3

“SharedPreferences” のすべてを入力しているにも関わらず、補完候補として現れてくれません。Android Studioの補完はSmart Completionという少し頭のいい補完をしてくれるのですが、たまに間違った推論が行われてしまう場合があるようです。

completion4

CamelCase入力でも同様です。

このような推論ズレが発生している場合、Ctrl+スペースを入力することで、Basic Completionによる補完候補の提示が行われますので、補完候補が出てくれないなという時には Ctrl-スペースで補完方法を切り替えてみましょう。ちなみに、キーバインドをEmacsライクに変更している場合は、Ctrl-スペースではなく Alt+/ となります。

completion7

一度補完が働き、コードの中でその型が使用されていれば、次回以降はSmart Completionでも適切に候補として提示されます。

completion6

completion5

コード入力支援 (Java編)

Android Studio はコード補完以外の入力支援も強力です。たとえば、以下はメソッド呼び出しで戻り値がある場合に、その戻り値を格納するローカル変数の作成の支援の例です。支援が可能な箇所(や、エラーがある箇所)では、Alt+Return を入力すると、適切な支援作業がポップアップで提示してくれます。

introduce_local_var1

変数の宣言と代入を”Introduce local variable” のポップアップから選択すると……

introduce_local_var2

このように変数宣言が追加されます。変数名の候補も、メソッド名などからの類推で自動的に提示されたりもします。

また、メソッドの引数が抜けている場合、その位置にカーソルを移動して Ctrl-P で何を引数として設定すれば良いかをポップアップで教えてくれます。

method_parameters1

上記の例では第二引数に@MagicConstant というアノテーションがついています。このアノテーションにより、第二引数を入力する時にCtrl-スペースで補完候補を表示すると、このメソッドの第二引数として利用してよい定数に絞りこまれた候補が一覧されます。

method_parameters2

Java8っぽいコード表示

Androidアプリ開発において、現時点では Java6相当(+α)の機能しか使用することができません。たとえば、ボタンクリック時のハンドラはリスナオブジェクトを生成して、そのオブジェクトを引数で渡すという方法で登録します。

callback_like_lambda1

おや?左側に (-) が表示されていて、そこをクリックすると折りたたみ表示が出来るようですね。押してみましょう。

callback_like_lambda

折りたたまれて表示されたコードは、Java8のlambda風に表示されます!

実際にlambdaのコードになっているわけではありませんが、直感的に理解しやすくなってコードの可読性は向上しますし、同ページ内に表示される情報量が増します。

レイアウトエディタ

Android Studioはレイアウトエディタも強力です。かなりの部分をGUIで記述するのも簡単でしょう。

layout_editor1

慣れている方はXMLを直接編集した方が早いかもしれません。その場合は、エディタの下部にあるタブでTextを選択します。

layout_editor2

ここでも補完機能は強力です。レイアウトXMLで非常によく使う属性の一つに android:id がありますが、これを入力してみましょう。

layout_editor3

上図は andid と入力しただけで、android:idが候補として提示されている例です。

以下はViewの必須属性である android:layout_width と andorid:layout_height が未設定の場合です。警告が出ています。

layout_editor4

右側に表示されているプレビュー画面上に、何か支援候補が表示されています。

layout_editor5

その中から”Automatically add all missing attributes” を選択してみます。

layout_editor6

自動的に必須項目が追加されます。楽ですね!

当然、レイアウトXMLに埋め込んだテキストを strings.xml に追い出すのもお手のものです。

layout_editor7

ハードコードしているものがあるよという警告が出ているので、Alt+Returnで修正方法の候補を表示し……

layout_editor8

その中から、”Extracting String Resource” を選択するとダイアログが表示されますので……

layout_editor9

ダイアログからその文字列を定義するstrings.xmlの置き場を選択すると、レイアウトXML内にそのまま埋め込まれた文字列を追い出せます。

ちなみに、カスタムビューを作成している場合、それもレイアウト作成時に入力の候補として表示されます。

layout_editor10

署名されたAPKの出力

アプリをGoogle Playを通じて公開する場合、必ず署名されたAPKを作成しなければなりません。Android Studioはこの部分の支援も優秀です。

generate_signed_apk1

メニューの Build -> Generate Signed APK… を選択すると以下のダイアログが表示されますので、出力したいアプリ(Module)を選んでNextを押して進みます。すると、Eclipseでもおなじみのように、鍵ストアおよび署名鍵の選択画面が表示されます。Android Studioでは一画面に収まっています。

generate_signed_apk2

このダイアログに “Remember Password”というチェックボックスがありますので、いちいち毎回パスワードを打つのが面倒だという方はチェックしておくと良いでしょう。パスワードを覚えせるのは不安だ?ご安心ください。それに対してはちゃんと対策が用意されています。

先ほど入力したパスワードを記憶させる場合、マスターパスワードを設定して、そのマスターパスワードを入力しなければ保存されたパスワードを参照されないようになっています。下記は、すでに設定済みのマスターパスワードを入力するダイアログです。

input_master_password

すでにマスターパスワードによる解除が行われているものとして、次の画面に Next で進むと、出力する署名したAPKファイルの出力先選択ダイアログが表示されます。

generate_signed_apk3

ProGuardによる難読化を行うかどうかもここで設定出来ます。

出力に成功するとその旨を示したダイアログが表示されます。

generate_signed_apk4

Macの場合は、出力されたフォルダをFinderで表示することもワンボタンです。

おまけ

残念ながら新規ファイル作成で作成できるAndroidコンポーネントに、Fragmentは含まれないようです。これはSupport Libraryを使うアプリとそうでないアプリとがあるということに起因しているんでしょうか。

new android componet1

何かの機能を呼び出すキーを忘れたら、Help -> Find Action… を使うと便利です。

find_action_help_menu1

たとえば「補完」を意味する completion で検索してみましょう。

find_action_help_menu2

私が Emacs キーバインドで使用しているため、Alt+/ がBasic Completionの呼び出し方だよと表示されています。Defaultのキーバインドを使用されている場合、ここには Ctrl+スペースが示されることになります。

以上、簡単なものだけですが、Android Studio Tipsをお送りしました。

Android Studio (およびそのベースとなっている IntelliJ IDEA)が便利なものであることを少しでもご理解いただけていると幸いです。

RubyMine (またはIntelliJ IDEA)で、deviseのヘルパーが認識されない問題を回避する方法

Ruby on Railsでのユーザ認証機能には、定番として devise がよく用いられます。

また、Ruby on Railsでのアプリは、JetBrainsRubyMine (もしくは同機能を包含した IntelliJ IDEA)を用いると非常に効率よく開発を進めることができます。

しかし、この便利なdeviseを用いたRailsプロジェクトを、RubyMineIntelliJ IDEAで編集する場合に、deviseが提供するcurrent_userやuser_signed_in? ((Userクラスをdeviseを用いて作成した場合)) などの便利なヘルパーメソッドを認識してくれないという問題が発生します。

IDEが認識をしていないだけですので、実際にそれらのヘルパーメソッドを用いて作成した機能は正常動作するのですが、それらのヘルパーメソッドを用いる箇所で、IDEによる補完機能の恩恵を受けることが出来なくなります。また、文法違反の可能性があるとして警告が出てしまうため、他の本当に対処すべき問題を埋もれさせてしまう(潜在的なバグを見つけにくくなる)という問題もはらみます。

これは、RubyMineが動的に生成されたメソッドを認識して文法チェックすることが出来ないために発生していると思われます。

そこで、その問題を回避するため、以下のようなヘルパーを app/helpers/application_helper.rb に追記します(この例は、ログイン用にdeviseで作成したモデルのクラスがUserの場合)。

# IDEの補完機能を有効にするため、Deviseのヘルパを宣言
def authenticate_user!(opts={})
  opts[:scope] = :user
  warden.authenticate!(opts) if !devise_controller? || opts.delete(:force)
end

def user_signed_in?
  !!current_user
end

def current_user
  @current_user ||= warden.authenticate(:scope => :user)
end

def user_session
  current_user && warden.session(:user)
end

上記に追加したヘルパーメソッド群、元々のdeviseの中ではより柔軟に様々なモデルに対して適用できるように以下のようなコードがevalで動的に処理されます。(Github上の該当ファイル)

def authenticate_#{mapping}!(opts={})
    opts[:scope] = :#{mapping}
      warden.authenticate!(opts) if !devise_controller? || opts.delete(:force)
end

def #{mapping}_signed_in?
  !!current_#{mapping}
end

def current_#{mapping}
  @current_#{mapping} ||= warden.authenticate(:scope => :#{mapping})
end

def #{mapping}_session
  current_#{mapping} && warden.session(:#{mapping})
end

この #{mapping} の部分は devise 管理下で作成されたモデル名を元にして引数として渡されたものと置き換えられます。たとえば、Userモデルクラスの場合は #{mapping} の部分は user となります。

上記のような、任意のモデル名に対応することが可能なヘルパーメソッド定義となっているものを、特定モデルに特化したヘルパメソッド定義のせいで発生している問題を、特定のモデルに特化したヘルパーメソッドを定義することで回避するという対策です。

同様の方法で動的にメソッドを追加している箇所は他にもあるため、deviseを用いてコーディングをしている時に補完が働かないという現象が発生した場合は、必要に応じて同様の処理を行うと解決させられるかもしれません。

ところで余談ですが、RubyMineやIntelliJ IDEAは、サムライズムさんのような日本の代理店から日本的な商慣行での購入も可能です。開発効率を劇的に向上してくれる非常にパワフルなIDEですので、まずは30日間の無料体験をしてみてはいかがでしょうか。((とはいえ、これを確認に来た方はすでにRubyMineかIntelliJ IDEAユーザさんなのではないかと思いますが。))

なお、Railsでの devise の導入方法や使用方法については日本語のブログでの解説記事も多数ありますので、本エントリでは割愛いたします。