2011年1月アーカイブ
TwitterのOAuth認証してつぶやいてタイムラインを取得できるiPhoneアプリを10分で作るというのを、昨日のスマートフォン勉強会@関西#13で実演してきました。
真っ白な状態のアプリに、OAuth認証を導入して、TextAreaで自由につぶやけるようにして、タイムラインを取得して表示するところまでで9:21。
動画の下、360pの左にあるCCボタンを押すと、解説が出るようになります。
先日公開したoAuthAdapter修正版を取り込んだtm_twitter_apiというのを使っています。
あと、補完機能は、emacsとAuto Complete Modeに自作の辞書を組み合わせたもの。10分で作る動画の場合、タイプミスしてビルドエラーが出ると撮り直しなので、補完機能はとても便利ですね。
コード:gist: 802605 - 10min twitter client- GitHub
USteram録画:古川大輔(mogya)「10分で作るtwitterクライアント」 スマートフォン勉強会関西#13
(2011-02-04 追記)
emacs autocompleteの辞書は、k1LoW/emacs-titanium - GitHubにあります。自分は、これを元にgist: 810559 - emacs titanium dictionary- GitHubを作って使っていました。
| デザイナさん? | iPhoneぽいUI | ネイティブUI | カメラやファイルアクセス | AppStore | |
| HTML/CSS/JS | 可能 | X | X | × | X |
| jQTouch | 可能 | ◯ | X | × | X |
| jQuery Mobile | 可能 | △ | X | × | X |
| SenchaTouch | 難しいのでは | ◯ | X | × | X |
| PhoneGap | まだマシ | 自前 | カメラなどごく一部 | ◯ | ◯ |
| Flash(Packager for iPhone) | ありうる | X | X | △ | ◯ |
| Titanium Mobile | たぶん無理 | ◯ | ◯ | ◯ | ◯ |
| MonoTouch | 無理 | ◯ | ◯ | ◯ | ◯ |
| ObjectiveC | 無理 | ◯ | ◯ | ◯ | ◯ |
説明
デザイナさん?
普段PC向けや携帯向けWEBサイトの制作をしているデザイナさんでも扱いきれるかどうか。もちろん、デザイナさんにもピンキリあって、C#をバリバリ書くデザイナさんがいないとは限らないんだけど、そんなのは(ryiPhoneぽいUI
ON/OFFがスライドするチェックボックスとか、右端に矢印のついたリストとか、そういうiPhoneぽい見た目のUIを実現する仕組みがあるかどうか。iQueryMobileは、jQtouchと同じ仕組みでUIをつくってくれるんだけど、iPhoneではなくて、スマートフォン全般をターゲットにしたUIになるので、△にしてある。
ネイティブUI
「iPhoneぽいUI」に近いんだけど、iOSが持っているネイティブのUIを使うかどうか。jQTouchは、画像を使って頑張ってiPhoneぽい見た目を再現してくれるんだけど、同じものではないから、テキストボックスをタッチしたときに開くキーボードの種類とか、チェックボックスをタッチしたときの動きとか、微妙な部分ではどうしても普通のアプリとちょっと違う動きになってしまう。
この違いを埋めようとし始めるとものすごく大変な開発になってしまうから、そんなことをするくらいならネイティブUIを使える環境を選ぶべき。そういう事は気にしない、見た目が同じであればいい、ということであればjQTouchがお手軽で便利です。
カメラやファイルアクセス
カメラ機能や、iOSのファイルシステム上にファイルを保存するといったことができるか。×になっている環境でも、例えばGPSとかsqliteデータベースは、HTML5の機能で使うことができる。でも、例えばデータベースに最初からデータを入れておきたいとか、カメラで撮影した写真をサーバに上げたいといった機能を実現するためには、ここが◯になっている環境である必要がある。
Packager for iPhoneは、原理的にはカメラだって使えていいはずなんだけど、この記事を書いた時点ではまだ対応出来ていない。
AppStore
作ったアプリをAppStoreで販売してもらうことができるかどうか。 AppStoreで販売できないのはひとつの弱点だけど、AppStoreに登録するためにはAppleの審査が必要だったり、バージョンアップに時間がかかったりしてしまうので、場合によっては、ブラウザで動かせる他の環境を使って気軽にユーザーさんに使ってもらうという選択肢もアリだと思います。@mogya While executing Timer, received script error. 'Result of expression 'URL' [undefined] is not an object. at oauth.js (line 453)'でした!
ただ、またもや互換性が保てなくて、oAuthAdapter.send()の戻り値を使うのが無理になりました。申し訳ない。
sendから戻ってきたからといってAPI呼び出しが完了して戻り値が入っていることは保証できないので、その代わりにonSuccessコールバックを利用してください。 初期化部分も含めたコード全体は、readmeで見ることができます。
How to start
- 新しくプロジェクトを作る
- Resources/libディレクトリを作って、oAuthAdapter.jsと、oauth.js,sha1.jsを入れる
- readmeのコードをapp.jsにべったり上書きする
- 'YOUR CONSUMER SECRET','YOUR CONSUMER KEY',部分を自分のキーに置き換える。SECRETが先であることに注意
- Launchすると、oAuth認証が立ち上がり、その後勝手につぶやき、タイムラインをデバッグコンソールに出力します。
解説
Davidの書いたoAuthAdapterには、sendを呼び出した時点でoAuth認証が完了していなかったら、呼出をいったん保留して、認証後に再呼び出ししてくれるという機能が付いています。上記エラーは、この再呼出部分のコードを修正するのを忘れていたことが原因だったので、これは修正しました。
ところが、そういう非同期の呼び出しが起こる以上、関数の戻り値にAPIの戻り値が入っていることは保証できなくなりました。(というか、最初から保証できなかったのですけど、僕が気づいていませんでした。)
あと、全然別件なのですけど、Davidの書いたoAuthAdapterでは、sendの引数にtitleとpSuccessMessageを渡して、API呼び出しが成功すると、かならずポップアップが出る仕様になっています。update_statusならともかく、タイムラインを更新したり、バックグラウンドでユーザー情報を取得したりする場合、この仕様はちょっとありえません。
二つの問題をバッサリ片付けるアイデアとして、titleとpSuccessMessageの使用を廃止して、代わりにonSuccessコールバックを採用することにしました。onSuccessコールバック関数の中でダイアログを出せば、従来と同じ挙動をすることができます。
友達に頼む
- 技術的詳細を知らなくても機能を実現することが出来る
- 愛と勇気しかお友達のいない方には向かない
- レベニューシェアという手もあるよ
プロに頼む
- lancersオススメ。過去の履歴が残るので発注価格の参考になる
- 普通に発注すると、バージョンアップのたびに開発費用がかかる点に注意
ObjectiveC
- Appleが認める正式な開発言語
- なんでもできるから、これで開発できる人はそうするのが一番
- めんどくさすぎだろjk...
Flash
- FlashCS5からiPhoneアプリを作ることができる
- デザイナさんとかは、Flashから入れるのでわかりやすいかも
- 一度Appleの規約改正でNGにされた。その後再改正されて、現在は通るらしい。
- でも、正直いつまただめになるかと思うと不安で不安で・・・
HTML+CSS+JavaScript
- iPhoneブラウザで見てもらう
- 普通のWEB開発の延長線上にあるので入りやすい
- GPSやローカルキャッシュなど、HTML5の機能も使える
- カメラとかファイルアクセスはできない
- iPhoneぽいUIにするのは大変
- AppleStoreに登録することはできない
- モバイラーズオアシスのiPhoneサイトはこの手法で作られています
- 技術的詳細は、iPhoneアプリケーション開発ガイド ―HTML+CSS+JavaScript による開発手法
にだいたい書いてある
jQTouch
- iPhoneブラウザで見てもらう
- 1ページに複数ページの内容を書くなど、ちょっと違うけどまだまだ普通のWEB開発の範疇
- HTML+CSS+JavaScriptでできること(GPS,ローカルキャッシュなど)は当然できる
- カメラとかファイルアクセスはできない
- iPhoneぽいUIにすることができる
- AppleStoreに登録することはできない
jQueryMobile
- みんな大好きjQueryをつかって、iPhone/Android/SymbianなどのブラウザでUIを実現しよう
- まだベータ版。今月あたりに正式リリース?
- 理屈上は、JavaScriptすら動かない環境でも見られるサイトになるそうだけど、その割にjQueryをロードしないといけないとか、正直まだよくわからない
- jQTouchに比べて、幅広い環境で動くらしい
- JavaScriptなので、カメラとかファイルアクセス、AppStoreはNG。
SenchaTouch
- iPhone/Android向けライブラリ
- jQTouch以上にリッチなUIが実現できる
- キャンバス描画ができるので、ソリティアみたいなゲームも登場している
- HTMLとCSSもつかうけど、bodyタグ空っぽのところに、JavaScriptで部品を挿入していくプログラミングスタイル。デザイナさんには厳しいかも。
- JavaScriptなので、カメラとかファイルアクセス、AppStore登録はできない
PhoneGap
- WEBページをiPhoneアプリにしてくれる仕組み。WEBKitブラウザを使って表示する
- カメラとかファイルアクセスのためのAPIも用意してくれる
- UIはjQTouchと組み合わせるのが一般的だと思う
- 当然、AppStore登録が可能
TitaniumMobile
- mogyaイチオシ!
- JavaScriptでプログラムを書くと、iPhoneとAndroidのプロジェクトに変換、ビルドしてアプリを作る
- PhoneGapのようにWebKitでHTML,CSS,JavaScriptのページを使うことも可能
- カメラやファイルアクセスのためのAPIも用意されていて使うことが可能
- AppStore登録も可能
- HTMLやCSSは出番が無くなって、完全にJavaScriptプログラミングの世界なので、デザイナさんとかは無理だと思う
一応、PhoneGapみたいな使い方もできないことはない
あと、発表後のQAで、.NET FrameworkをつかってiPhoneアプリを作るMonoTouchというのもあるよ、と教えていただきました。
今軽く見た感じだと、TitaniumMobileよりもっとObjectiveCよりで、ObjectiveCの開発環境から言語がC#に置き換わった、という感じでしょうか。開発環境が有償なのが注意点になりそうですね。
(2011-01-15追記)動画が公開されました。
TitaniumMobileで簡単にTwitterのOAuthを通すことが出来る(というふれこみの)oauth-adapterというのがあって。
実際この記事通りにするとあっという間にtwitterにつぶやくことが出来る。
Twitter oAuth Implementation for Titanium Mobile « Appcelerator Developer Center
問題なのはその先で。このコード、どうやらPOSTしかできないので、updateはできるけどhome_timelineがとれないみたい。
@chris4403がoauth-adapterを直してはてなAPIで動くようにしたtitanium-hatena-oauth-sampleを参考に、TwitterのGETメソッドも使えるoauth-adapterに直してみた。
mogya/oauth-adapter - GitHub
sendメソッドだけ、元のコードと引数が違います。
- params.url APIのエンドポイント
- params.parameters APIに渡す引数
- params.title 成功/失敗の時に出すダイアログのタイトル
- params.successMessage 成功した時に出すメッセージ
- params.errorMessage エラーだった時に出すメッセージ
- params.method 'POST'/'GET'
つぶやく
//initialization
Ti.include('lib/oauth_adapter.js');
var oAuthAdapter = new OAuthAdapter(
'YOUR_CONSUMER_SECRET_HERE',
'YOUR CONSUMER KEY HERE',
'HMAC-SHA1'
);
// load the access token for the service (if previously saved)
oAuthAdapter.loadAccessToken('twitter');
//OAuth if need.
if (oAuthAdapter.isAuthorized() == false)
{
var receivePin = function() {
oAuthAdapter.getAccessToken('https://api.twitter.com/oauth/access_token');
oAuthAdapter.saveAccessToken('twitter');
};
// show the authorization UI and call back the receive PIN function
oAuthAdapter.showAuthorizeUI('https://api.twitter.com/oauth/authorize?' +
oAuthAdapter.getRequestToken('https://api.twitter.com/oauth/request_token'), receivePin);
}
//TWEET
oAuthAdapter.send({
url:'https://api.twitter.com/1/statuses/update.json',
parameters:[
['status', '@mogyatest test from tmtwit. '+Math.random()]
],
method:'POST',
title:'Twitter',
successMessage:'tweeted',
errorMessage:'tweet failed'
});
GET TIMELINE
//same code for initialization and authrization.
//get timeline
var responce = oAuthAdapter.send({
url:'https://api.twitter.com/1/statuses/home_timeline.json',
parameters:[
],
method:'GET',
title:'Twitter',
successMessage:'success',
errorMessage:'failed'
});
if (responce){
Ti.API.debug(responce);
responce = JSON.parse(responce);
//Enjoy with this responce:-)
}
