[iOS] タブを残さずURLスキームを開く

TitaniumのユーザーBBSで、ChatWork のiPhoneアプリの挙動が話題になっています。

ChatWork の謎 | Don’t Fall – Titanium Mobileユーザー会サポートBBS

ChatWorkアプリでは、facebook認証でアプリを使うことが出来るのですが、これまでよく使われていたWebView上での認証ではなくて、Ti.Platform.openURL() を使ってブラウザを立ち上げてfacebook認証を行っています。

WebViewを使わない理由は、「OAuthの認証にWebViewを使うのはやめよう – Shogo’s Blog」に書かれているとおりだと思います。具体的な実装としてChatWorkアプリはとても参考になりますね。

さて、ブラウザ上でfacebook認証が成功すると、ChatWorkサーバはURLスキームを使ってChatWorkアプリケーションを起動させます。
ここがマニアックに興味深いところです。

  • ユーザーはリンクをクリックしていないのに、なぜURLスキームが起動したのか?
  • ChatWorkからブラウザに戻ったとき、URLスキームを起動したWEBページが残っていないのは何故?他のアプリだと残っちゃうよね?

結論から言うと、こういうふうに書けば同じ挙動が再現できました。

(本当は”chatwork:///”でChatWorkアプリが起動するのですけど、テストのために意味不明な起動を繰り返すとご迷惑になりそうだったので、メッセージアプリを起動しています)

ページを読み込むと同時にURLスキームを起動させる

 URLスキームは普通、aタグのhrefに書いて、ユーザーさんにクリックしてもらって使います。例えば、

<a href="sms:///">sms</a>

と書かれたHTMLのリンクをユーザーさんがクリックすると、メッセージアプリが立ち上がります。でも、facebook認証が済んだら、ユーザーさんの手を煩わせることなくアプリケーションに戻ってほしいですよね。

 location.hrefで強制移動とか、aタグを書いてjQuery(hoge).click();とか、いろいろ試してみたのですけど、そういうのは駄目なようです。
ページ内に動的にiFrameを生成してURLスキームを持たせることで上手く起動させることが出来ました。

URLスキームを起動したあと自分を閉じる

 URLスキームでアプリを起動したのはいいものの、そのHTMLがブラウザ上に残ったままになっていると、あとでブラウザを開き直した時に変なページが見えてしまったり、場合によっては勝手にアプリが立ち上がってイラっとさせられることがあります。結構有名なアプリでもこの現象起こしますよね。

 JavaScriptで自分を表示しているタブを閉じる場合、理屈上はwindow.close()で出来るのですけど、safariのwindow.closeはjavascriptで開いたページしかclose出来ないので、このようなごまかしテクニックを使うことで自分をcloseすることが出来ます。

window.opener = window;
var win = window.open(location.href,”_self”);
win.close();

URLスキームとwindow.close、どっちかが他方を妨害しそうな気がしますけど、実際には両方上手く動くみたいです。

P.S 1:自分でJavaScript書いて同様の挙動を再現させることに成功しただけなので、ChatWorkさんのアプリと厳密には一致しないかも知れません。
P.S 2:[iOS]って書いてますが、URLスキームをintentに変えればAndroidでもそのまま動作しました。
P.S 3:ChatWorkの中の方、出来るだけ迷惑かけないように調査したつもりですけど、不審なログとして調査対象に上がっていたりしたらごめんなさい。