2010年 02月 06日

Eclipse + Vim 開発環境構築

Android SDK は Eclipse 前提でだいたい話が進むので、かたくなに Eclipse を使わないようにしているといらない苦労を負いすぎます (リソース管理とか)。ので、これを期に Eclipse と連携させて Vim を使う環境をつくりました。

Eclipse をコンパイル、実行環境にし、編集を Vim にするために

  • Eclim をいれる http://eclim.org/
  • eclimd を起動 (Window -> Show View -> eclimd or /Application/Eclipse/eclimd) して :PingEclim :EclimValidate がうまくいくか確かめる。ぼくは大丈夫だった。ダメなら FAQ
  • ワークスペースの設定をする
    • Eclipse デフォルトなら変えなくてもいいっぽいけど、僕の場合 ~/project なので
  • eclimd はメモリ増やして起動する
  • :ProjectInfo がうまくいくかを確認する。できなければ FAQ を見る

AutoComplPop の設定

.vimrc に追記

let g:AutoComplPop_Behavior = {
      \   'java' : [
      \     {
      \       'command'  : "\<C-n>",
      \       'pattern'  : '\k\k$',
      \       'excluded' : '^$',
      \       'repeat'   : 0,
      \     },
      \     {
      \       'command'  : "\<C-x>\<C-u>",
      \       'pattern'  : '\k\k$',
      \       'excluded' : '^$',
      \       'repeat'   : 0,
      \     },
      \     {
      \       'command'  : "\<C-x>\<C-f>",
      \       'pattern'  : (has('win32') || has('win64') ? '\f[/\\]\f*$' : '\f[/]\f*$'),
      \       'excluded' : '[*/\\][/\\]\f*$\|[^[:print:]]\f*$',
      \       'repeat'   : 1,
      \     }
      \   ]
      \ }

キーワードマッチしなければ eclipse に投げる (めっちゃ重い)。

デバッグ

保存すると自動で :Validate が走る。:lope で確認できる。+sign つきで vim がコンパイルされているならいい感じにでてくる!

:Validate が走るタイミングが保存よりも早いときがあってちょっと変

import 分関係

http://eclim.org/vim/java/import.html

  • :JavaImportMissing
  • :JavaImportClean

override しまくる

:JavaImpl すると override できるメソッド一覧がでてくるので、適当に RET おすと テンプレートが挿入される。便利なんだけど、Vim の undo が効かなくなってしまうのであんまり使ってない (表示させてコピペ、っていう使いかたをしてる)

データクラス

ハッシュを自由に作れないのが LL に比べて極めて不便なので、つどデータクラスを作るわけですが、getter setter 作るのが死ぬほどめんどい。

  • :JavaGetSet

Android アプリケーションのヒープメモリを観察する

メモリが限られていると頻繁に OOM エラーがでますが、OOM エラーは出さないことが大前提なので、頑張って何が容量食ってるか調べないといけません。まぁ、コード的に勘が効く部分は良いのですが、ライブラリに隠蔽されていたり、普段 LL 使ってると見落したりする部分があるのでちゃんと計測したいもんです。

http://www.eclipse.org/mat/ をいれる。

エミュレータでアプリケーションを起動して、ある程度動かしてから

↑ のボタンを押す

メモリーリークしているっぽいものまで解析してくれる。すごい

Histogram -> ソート -> 右クリック -> List objects でどんなオブジェクトがみれるっぽい。List objects の outgoing incoming はよくわからない。

開発中これを使ったら、画像のURLを保持する的な部分で随分メモリを食っていることが分ったので、はてな記法のみを保持してURLとかは必要なときだけ更めて生成 (パフォーマンスは劣化しますがOOMでるよりはマシです) するようにしたらだいぶ改善しました。

あと、スレッドの一覧を見ながら動かして想定通りのスレッド数かを観察するのも大事だと思いました。HttpClient はインスタンスごとにプールスレッドを持つので注意が必要でした (若干反則な気がしますが static に確保するようにしました)

2010年 02月 05日







意外と空の写真を撮ってるなぁ。空ほど、写真にしてあとで見てがっかりするするものはない。







こういうシーンだとケータイの撮って出しでもいい感じ (一番下のはたぶん素子の許容量超えて光が入って飽和して色が変わってる? フレアがでたらいいなぁと思って撮ったらこうなった……)

Android の組込みアプリ以外のパーミッションの取り扱い

はてなアカウント管理を作るにあたり、最初は Android のパーミッションの仕組みにのっかろうと考えていましたが、調べていくうちにセキュリティリスクがあることがわかったので、別途自力でユーザにオプトインする仕組みを入れました。(はてな以外からリリースされるアプリケーションでは、アカウント管理に情報を渡す際に本当に渡すかをユーザに同意を求めるようになっています)

Android のパーミッションの仕組みは「先に定義したもん勝ち」という感じのようなので、端末デフォルトでインストールされていて、アンインストールが不可能になっているアプリケーションでのみ、安全に働くようでした。なんかやりかたがあるのかよくわかりませんが、そんな感じでしたので、今のところ一番確実な方法を選んでいます。

手元の実機 (Android 1.6) での検証では

  • <permission android:name="com.example.permission.FOOBAR" android:protectionLevel="dangerous".../> というパーミッションを定義する、アプリケーションA
  • それを uses-permission で定義する、アプリケーションB
  • <permission android:name="com.example.permission.FOOBAR" android:protectionLevel="normal".../> というパーミッションを定義する、悪意あるアプリケーションC

A の signature と B, C の signature は別

A → B とインストール

  1. A インストール
    • permission が定義される
  2. B インストール
    • uses-permission の内容が表示される
  3. B で該当パーミッションAに対し使おうとする
    • 成功する

→ 正常

B → A とインストール

  1. B インストール
    • uses-permission は表示されない (Unknown permission)
  2. A インストール
    • permission が定義される
  3. B で該当パーミッションAに対し使おうとする
    • 該当パーミッションは定義されていないためセキュリティエラー Permission Denial

→ 正常 (この場合 B をインストールしなおすしかないのでユーザビリティ的に問題があるため採用できない)

C → A → B とインストール

  1. C インストール
    • permission が定義される (protectionLevel="normal" == ユーザに確認がでないパーミッション)
  2. A インストール
    • permission は定義されない (既に存在するので無視される)
  3. B インストール
    • uses-permission の内容が表示されないが C で定義された permission が grant される
  4. B で該当パーミッションAに対し使おうとする
    • 成功する

Bがユーザへの確認なしに、不正にパーミッションを行使していることになる。

インストール関係のインテントとかをコマンドラインから発行する

パーミッションのテストみたいなのは死ぬほどめんどいです。コマンドラインからやってもめんどい。

adb install は PackageManager を使わないのでダメです。もちろんちゃんと sign した apk じゃないとダメです。

adb push Foo.apk /sdcard
adb shell am start -a android.intent.action.VIEW -t application/vnd.android.package-archive -d file:///sdcard/Foo.apk

でインストール

adb uninstall com.example.foo

でアンインストール (パッケージ名を指定するみたいです)


ちまたの sdcard からアプリをインストールするやつは、上記 Intent を投げているだけなので、特別パーミッションがいらないはずですが、なんかやたらパーミッションを要求するのが多くて、開発者以外にテストしてもらう際に困ります。

全くパーミッションを要求しないやつには com.mmg.appin というものがあるっぽいです。

ウェブアプリとAndroidアプリの対応

  • ページ表示 (View, Controller) → Activity
  • モデル → ContentProvider
  • ワーカー → Service
  • cron バッチ → AlarmManager
2010年 02月 04日

Fotolife for Android リリース

Fotolife for Androidがリリースされました。

期間的にはだいたい1ヶ月で、そんなに短かいわけではないのですが、割と大変でした。Android ケータイはもちろん持っていて、使っていたわけですが、開発は Scala で rake 使って Hello, World! を動かす程度しかやっておらず (いろいろ間違ってる)、Java 自体、Rhino、Scala で間接的に一部 API を使ったことがあるだけで、ちゃんと Java のコードを書いたのは開発が決まってからでした。

「Java の文法・API」と「Android の API・バッドノウハウ」の二重でハマるので、特に最初の2週間は、アプリケーションも形にならず (アップロードもできず、表示もろくにできなかった)、たいへんしんどかったです。ちゃんとしたマルチスレッドも、普段 Perl, JavaScript ばかりなので同期方に慣れずに苦労しました (Ruby も割とシングルスレッド脳で書いてるし)、というか、いまもしてます。

スレッドまわりに関しては「Java 言語で学ぶデザインパターン入門 マルチスレッド編」を借りて読んだり、「Java 並行処理プログラミング」を買ってもらって読んだりしてみました。どちらも解りやすく、後者は特に何を使うべきかが明確で実践に即応用できたので良かったです。java.util.concurrent スゲー! ってことで使いまくってます。ソースコードは Future だらけです。new Thread() を全然書いてないです。

基本的に、Android の開発は Google のオフィシャルのドキュメントをちゃんと熟読するのが近道だと思いました。あと、それだけだと、僕みたいなのは頭に入ってこないので、android のレポジトリを全部落としてきてデフォルトで入っているアプリのソースを読むのがいいと思いました。SDK のサンプルは最小限で、それはそれでいいのですが、もっと具体的にどうするのかがよくわからなかったりするので、やっぱちゃんと動いてるコードは偉大です。

Java は食わず嫌いでしたが、やってみると案外楽しくて、思ったより書いていてイライラしない言語だなぁと思いました。基本部分のAPI (特に Stream 系) は死ぬほど冗長で意味がわからないのですが、Android 関係の API は割と普通に使える印象でした。(そのうち書きますが Eclipse と Vim を連携させて書いてます) 匿名クラス萌えです。

id:secondlife さんディレクションのもと開発し、id:nagayama さんに各種アイコンのデザイン、id:aaron さんに英語リソースのチェックをしてもらい、id:tikeda さん、id:hakobe932 さんに直前にフィードバックを貰いました。

しばらく社内用に書いたノウハウを公開していこうと思います。Fotolife for Android のAPI (インテント) も公開するので少々お待ちください。


2010年 02月 03日