Android ウェブアプリケーション 連携術 · 2011-12-01 · 同期API (独自Intent)...
Transcript of Android ウェブアプリケーション 連携術 · 2011-12-01 · 同期API (独自Intent)...
Androidウェブアプリケーション
連携術
株式会社はてな
自己紹介
株式会社はてな
アプリケーションエンジニア
id:cho45
について
● ウェブサービスの開発・運営をしている会社です
● 京都・東京
● Perl を使うことが多いです
(もちろん他の言語も使います)
cho45について
株式会社はてな
京都8F(@hatena8f)勤務
cho45
http://www.lowreal.net/
京都・サービス開発部・アプリケーションエンジニア
普段は Perl / JavaScript をメインにほか色々
領域:
● アプリケーションサーバコード
● ユーザーインターフェイスコード
Android 開発はじめてから Java を触る
趣味
神社巡り
本題
Agenda - Android ウェブアプリケーション連携術
はてなで開発された
Android アプリケーションの
事例を通して実際の開発方
法についてご紹介致しま
す。
Agenda - Android ウェブアプリケーション連携術
1. 事例1: フォトライフ for Android
ウェブではできないこと、Android で生まれた可能性
メモリ管理
2. 事例2: はてなログイン管理
なぜこのアプリケーションが必要だったか?
Android のパーミッション管理
3. 事例3: はてなモノリス
ウェブアプリケーションとの密な連携
設計の際気をつけたこと
4. 事例4: はてなココ
http://f.hatena.ne.jp/guide/android
はてなフォトライフ for Android
最初に取り組んだ Android アプリケーション
ウェブでは解決できないことを解決する
● はてなフォトライフの写真を快適に閲覧
● 写真アップロード・自動アップロード
● スライドショー
● など
写真閲覧
Activity Stack を活用した実装に
一覧系は同一 Activity
インテントを投げて全部別インスタンス
→ おかげで実装はそこそこ綺麗
ウェブページと 1:1 になる実装 (Activity == Page)
が、問題点が……
写真閲覧
Stack に残っている Activity インスタンスは開放されない
Android OS は・ユーザが操作している Activity
が属する
・アプリケーション
を自動で kill しない (古すぎる Activity は開放される)。
メモリを大量に使う Activity を短時間に積むと OOM
写真閲覧
Stack に残っている Activity インスタンスは開放されない
サムネイルを大量に保持すると当然 OOM
ページを辿りすぎると落ちる事態に……
→遷移前に保持しているサムネイルは開放し、
onResume 時に更めてキャッシュから読み直す実装へ
→Back ボタン時に若干ロードが走るようになったが許容範囲
あまりメモリを食わない情報は onLowMemory で開放
写真閲覧
端末回転の実装
普段回転をオフにして開発していたため暫く気付かず
回転したら全て作りなおす実装では重すぎた
→回転時に発生する onRetainNonConfigurationInstance
を真面目に実装して解消
読みこんだ画像を保持して持ちこすようにしただけ
写真閲覧実装時の教訓
メモリ開放は繊細に実装しよう
端末回転はマジメに実装しよう
写真アップロード
Service を使わなくても実装できるかと思ったが無理だった
→ 普通に Service を使って実装
(Service == Worker サーバ的なもの)
プログレスの Notification などに苦労したが
基本に忠実に実装
写真閲覧のプロセスと別にすることで
Service 自体のメモリ使用量を減らし、kill されにくくしている
外部 Intent からのアップロードに対応
● 非同期API (Intent.ACTION_SEND)
Service に投げっぱなし
● 同期API (独自Intent)
プログレスを表示するため aidl を書き、
内部でIPC
写真アップロード
● 撮った写真を自動アップロード
● フォトライフ側の twitter 連携を使うと
自動で twitter 投稿までやってくれる
寒くてアップロード待ってられないし、全部 twitter に投稿してライブ
したいし…… というとき非常に便利
写真自動アップロード
● Service を常時起動
● 数十秒ごとにファイルシステムを監視
カメラの撮影Intentを掴まえたほうがいいのだが
各社カメラアプリがそれを発行するか解らかったため
確実に動く方法を採用
● 工夫
・スクリーンがついているときだけ監視
・lastModified が起動直後狂うので頑張る
写真自動アップロード
基本的に Service は死なないことになっているが
何らかの原因で死なれて復帰しないと困るので
AlarmManager で定期的に死活を確認している
Notification が出ていても、起動しているとは限らない
Service の常時起動
少なくとも HT-03A (1.6) で再現して困った。
以下で解決
long lastModified = file.lastModified() - TimeZone.getDefault().getRawOffset();
起動直後はTZが設定されるまでディレイがある……
起動直後しか発生しないのでデバッグが▽めんど
(Tips) 起動直後の時間狂い
アップロード実装時の教訓
サービスは利用すべきなら積極的に
プロセスをうまくわけよう
メモリ消費削減の手
うまくツールを使おう
● Memory Analyzer (Eclipse plugin) 参考
どんなオブジェクトがメモリ消費しているかわかる
(画像じゃない部分で消費量が多い部分があってなおした)
● DDMS で見れるスレッド一覧 (エミュレータ)
意図していないスレッドができていないか?
(HttpClient がスレッドを作るので一本化した)● traceview ...
プロファイル結果をグラフィカルに見れるやつ
SDK に入ってる Debug.startMethodTracing
バグレポート送信機能
2系のOSだとマーケットでバグレポが見
れますが、
1.6系だと見れない or マーケットにあげ
てないと見れない
組込みが簡単なよう、メールで送るような
やつを書いて使っています。
http://subtech.g.hatena.ne.jp/cho45/20100210/1265797885
バグレポート送信機能
欲しいけど(端末供給的に)買えない
端末から送られてくるとmoge感
はてなログイン管理
はてなログイン管理
アカウント情報管理アプリ
● ユーザ情報を何回も入れたくない
(Android 2系にはOS組み込みで同様のものがあるが、1.6 にはなかったので、仕方なく)
はてなログイン管理
最初はOSの Content Provider + permission を
考えていた
→セキュリティ上の問題で止め、
Intent のやりとりに変更
<permission>
<permission> は先に定義したもの勝ちする
→プリインストールアプリケーション以外は
安全性を確保できない
検証
はてなログイン管理
Android 2系に対応とともに
補助アプリケーション扱いにしたい
OS組み込みのアカウントマネージャは
まだ検証中
はてなモノリス
http://mono.hatena.ne.jp/バーコードを読んでモノを共有するサービス
アプリは Android, iPhone で提供
アプリでバーコードを読んで投稿する
● 外部ライブラリ組込み
● ウェブとの連携
設計と実装
最小工数でリリースすること
● できる限りはウェブで
(我々のメインフィールドはウェブなので)
● ウェブのシームレスな連携
(Android は OS 自体がそうなっており、理にかなっている)
外部ライブラリ
zxing を使用
既存のものを最大限利用したいが……
● リソースファイルが……
● クラスの依存関係が……
ライブラリ系は単にコピーするだけにしたいが
変更なしでは無理だったので、
頑張って移植作業をした
リソース名・リソースファイル
別のプロジェクトのを利用しようとすると
名前がかぶって困る
ログイン管理統合版フォトライフでも同様の問題が発生したが、こちらはかぶらないように両方を調整することで対処
res/values/strings.xmlres/values/accounts_strings.xml@ -> ../../modules/HatenaAccounts/res/values/accounts_strings.xml
ウェブとの連携
● 本番サーバとテストサーバがある
● 別々のバイナリを作るのは面倒
社内の人に試してもらうときも面倒→非表示な設定項目を作ることで対応
特定の Intent を手動で投げることで表示
adb shell am start -n com.example.foo/.Setting --ez debug true
adb shell am start -n com.example.foo/.Setting --ez debug true
で開発者用の設定が
出るように
設定でドメイン切り替え
デバッグサーバ
onCreate でif (!intent.getBooleanExtra("debug", false)) { pAdvancedContainer.removePreference( findPreference("test_server_enabled_key") );}
とかやって消しているだけ
デバッグ用
● はてなでは翻訳者とやりとりするツールがある
● ID + 言語 + 単数複数活用 のデータベース
国際化
● 翻訳データベースから strings.xml は自動生成
● OS組込みのリソース切替えだと不完全
● 複数・単数対応は独自に Locale.java
(リフレクションで頑張っている)
国際化
<string name='monolith_users'>%1$s users</string><string name='monolith_users_1'>%1$s user</string><string name='monolith_users_qt'>1_o</string>
Locale.getStringN(this, R.string.foo, n);
none : 複数形"_1" : 単数形"_qt": 単数形ルール
● 1 だけ単数形 (1_o) (英語など)● 0 と 1 が単数形 (01_o) ()● 単複同形 (o) (日本語など)
国際化
はてなココ
http://c.hatena.ne.jp/イマココ(位置情報)共有サービス
アプリは Android, iPhone で提供
WebView の組み込み
● ココアプリでは WebView がアプリ組込み
● 開発者独りでバックエンドからアプリまで作ってい
るので、インターフェイスを Web によせ、最小限
実装
● リソースを多く使うなど欠点はあるが、必要な部分
から徐々に置き換えたりができる
WebView の組み込み (BK)
● API が JSON の中に HTML をそのまま返す
→ WebView に流しこみ
というが部分的にある
● なぜか <meta charset="utf-8"/> がないと
文字化け
WebView の組み込み
● http 経由で読み込んでいる部分
● アプリかどうかで一部(サーバサイドで)
出しわけし、最小限の転送になるように
ウェブエンジニアの視点から
Android に対して思うこと
Android になってアプリが作れても
基本はウェブ
Intent は高級になったハイパーリンク
Activity は進化したウェブページ
Service はワーカープロセス
Content Provider はデータベース
ウェブとのシームレスな連携は
(早すぎるかもしれないが) 恐しく未来的
うまく生かして開発していきたい
はてなの開発リソースhttp://developer.hatena.ne.jp/
利用可能な Intent の仕様も纏まっています
是非使ってください!!!
ご清聴ありがとうございました。
Androidウェブアプリケーション連携術
株式会社はてな
アプリケーションエンジニアcho45