mojavy.com

Rubotoを使ってRubyでAndroidアプリをかく

March 29, 2013 at 09:53 PM | categories: android, ruby |

ruboto

最近iOSアプリ界隈ではRubyMotionMobiRubyが盛り上がってきてますが、AndroidでもRubotoをつかえば簡単にrubyで開発することができるようになります。

そもそもjavaで実装された処理系であれば大抵javaクラスの呼びだしは簡単にできるようになっているので、jrubyやjythonでandroidアプリを開発することは以前から可能でした。 しかし、以下のような問題があって実際にやるとなるとそれなりに面倒なものでした。

  1. jrubyやjythonをdalvikvm用バイナリ(dex)にコンパイルするのに時間がかかる1
  2. androidのjavaでは使えない機能を使って処理系を実装してある場合があるので、何らかの方法で回避する必要がある
  3. スクリプトのソースファイルの配置やパスの設定を自分でやる必要があり、パッケージングが面倒
  4. アプリのフットプリントが大きくなる2

Rubotoをつかえばこのあたりの面倒をみてくれるので、ほとんどjavaを書く必要がなくなります。Ruboto自体は結構前からありますが、ここ1年くらいでもろもろの機能が充実してきて大分実用的になってきた感があります。

以下Rubotoの使用方法について簡単に紹介します。

インストール

gem install ruboto
gem install jruby-jars

また、ANDROID_HOME環境変数の設定と、android sdkの tools/platform-tools/にはあらかじめパスをとおしておきます

雛形の生成

ruboto gen app --package org.rubyandroid.new_demo

# 以下のようにしてより詳細に設定することもできます
# ruboto gen app --package org.rubyandroid.new_demo --path ./myapp --name MyApp --target android-17 --min-sdk android-10 --activity MainActivityName

ビルドとインストール

rakeからビルドできるようになっています。また、rubyスクリプトの更新はコンパイル不要で反映できます。 あとは普通にrubyを書くだけです。

cd new_demo
rake
rake install

#
# edit ruby scripts..
#

rake update_scripts

rubygemsを使う

通常のGemfileと同じ内容を、Gemfile.apkという名前のファイルに書いてプロジェクトのルートディレクトリに置いておけば、rakeした際にlibs/bundle.jarを生成してapkにいれてくれます。

詳細は以下の例を参考にしてください。 https://github.com/ruboto/ruboto/wiki/Tutorial%3A-Using-an-SQLite-database-with-ActiveRecord

補足

rubotoではjrubyの実行環境は別途Ruboto Core platformというapkで提供されています。そのためアプリ本体にruby処理系を同梱する必要がなく、省サイズでコンパイルも速くなるというメリットがあります。しかし、このやり方だとRuboto Core platformを別途インストールしてもらう必要がでてきてしまい、実際にGoogle Playで配布するようなアプリでは受け入れ難いと思います。

これを回避する方法も提供されていて、プロジェクトを生成する際に--with-jrubyというオプションをつければjrubyを同梱したapkをビルドできるようになりますが、この場合は前述のメリットはうけられなくなります。ただ、コンパイル時間に関しては、rubyスクリプトだけを触っている限りは、dexの再コンパイルは必要ないのでそれほど気にならないと思います。

まとめ

  • androidで素のjrubyを使うのは茨の道ですが、rubotoを使えば非常に簡単にrubyを使えるようになります
  • jrubyなので普通のrubygemsやjavaでかかれたライブラリもそのまま使えます
  • javaで開発した場合はコンパイル〜再インストールが毎回必要になりますが、.rbの更新反映は高速にできるので開発効率があがります
  • まだそれほど使い込んでないので思わぬはまりどころがあるかもしれません

  1. dxが分割コンパイルに対応してないので回避しづらい 

  2. ファイルサイズも実行時のメモリ使用量も 



細かすぎて伝わらないAndroid開発のはまりどころまとめ その1

November 07, 2012 at 12:00 PM | categories: android, tips |

android

これまでandroidアプリを開発しててはまったことがたまってきたのでまとめておきます。順不同です。 その2はまたねたがたまってきたらたぶんそのうち。

目次

onAnimationEndでviewの階層を操作するとNullPointerExceptionでおちる

Viewをフェードアウトして親Viewからremoveする、というような動作をしたい場合に、普通にonAnimationEndの中でremoveViewとかするとNullPointerExceptionでおちます。onAnimationEndの中でViewの階層構造を操作するような処理をしてはだめらしいです。回避するには、Handlerをつかってタイミングをずらしてやるとよいです。

Animationが動かない

AnimationさせるViewには親Viewが存在している必要があります。WindowManagerはViewではないので、WindowManagerにaddViewしたViewをアニメーションさせたい場合は空のRelativeLayoutとかにaddViewしてから、RelativeLayoutのほうをWindowManagerにaddViewしてやる必要があります。

WindowManagerにaddViewしたときの挙動

WindowManagerにもaddViewできますが、通常のViewとは挙動が違います。

  • 背景透過はWindowManager.LayoutParam.format に TRANSLUCENT をセットすればよいです。
  • dimでフェードインできますが、その際のdurationを変更する方法は分かりませんでした。
  • BACKボタンはきかなくなります。自分でKeyEventを処理してやる必要があります。android.widget.PopupWindowのdispathKeyEventのソースが参考になります。

Activityが横向きでスタートした場合と縦向きでスタートしたときで表示倍率が違う

onCreateが何回もよばれる

回転やキーボード表示のタイミングでもonCreateがよばれます。AndroidManifest.xmlでconfigChangesを設定することで回避できます。

popupWindowのsetWidth, setHeightは次回以降の表示サイズしか変えられません。既に表示しているポップアップウィンドウのサイズはそのままです。invalidateしても無駄です。

HttpURLConnectionが 0byteのresponseを返す

コネクションプールとkeepaliveがらみで問題が発生する場合があるみたいです。SDKのバージョンとウェブサーバ側の設定も影響します。 System.setProperty("http.keepAlive", "false") で回避はできるようです。これに遭遇したときは、org.apache.http.impl.client.DefaultHttpClientの方を使うことにしたので詳細は追ってません。

org.apache.http.impl.client.DefaultHttpClientがすごく遅い

httpsでリクエストを投げると、ウェブサーバ側の負荷が高いわけでもネットワークが細いわけでもないのに、返ってくるまでなぜか数秒かかる場合があります。こちらもkeepaliveがらみの問題っぽいです。これもウェブサーバ側の設定が影響します。 試した限りでは以下のような状況でした。

  • setHeader("Connection", "close") しても効果なし
  • setKeepAliveStrategyでdurationを 0とか1にしても効果なし
  • Connection closeしないウェブサーバならすぐレスポンスが返ってくる
  • httpならすぐレスポンスが返ってくる

ここ( http://hc.apache.org/httpclient-3.x/sslguide.html ) のKnown limitations and problemsをみるとそれっぽい既知の問題があるようですが、根が深そうだったので詳細は追ってません。

eclipseのAndroid pluginが動かなくなった

なぜかeclipseでAndroid pluginが動かなくなるときがありました。詳細をメモるのを忘れてしまいましたが、以下の手順で直ったような気がします。

  1. Android Support Libraryをアンインストール
  2. eclipse再起動
  3. 新しいAndroidプロジェクトを作るとダイアログでライブラリのインストールを促されるのでそれに従う
  4. android プラグインをアップデート

WebViewで表示されるコンテンツが小さすぎる

通常ビューのスケールとWebViewのスケールは別です。setScaleで調整する必要があります。 これはたぶんiOSでも同様かと。

java.lang.RuntimeException: Stub!

android.jar内のコードはdalvikvmの外で実行することはできません。問答無用でタイトルの例外が飛びます。 エラーメッセージはもうちょいなんとかならなかったのか。

参考

jarとして配布するandroidライブラリ内にリソースを埋め込むことはできない

リソースIDを列挙しているRパッケージはjarにそのまま入れることはできますが、そのリソースIDは不正なものとなります。 ライブラリにリソースを含めたい場合は、ソースも含めたプロジェクトをまるごと配布するしかないようです。

ごく小さなアイコン画像だけとかであればバイナリデータをソース中に埋め込んでしまう、というのも手です。 iOSならBundleという仕組みがあります。

android-maven-plugin から mvn eclipse:eclipse でeclipse用にエクスポートすることはできない

androidでもmavenは使えますが、androidのmavenプロジェクトは通常の方法(mvn eclipse:eclipse)ではeclipseにインポートできません。 以下のファイルを手動でつくってみたらとりあえずいけました。

  • .classpath
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
        <classpathentry kind="src" path="src/main/java"/>
        <classpathentry kind="src" path="gen"/>
        <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
        <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
        <classpathentry kind="output" path="bin/classes"/>
</classpath>
  • .project
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
        <name>project-name</name>
        <comment></comment>
        <projects>
        </projects>
        <buildSpec>
                <buildCommand>
                        <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
                        <arguments>
                        </arguments>
                </buildCommand>
                <buildCommand>
                        <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
                        <arguments>
                        </arguments>
                </buildCommand>
                <buildCommand>
                        <name>org.eclipse.jdt.core.javabuilder</name>
                        <arguments>
                        </arguments>
                </buildCommand>
                <buildCommand>
                        <name>com.android.ide.eclipse.adt.ApkBuilder</name>
                        <arguments>
                        </arguments>
                </buildCommand>
        </buildSpec>
        <natures>
                <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
                <nature>org.eclipse.jdt.core.javanature</nature>
        </natures>
</projectDescription>
  • project.properties
# Project target.
target=android-10

# if it is a library
# android.library=true

まあ、なんというか、Androidはいろいろ残念ですね。

iOSはこういう仕様なのかバグなのかよくわからないようなものが少ないし、OSバージョンの入れ換わりが早くて対応バージョンも少なくて済む分、個人的な体感ではandroidアプリの工数はiOSの3割増しという感じ。



About Me

pic
mojavy

Recent posts






Categories



Badges