ワンボタンの声 for iPhoneをAppStoreの審査に提出しました

長らくお待たせしました。最初に思い立ったのが去年の秋。半年とはいかないまでも5ヶ月かかっちゃいましたね。

番組中の一言に反応してはじまったこのプロジェクト。ワンボタンのメンバーのみなさんだけでなく、いろいろな方の協力を得てようやくここまできました。

とはいえ、提出したところなので、審査を通過したわけではなく、したがってまだ公開されてないですが、とにかく、こんな感じのものに仕上がりました。

ニュースサイトの専用リーダーがあるようにPodcast番組の専用プレーヤーがあってもよいと思うのです。特にPodcastは公開ブログにいろいろ関連情報が載っていることが多く、あとでチェックしようと思っていても結局見ないままでいることとかって多いですよね。そういうのもったいないですしね。

そういう意味で、専用プレーヤーとしてだけでなく、関連情報収集ツールとしてもリスナーのみなさんのお役に立てればと思います。

ここがようやくスタートラインです。私も一リスナーとしてまだまだ進化させていきたいと思いますので、ご意見ご要望などどしどしお願いします。(あ、だから、まだ公開されてないんですけれど・・・なので、予断は許さないわけですが)

公開をお楽しみに!

twitterクライアント : Hummings v2.0b1 公開しました

hummings_title.png

というわけで、ついにβ版です。まあ、そうは言ってもそんなに違いはないのですけれど、気持ちの問題ですかね。

変更点

  • 10.5 Leopard でwebが開けない問題を修正
  • ユーザーのアイコンが古いままになることがある問題を修正
  • GUI修正

基本的にa13からのバグ修正のみになります。a13で搭載した正規表現が10.5と10.6で若干挙動が異なっていたようで、そのせいで10.6で動いても10.5で動かないという自体になってしまいました。ユーザーのみなさんご迷惑をおかけしました。

なんというか、そもそも家に10.5の環境がないというのが一番の問題なんですけどね。なので、家でコンパイルして、翌日の仕事の昼休みに会社の10.5のマシンで動かして、、、というプロセスを数日繰り返して、ようやくなんとかなりました。SDカードからの10.5起動にでも挑戦してみるかなあ、という今日この頃です。また、そんな中、テストに協力していただいたユーザーのみなさん、どうもありがとうございました。

なんにしても、ようやくβです。気持ちだけの問題とはいえ、これからもどうぞよろしくお願いします。

シンプルな twitpic 専用 iPhoneクライアント TwitPict v1.2 を公開しました

実に8ヶ月ぶりのアップデートとなりました。

もともとシンプルであるがゆえに、そんなに機能追加するものでもないと思うのですが、最近ネットや書籍でよく取り上げられるようになったこともありまして、かねてから思っていたこまごまとした変更を行いました。

変更点

  • 投稿写真の端が1px欠けることがある問題を修正
  • 撮影後に落ちることがある問題を修正
  • ツイートの残り文字数表示
  • ハッシュタグ #TwitPict の自動挿入
  • 日本語ローカライズ追加
  • GUIの改善

avail_on_app_store.png

ようやくローカライズもしたのでスクリーンショットをOS3系ベースで撮り直し。

TwitPict_v120

ハッシュタグの自動挿入についてはいろいろとご意見があるかとは思っています。ただ、ON/OFFするほどのものでもないなあ、というのもありましたし、これで、どれだけのアクティブユーザーさんがおられるのかがざっくりわかるので、それが開発の励みになるんですよね。そういうわけでご了承下さいませ。

実際、今朝公開されたこのアップデートですが、#TwitPict で検索すると私が思っていたよりもたくさんの皆さんが普段から使われているのがわかりました。ほんと、嬉しい限りですね。

今回の審査はこんな感じ。

  1. 3/8: 提出
  2. 3/9: in Review
  3. 3/11: ready for sale

アップデートの場合は、だいたい、夜に提出して3日後の朝には Rfs というのが最近のペースですかね。

アップデートされる方も、新規の方も是非どうぞ。

TwitPictが本日発売の新書「ツイッターを使いこなす」に掲載されました

初の新書掲載。

4537257474 携帯&iPhone ツイッターを使いこなす! (日文新書 43)
日本文芸社 2010-03-06

by G-Tools

TweeieやTweetDeckなどの有名クライアントが紹介されている中、こんな感じで1ページ割かれていました

twitpict_on_twitter_book_201003

機能を絞ったおかげで、紹介する側としてもやりやすいんですかね。ありがたいことで、掲載していただき感謝感謝です。

avail_on_app_store.png

最近取り上げられることが多くなったから、というわけではありませんが、現在v1.2を開発中です。新機能がついたというわけではないものの、使い勝手はよくなったんじゃないかと思っています。ここ数日中に提出予定なので、うまくいけば来週中には公開されているかもしれません。お楽しみに。

twitterクライアント : Hummings v2.0a13 公開しました

hummings_title.png

お待たせしました。ついに(やっと)favoriteに対応しました。

変更点

  • favoriteに対応
  • 短縮URL (j.mp) 対応
  • つぶやきが複数URLを含んでいても “w” キーで全部開けるように
  • 内蔵ブラウザで閲覧中にTL更新されてもwebをリロードしないように
  • 同じつぶやきが Growl 通知され続ける問題を修正

favoriteは新しいタブが作成されてこんな感じになります。”f” キーでON/OFFのトグル。

Hummings2_timeline_favorite

短縮URLは j.mp (bit.ly) 固定ですが、設定から常に短縮するかどうかを選択できます。デフォルトでは140文字を越える時だけ短縮します。

詳しくは上記 Humming2 のページをご覧下さい。

長らくα版でしたが、今回のバージョンを最後のα版としたいと思います。(だからといって、どうというわけじゃないんですけれど、気分の問題で)

TwitPictが本日発売の「iPhoneカメラライフ」に掲載されました

4861006902 iPhoneカメラライフ
ビー・エヌ・エヌ新社 2010-02-22

by G-Tools

拙作の TwitPict が本日発売の「iPhoneカメラライフ」に掲載されました。

名前の通りiPhoneのカメラで楽しもう!という主旨の本なのですが、有名なカメラアプリに紛れて、一番最後の “twitterに投稿する” というコーナーにて写真を簡単に投稿できるアプリとして紹介されました。

20100222_iphone_camera_life

iPhoneのカメラといえば、200万画素だったり300万画素だったりで、最近のデジカメからするとものすごくスペックは低いようにみえますが、そこを補うかのようにたくさんのカメラアプリがでていますし、そんなカメラアプリで写真を撮るというのも一つの魅力ですよね。(ま、私のTwitPictは違いますけれど・・・)

最後になりましたが、掲載していただきありがとうございました。

avail_on_app_store.png

twitterクライアント : Hummings v2.0a12 公開しました

hummings_title.png

ものすごく久しぶりのアップデートです。そして致命的な問題を修正しました。

変更点

  • 使用し続けると動作が重くなる問題を修正

なにか、最近ずいぶんと動作が重いなあ、、、と思っていたら、、、ものすごく根本的なところに問題がありました。もうなんとも言い訳のしようがない感じです。ユーザのみなさんどうもすいません。

これでまた普段使いのクライアントとして復帰していただければと思います。

しかし、3ヶ月ぶりにソースを見ましたね。定期的にメンテしないとダメですね・・・いろんなプロジェクトに手を出し過ぎなのが問題で・・・

そんなわけで、不定期更新ですが、これからもどうぞよろしくお願いします。

Cocoa と twitter と OAuth に関する覚書

いろいろと話題のOAuthですが、その意義とか仕組みとかはさておき、実際に実装してみようと思ったときに、ややこしいのはsignatureを作ってリクエストを生成するところなので、そのあたりをざっとメモっておきます。

あくまで個人的な覚書なんで、より詳しくは本家のサイトを参照してください。OAuth Core 1.0a


以下、NSString を ‘&’ や ‘=’ で連結しているかのような記述がありますが、単なる文字連結のイメージですのでご了承下さい。

はじめに

全体を通していえることですが、すべてのGET/POSTパラメータは key, value ともにURLエンコードされている必要があります。(実際 key のほうは不要であることが多いですが)

OAuthでのURLエンコードはRFC3986準拠ですので注意しましょう。CFURLを用いて例えばこんなふうにできます。

CFStringRef encoded = CFURLCreateStringByAddingPercentEscapes(
    kCFAllocatorDefault,
    (CFStringRef)str,
    nil,
    CFSTR(":/?=,!$&'()*+;[]@#"),
    kCFStringEncodingUTF8);

以下、http://twitter.com/statuses/user_timeline.xml?screen_name=itok_twit にアクセスすることを前提にメモっておきます。

標準パラメータ

OAuthの標準パラメータとして、以下のようなものがあります。(GETなりPOSTなりで渡す必要があります)

oauth_consumer_key
twitterでアプリを登録したときにもらえる値。そのまま使います
oauth_nonce
ユニークな文字列を作成。タイムスタンプでもよいけれど、より確実にUUIDを使うとか
CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef nonce = CFUUIDCreateString(kCFAllocatorDefault, uuid);
CFRelease(uuid)
oauth_signature_method
twitter は HMAC-SHA1 固定
oauth_timestamp
タイムスタンプ。 time(NULL); の返り値でOK
oauth_version
1.0固定

signature

signature の元となる signature base は分解した link や normalized parameter を元に ‘&’ で結合します。

NSString* base = [HTTP method]&[my_urlencode_rfc3986(link)]
    &[my_urlencode_rfc3986(parameter)];

ここで link はいわゆる query をのぞいた部分。

NSString* link = @"http://twitter.com/statuses/user_timeline.xml";

normalized parameter は POST/GETパラメータ(標準パラメータ含む)を全部key=valueの形にして昇順ソートし、それを ‘&’ で結合して1つの文字列にしたものです。

NSString* parameter = [key1]=[val1]&...;
/* oauth_consumer_key=xxxx&oauth_nonce=xxxx&
   oauth_signature_method=HMAC-SHA1&oauth_timestamp=123456&
   oauth_version=1.0&screen_name=itok_twit */

次に HMAC で使う key も ‘&’ で結合。

NSString* hmacKey = [my_urlencode_rfc3986(consumer secret)]
    &[my_urlencode_rfc3986(token secret) *なければ空文字];

signature base と HMAC key から HMAC-SHA1 ハッシュを生成し、これを Base64 エンコーディングしてURLエンコードして signature とします。

NSString* digest = my_hmac_sha1(base, hmacKey);
NSString* base64 = my_base64_encode(digest);
NSString* signature = my_urlencode_rfc3986(base64);

パラメータに oauth_signature=signature を追加して、最終的にアクセスするURLの出来上がり。

備考

  • POSTは ContentType: application/x-www-form-urlencoded で行う
  • より詳しい例は本家の Appendix 参照

と、ざーっと書き連ねてみました。手元で動いている現状のソースから引っ張ってきたので多分大丈夫と思いますが、なんかおかしかったら教えてください(いつでも弱気)

iPhoneとTwitter OAuth認証の流れについて

twitterヘの認証方式は2つありまして、1つはお馴染みBasic認証。もう1つがOAuthです。で、なにやら、今後はOAuthしか受け付けなくなるとかいう話があって、ちょっと盛り上がっているtwitterクライアント界隈。

OAuthの細かい話はさておき、twitterのOAuth認証(access_token取得)の手順には2通りがあります。(太字はiPhone上での主な挙動)

サーバ型

  1. アプリごとの key から request_token 取得
  2. request_token を用いて twitter のサイトを表示
    → MobileSafari起動
  3. ユーザにログインしてもらう
  4. 設定していた callback URL が呼び出される
    → サーバ側で元アプリの URL scheme にリダイレクトし、元アプリを起動
  5. callback に渡された oauth_token から access_token を取得
    → アプリ起動時に渡された URL から access_token を取得

クライアントアプリ型

  1. アプリごとの key から request_token 取得
  2. request_token を用いて twitter のサイトを表示
    → 内蔵ブラウザで表示
  3. ユーザにログインしてもらう
  4. サイトに表示されたPINをアプリに入力してもらう
    → ユーザがブラウザ外のフィールドに別途入力
  5. 入力された PIN から access_token を取得

まあ、セキュリティ云々の話は別として、どっちもどっちだと思うわけです。サーバ型ではアプリをいったん離れなければなりませんし、クライアントではPINを入力するという手間がかかります。

じゃあ、アプリを離れることなしに、サーバ型の方式は使えないのかと思って試してみました。

やってみたこと

UIWebView の delegate でアクセス予定の URL を取得できます。ここで、指定していた callback URL にアクセスしようとしていたら、そこから oauth_token パラメータを取り出せるのではないかと考えました。

結果

予想通り、UIWebView の delegate で (4) の callback 呼び出しをとらえて、そこから oauth_token を取得することができました。これだと操作がアプリ内蔵の UIWebView だけでとじているので、アプリの切替もPINの入力も要りません。極端な話、callback URL 先の実体すら不要です(存在しないURLを指定していても大丈夫のようです←実際にアクセスする前に request を止めるので当然といえば当然ですが)

delegate 内はこんな感じで。

- (BOOL)webView:(UIWebView *)webView
    shouldStartLoadWithRequest:(NSURLRequest *)request
    navigationType:(UIWebViewNavigationType)navigationType {
    if ([[request.URL host] isEqualToString:@"callback.example.com"]) {
        NSString* query = [request.URL query];
        NSArray* arr = [query componentsSeparatedByString:@"="];
        if ([arr count] > 1 && 
            [[arr objectAtIndex:0] isEqualToString:@"oauth_token"]) {
            NSString* token = [arr objectAtIndex:1];
            // do something
        }
        return NO;
    }
    return YES;
}

OAuthの運用上、あるいはセキュリティ上の問題があるかもしれませんが、それらをさておいたとして純粋にユーザ視点にたてば、これが一番スマートなのではないでしょうか、と。

あとは、twitterのログインページがiPhoneに最適化されれば問題ないんですけれど・・・

***一応、手元で開発中にアプリでは問題なく動いているんですが、なんかおかしかったら教えてくださいませ。