naoki86star

インターネットの片隅でなにかしら書いてみる

Androidアプリからoauth2認証通せたらtokenを設定に取り込む

表題のようなことをやってみたら自分にはちょっと大変だった話。

少し汎化した表現にすると、Android端末で、複数Web画面遷移を経た最後の結果をAndroidアプリに取り込む、といったところ。

以下、冗長な背景

 oauth2を使う認証サーバが用意してある。認証はgithub.comとgoogleのアカウントを使えるようにする。実装はpython/tornado使ってるので、googleアカウントのoauth2認証なんかはtornado.webに含まれてる。github.comのは自分でなんとかする。リソース的にはIDだけ使う。oauth2といっても特に他のリソースは参照しない。
 Androidアプリで使うときのweb-APIをtoken認証するつもりで、そのtokenを認証サーバが発行して、Androidアプリに直接取り込みたい。

 当初の脳内作戦では、AndroidアプリからWebUIを起動してgoogle or github.comのログインが通ったら最後にIDとtokenを返す画面にコールバックして、表示された画面の情報をなんとかAndroidアプリで参照しようと試みようとしていた。

 AndroidアプリからWebサービスを組み合わせるには、今どきはWebViewというクラスを使うらしい。最初はブラウザを起動してアプリとブラウザ間でなんとかするのかとかブラウザをハンドリングしつつ別API(直接アプリからHTTPSアクセス)と組み合わせてみることを考えていた。

WebView でのウェブアプリの作成  |  Android デベロッパー  |  Android Developers

 WebViewClientというクラスのオブジェクトから表示したページのhtmlが簡単に参照できるかな思ったら、それはできないようである。これを乗り越えるのに時間かかった。

要点

実現のために自分が到達した要点は結局以下の通り。

  • WebViewClientのjavascriptを明示的に有効にする必要がある
  • oauth2の過程の複数画面遷移に対応するため、WebViewClient#shouldOverrideUrlLoading()をoverrideしておかないといけない。
  • WebViewClientとAndroidアプリの連携ギミックは、(WebViewの)Web画面で動かすjavascriptオブジェクト/関数を目的が達成できるように設計する。

 三番目について、画面ロードしたらonloadでjavascript関数が呼ばれるようにしておく。目的の情報を引数にしておく。その関数は、(web側html側でなく)WebAppInterfaceというクラスで定義する。これがAndroid側のコードなので、アプリ側でしたいことが書ける。これをWebView#addJavascriptInterface()でつないでやる。

 ちょっとアレなのは、先にjavascriptオブジェクトは定義してしまうので、今回都合3画面遷移してる中で万一同名のjavascriptオブジェクトがあるとなにかよろしくなさそうであるが、なのでそれは注意事項ということで。