下記で訳してたものがまとまったので、こちらでも公開しておきます。
http://silentworlds.info/pukiwiki/?RubotoReadme
アップデートはwikiの方で行っていくのでご注意を。
オリジナル
2011/5/28最新のものを訳しています。
https://github.com/ruboto/ruboto-core/blob/master/README.md
ライセンス
古くなっていたり、翻訳が間違っている可能性もあるので、その点留意してご参照ください。
細かい表現を省いて訳している部分もありますので、ご注意ください。
Ruboto-CoreのReadme(日本語訳)
Ruby on Android.
インストール
$ gem install ruboto-core
はじめに
Rubotoを使う前に、次のことをやっておくこと。
- JDKのインストール
- jrubyのインストール
JRubyのインストールはとても簡単。もしくはrvmも使える
- Android SDKのインストール
- `$PATH` にAndroid SDKの`tools/`を追加する
- Android エミュレータイメージを生成する。(実機で開発するなら不要)
基本的なこと
Rakefileはアプリのルートディレクトリで実行されることを想定しており、Rubotoコマンドも同様である。(`ruboto gen app`は除く)
RakefileはJRubyのrakeを使って実行される必要がある。
コマンドラインツール
- アプリ生成コマンド(railsのアプリケーション生成に似てる)
- クラス生成コマンドは追加のActivity、BroadcastReceiver、Serviceなどを生成する
- コールバック生成コマンドは、多くのAndroidAPIのアクセスのために必要なサブクラスを生成する
- パッケージ処理はapkファイルを生成する
- デプロイ処理は、エミュレータか接続されたデバイスに、生成されたパッケージをデプロイする
- 変更のたびにコンパイルしないですむような開発
アプリ生成コマンド
$ ruboto gen app --package com.yourdomain.whatever --path path/to/where/you/want/the/app --name \
$ NameOfApp --target android-version --min_sdk another-android-version --activity MainActivityName
versionの値は、'android-'+SDKのレベル番号の形式をとること。(froyoの例 android-8 ).
クラス生成コマンド
rubotoのスクリプトで、Javaのクラス (Activity、Service、BroadcastReceiver) を生成する。同時にテストスクリプトも生成する。
$ ruboto gen class ClassName --name YourObjectName
Ex:
$ ruboto gen class BroadcastReceiver --name AwesomenessReceiver
コールバック生成コマンド
このコマンドで、特定のメソッドが呼ばれたときに、スクリプトに制御を渡せるようにどんなAndroid APIでもサブクラス化できるようにする。あなたがrubotoに制御を渡すAndroidインタフェースを実装することもできる。
サブクラス化する必要があるクラスの場合は、(例 PhoneStateListener, SQLiteOpenHelper, View)
$ ruboto gen subclass AndroidPackageAndClassName --name YourClassName --method_base all-on-or-none --method_include methods --method_exclude methods
実際の例:
$ ruboto gen subclass android.telephony.PhoneStateListener --name MyPhoneStateListener --method_base on
実装が必要なインタフェースの場合は、(例 OnClickListener or SensorListener)
$ ruboto gen interface AndroidPackageAndInterfaceName --name YourClassName
実際の例:
$ ruboto gen interface android.hardware.SensorListener --name MySensorListener
スクリプトの中で使う時は:
# java_importとは違うことに注意
ruboto_import "your.package.MySensorListener"
後ろの方で:
# コールバックオブジェクトを生成
@sensor_listener = MySensorListener.new
# 呼び出しされるブロックの設定
@sensor_listener.handle_sensor_changed do |sensor, values|
# Do stuff
end
# リスナーの登録
パッケージ処理
apkファイルを生成
$ rake
apkを生成して、接続されたデバイス(またはエミュレータ)に一発でインストールするには、下記のコマンドを打つ。
$ rake install
デプロイ処理
マーケットで公開する準備ができたら、いくつかやることがある。
まず、`keytool`でアプリの署名を行うためのキーを生成する必要がある。いくつかのしっかりした初期値を使うつもりがあれば、
$ ruboto gen key --alias keyの名前
というコマンドを、`--keystore /path/to/keystore.keystore`というオプションと共に使うことができる。それは、`~/.android/production.keystore`のデフォルト値となる。(?)
途中、keystoreと、キーそれ自身のための、パスワードを聞かれる。その二つのパスワード、キーの名前をちゃんと覚えておくこと。
キーはセキュリティに気をつけつつ、バックアップをしておくようにしておくように。(鍵をなくすと、アップデートがリリースできなくなる)
あなたのキーがあれば、`rake publish`タスクを使って、マーケットに公開できるapkファイルを作成できる。その際、環境変数`RUBOTO_KEYSTORE`と`RUBOTO_KEY_ALIAS`にkeystoreのパスと、キーの名前を下記のように設定すること。
$ RUBOTO_KEYSTORE=~/.android/production.keystore RUBOTO_KEY_ALIAS=foo rake publish
または`~/.bashrc`やそれに準じるファイルに設定してもよい。
そして下記を実行する。
$ rake publish
マーケットに公開可能なapkのできあがり。
スクリプトの更新
これまでのAndroid開発では、変更があるたびに、アプリをビルドし直して、デバイス/エミュレータにインストールしていた。
遅くて退屈であった。
Rubotoでは、幸運にも、変更のほとんどはJavaをコンパイルしないですむスクリプトの中だ。もし変更がRubyのみの場合、下記を実行するだけでよい。
$ rake update_scripts
このコマンドは、デバイスの中のスクリプトを更新する。
チャンバラのための言い訳を無くしてしまったとしたら、ごめんなさい。

注意:
これは変更が全てRubyの中に収まっているときだけ、上手く動作する。Javaの変更(一般的には新しいクラスを生成したとき)、またはXMLの変更があったときは、再コンパイルが必要である。
また、この処理を行うため、リードオンリーのディレクトリに書き込むことが必要になるようなときに、デバイスのroot権限が必要になる。rootを取れないときの、最も簡単な解決方法はエミュレータでテストするということだ。
Ruboto関連ファイルの更新
rubotoのコマンドで、生成されたアプリの色々な部分を更新できる。
- JRubyの更新:
- 1) JRubyの新しいバージョンがリリースされたら、gemを更新するべき (例えば sudo gem update jruby-jars)
- 2) アプリのrootディレクトリで、次のコマンドを実行する
$ ruboto update jruby
- ruboto.rb スクリプトの更新:
- 1) アプリのrootディレクトリで、次のコマンドを実行する
$ ruboto update ruboto
- 主要なクラスの更新(例えば RubotoActivity):
- 1) これらのクラスはSDKに依存して生成されている。SDKのバージョンは'gen app'の時に決まっている。(AndroidManifest.xmlに記録されている)
- 2) 新しいSDKがリリースされたとき、ターゲットを変更したとき、コールバックに手を入れてより拡張しようとするときなどに、あなたは再生成することを望むだろう。
- 3) アプリのrootディレクトリで、次のコマンドを実行する
$ ruboto gen core Activity --method_base all-on-or-none --method_include specific-methods-to-include --method_include specific-methods-to-exclude
-
- 4) ジェネレータはSDKの除法を読み込み、指定のメソッドを見つけ出す。ジェネレータは、メソッドが追加されているか、指定のSDKレベルで非推奨であるときに処理を中断する。あなたは、それらのメソッドを除外するか、または--force を付けて強制的に生成できる(追加されたメソッドは既存のハードウェア上でクラッシュしないように、superを呼ばない形で生成される)
スクリプト
Rubotoがあなたに求める主なことは、Activity、BroadcastReceievers、Serviceの動作を定めるRubyスクリプトを書く能力である。(ゆくゆくは全てのクラスになるだろう。クラスが増えてもそれはさほど大変なことではない)
どんな風に動いているのか:
最初に、あなたのスクリプトは`assets/scripts/`にあり、スクリプトの名前はあなたのクラスと同じである。キャメルケース記法の代わりにアンダースコアを使っている。
Androidのクラスは、特定の状況で呼ばれるメソッドの全てを持っている。例えば、`Activity.onDestroy()`はActivityがkillされるときに呼ばれる。
変わった場合の対応として(JRubyのセットアップが必要な起動メソッドのような)、onFooBarを書くために、あなたはAndroidオブジェクトの中で、Rubyメソッド handle_foo_barを呼ぶ。(?)1
あなたのスクリプトの中では、それらは`$class_name`として定義されている。これはまったくの概要なので、例を示す。
アプリを`--activity FooActivity`オプションを付けて生成するということは、rubotoはFooActivityを生成することを意味する。
`assets/scripts/foo_activity.rb`を好きなエディタで開いてみる。アプリが起動した時と破棄されたとき(onCreate、onDestroyのなかで)にLogを出すactivityが欲しいとき、スクリプトは下記のような感じである。
require 'ruboto.rb' #これ抜きではスクリプトは動かない
$activity.handle_create do |bundle|
Log.v 'MYAPPNAME', 'onCreate got called!'
handle_pause do
Log.v 'MYAPPNAME', 'onPause got called!'
end
end
下記のようなやり方を選択することもできる。やっていることは同じである。
require 'ruboto.rb' #これ抜きではスクリプトは動かない
$activity.handle_create do |bundle|
Log.v 'MYAPPNAME', 'onCreate got called!'
end
$activity.handle_pause do
Log.v 'MYAPPNAME', 'onPause got called!'
end
それぞれのクラスは、他の呼び出しをネストすることができるメソッドを一つだけ持つことができる(最初の例のように、二回目の`$activit.`の記述が不要になる)。(?)2
ActivityとServiceのためには`handle_create`、BroadcastReceiverのためには`handle_receive`がある。
基本的なルールは、これはクラスのライフサイクルの最初のメソッドに依存している。
しかし、このようなことは気にするべきではない、それはジェネレータがクラスを作る時に、メソッド呼び出しのサンプルスクリプトを生成しているからである。
引数は`handle_`メソッドに与えたブロックに渡される。それらはJavaのメソッドが受け取った引数と同じである。(?)3
Activityは、色々と簡単以するためにいくつか特別なメソッドをもっている。それらはdemo scriptsあたりを見れば分かるだろう。
合わせてruboto.rb fileを読めば、そこには全て定義されている。
テスト
それぞれの生成されたクラスについて、テストスクリプトはtest/assets/scriptsに生成される。
例えば、RubotoSampleAppActivityを生成したとすれば、test/assets/scripts/ruboto_sample_app_activity_test.rb がテストスクリプトのサンプルである。
activity Java::org.ruboto.sample_app.RubotoSampleAppActivity
setup do |activity|
start = Time.now
loop do
@text_view = activity.findViewById(42)
break if @text_view || (Time.now - start > 60)
sleep 1
end
assert @text_view
end
test('initial setup') do |activity|
assert_equal "What hath Matz wrought?", @text_view.text
end
test('button changes text') do |activity|
button = activity.findViewById(43)
button.performClick
assert_equal "What hath Matz wrought!", @text_view.text
end
Antまたはrakeを使って、テストを実行できる。
$ jruby -S rake test
$ cd test ; ant run-tests
プロジェクトへの協力
協力したいって?それは素晴らしい! irc.freenode.net の #ruboto で話そう。そしてプロジェクトをforkしてコーディングを始めよう。
「でも、プロジェクトをforkして協力していくほど、十分理解できてないのだけど」
気にすることは無い。下記のようなやり方もある。
- Rubotoを使い、どうしていけばよいか教えてほしい
- 何かよい考えがあれば、それをwikiに書いてほしい
- 考えがまとまったら、プロジェクトをforkすることをもう一度考えてほしい
プロジェクトへコードを提供するなら、既にあるテストを走らせて、あなたの変更分についてのテストも追加して欲しい。テストは下記のようにやって実行できる。
$ jruby -S rake test
ヘルプ
- Android APIについても多少詳しくあるべきだろう。 Developer Guide とReference が便利だ
- さらに詳しいドキュメントはwikiにある
- バグを見つけたり、リクエストがあるときは、GitHubを開いて項目を登録してほしい。
- irc.freenode.net の #ruboto とmailing list で質問を投げることができる。
- サンプルスクリプトは ここにある。
小ネタ
エミュレータ
Androidでの開発を多くこなしているなら、多くのエミュレータを`emulator -avd name_of_emulator`コマンドで扱っているだろう。これをaliasで短くして便利にできる。
例として, あなたの `~/.bashrc`, `~/.zshrc`など、適切な設定に,
alias eclair="emulator -avd eclair"
alias froyo="emulator -avd froyo"
と追記する。
代替になるもの
Rubotoのパフォーマンスが問題であるなら、またはRubotoがまだできてないAndroidAPIへの全体的なアクセスが欲しいなら、Mirah と Garrett をチェックアウトするとよい。
Dubyとして知られる、Mirahは、Rubyに似た文法を持ち、Javaファイルにコンパイルされる言語である。これはランタイムへの大きな依存を避け、Javaで書いたのと同等の性能を出せることを意味する。これは性能が大きな問題となるモバイルデバイスによく適合するだろう。
Garrettは”Android上でのMirah評価用の遊び場”である。
Domo Arigato
以下の皆様に感謝:
- JRubyコアチームのメンバーのCharles Nutter氏へ。RSoCプロジェクトのメンテナンス、そしてirbで、最初にRubotoに取りかかってくれたことに対して。
- Ruby Summer of Codeの スポンサーの皆様へ。
- Engine Yardへ。RSoCとJRubyの協力なスポンサーとして。このプロジェクトの重要な部分を担っています。
- すべての Ruboto-coreコントリビュータ と Ruboto-irbプロジェクトのコントリビュータへ。多くのRuboto-irbのコードを参考にしてます。
-
Save weird cases (like the "launching" methods that need to setup JRuby), to script the method onFooBar, you call the Ruby method handle_foo_bar on the Android object. ↩
-
Each class has only one method that you can nest other calls inside of [例 what is happening in that first example that removes the need for the second `$activity.`]. ↩
-
The arguments passed to the block you give `handle_` methods are the same as the arguments that the java methods take. Consult the Android documentation. ↩