March 01, 2009
最近、iMovatwitterというiPhoneアプリを出しました。
iPhoneのブラウザは携帯電話のようにGPSやデジカメとインテグレーションすることを考えられていないので、GPSを使った「イマココ」や、デジカメと連携する「写ツ」をiPhoneで使うためにアプリ側で吸収しました。
このアプリでやりたかったことの一つが、UIWebViewというブラウザコントロールとWebサービス/アプリとの連携でした。
UIWebViewというのは、SafariをiPhoneアプリ内に組み込むコントロールです。
丁度、Flash PlayerをHTMLに組み込むようにWebブラウザをiPhoneアプリ上に表示することができます。
このiPhoneアプリ上のWebブラウザとWebサービスの主な連携ポイントとしては、大きく3つあります。
1.iPhoneアプリからWebページを制御する
2.Webページのメタデータを通じて、iPhoneを制御する
3.ページのリンクをクリックすると、iPhoneアプリのUIが動作する
というものです。
以下にその説明をしていきたいと思います。
1.iPhoneアプリからWebページを制御する
(JavaScript injection)
UIWebViewを使うとアプリ側からJavaScriptを実行することができます。
単純にページに組み込まれているJavaScriptを起動することもできますが、ブックマークレットのようにJavaScriptを注入して動作させることができます。
例えば以下のようなコードがあります。
[webView stringByEvaluatingJavaScriptFromString: @"function mova_actr(){ var aTags = document.getElementsByTagName('a'); for (var i= 0 ; i < aTags.length ; i++){ if (aTags[i].target){aTags[i].target='_self'; } } return true;}; mova_actr();" ];
これはページ内リンクのtargetの値を、_selfに向ける処理です。
このコードは割と実用的な問題解決のサンプルで、UIWebViewはtarget=_blankのリンクに対してページ遷移できないという問題があったので、新たなWebページが表示されるたびに、このようなJavaScriptをiMovatwitterから注入して対処します。
iPhoneのSafariでtarget=_blankがあると別ウインドウが開くと思いますが、UIWebView単体は「一画面のブラウザ」なので、そういう制御には対応していないようなので、このような対処を行いました。
ちなみにtarget=_blank問題については、以下のページで無理矢理イベントを取得する方法が公開されています。
sonson@Picture&Software - [iPhone SDK] Avoid target="_blank" problem
2.Webアプリからメタデータを通じて、iPhoneを制御する
(semantic web application)
先ほど紹介したJavaScriptを実行する処理は、JavaScriptの実行結果を戻り値として取得することができます。
以下のような処理を、「ページが表示された直後」のイベントで実行しています。
- (void)webViewDidFinishLoad:(UIWebView *)webView {NSString *comString=[webView stringByEvaluatingJavaScriptFromString:
@"function a(){
l=document.getElementsByTagName('meta');
for(i=0;i<=l.length;i++)
{if(l[i].name=='iphone-command') return l[i].content
}
};
a();"];
}
metaタグにiphone-commandという名前を追加すると、その文字列がiPhoneアプリに渡されます。
このような機能を使って、写ツやイマココの送信先URLをサーバーサイドで制御するようなことを考えていました。
もしiMovatwitterを汎用ブラウザとして機能させた場合、Webページのmetaタグにそのような写ツの送信先アドレスを渡すことで、写真を送る処理が自由に使えるようになります。
multipartで送る変数名だけ知っていれば、どんなWebサイトへも写ツの写真送信機能が使えるようになるわけです。
また写ツコマンドを渡すことで、iPhone上には写ツのボタンが表示されます。
つまり、Webサイトのメタ情報によって、iPhoneアプリの挙動が変わるわけです。
これを応用するとWebサイト上の住所や電話番号に応じて、iPhone上のデータを呼び出したり音楽を再生したりすることができるのではないでしょうか。
また、microformatsで統一されたメタ情報が付与されていれさえすれば、iPhoneアプリ側で、その情報に対する適切な処理ができるということです。
今まで、「GoogleやMSのブラウザが対応しないとできないよね!」なんて思っていたことがiPhoneアプリで実現できます。
3.ページのリンクをクリックすると、iPhoneアプリのUIが動作する
モバツイでは誰かのつぶやきにreplyをする場合、「Re:」というリンクを押すと、一旦、ページ遷移しHTMLによるフォームに「@だれそれ」が入力されて簡単に返信を書くことができます。
iMovatwitterでは、「@だれそれ」がプリセットされたつぶやき入力用のダイアログウインドウが表示されるのでページ遷移なくreplyを書けます。
ここでカメラで撮った写真を添付したり、GPSを使った住所文字列を追加することができます。
これを実現するのはなんてことなくて、UIWebViewには、shouldStartLoadWithRequestイベントというページ遷移前に呼び出されるイベントがあるので、そこでURLを調べて該当するボタンのURLだったら、URLのパラメータやRequestの内容を取得して、iPhoneアプリのウインドウ表示するようにし、URLのリクエストそのものはキャンセルしてしまえば良いのです。
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { 〜省略〜 if ([sUrl rangeOfString:@"/log?atuser="].location != NSNotFound ){ [self showPostWindow:initMes picture:nil replyId:reply_id]; return NO; } }
一旦送られたリクエストの中身を入れ替えて、再度リクエストを投げることができるので、ヘッダを付与したり、URLを書き換えてしまうことも可能です。
◆もっといろんなことができる
UIWebViewでWebページを読み込んで、その内容に応じてiPhoneアプリの挙動を変えたり、他のデータと連係をするというのは、もっといろんなことができると思うんですよね。
特にmicroformatsによって面白い動きをするアプリが簡単に作れるので、ここはアイディア如何だと思います。
microformatsのようなメタデータの拡張はアプリが先導して利便性を作ることで、徐々に多くのWebサイトに対応されていくものですが、PCのWebブラウザだとどうしてもgoogleやMS頼みになってしまいますが、iPhoneアプリであればモバイルという利便性の上で、自分たちで世界を作り出すことができます。
普及させる流れはシンプルで、まずは小さな世界で、iPhoneアプリとWebサイトの組み合わせたアプリがヒットすることが第一。そして、その世界を徐々に拡張していき、対応する人たちとユーザーと自分たちとの間にwin-win-winの関係が作れるのであれば十分、普及しうるのではないでしょうか。
本当はセカイカメラのようにすごいデモが作れればもっちょっとわかりやすく世界観までご提案できるかと思うのですが、僕が現状、提供できるのはiMovatwitterまででした。すいません。
なお余談ですが今は、iMovatwitterが他のtwitterクライアントアプリに劣らぬ機能を実現するようWebアプリの方を重点的にアップデートしています。リリースするまではモバツイの画面に条件分岐をした程度だったのですが、リリースしてすぐにiMovatwitterのViewのテンプレートは完全にモバツイ本体から分離させました。AjaxによるUIを実現するためです。
それをやったおかげで、AjaxはもちろんCSS3を使うことができるようになりました。
早速、CSS3の角丸などを使ってフキダシ調のUIに変更しています。
またSafariはSQLiteも使えるそうですからオフラインにも対応したいと思っています。