2013年9月1日日曜日

startActivityForResult で返却された結果(Intent)が反映されなくて大ハマリした件

Android で twitter 連携しようとしたときのはなし。

twitter4j を使ってるんですが、 twitter ってヤツは初回にアカウントの
認証が必要なんすね。

んで、認証の処理の流れは大体以下のような感じになってます。

  1. 認証オブジェクトを用意
  2. 認証オブジェクトとコールバック用URIから認証ページURL生成
  3. 認証ページを startActivityForResult で開く
  4. 認証ページで「連携アプリを認証」ボタンを押すと元のアプリに戻ってくる
  5. Intent にセットされている URI を取得
  6. URI にくっついてる verifier(文字列) を取得
  7. verifier とか使ってアクセストークンを取得
  8. 以降、各種 Twitter API を使うときはアクセストークンを使用
※細かいことは↓とか見ると吉。
 Android再入門 - Twitterクライアントを作ってみよう - OAuth認証

で、問題は3~5の部分。

3で startActivityForResult を呼び出した Activity と
5で Intent を受け取る Activity が異なる場合は問題ないんですが、

3と5が同じ Activity の場合(全く同じ画面に戻ってくる場合)に、
なぜか Intent に URI がセットされていない???


で、さんざんハマったワケですが、ようやく原因がわかりまして。

既に存在する画面に対して startActivity(Intent) を実行した場合、

 onNewIntent(Intent) → onResume()

の順に呼び出されるんですが、この onNewIntent のソースを見たところ、

protected void onNewIntent(Intent intent) {
}


・・・・・・何もしてねぇ!!


要は新しい intent に更新されない=初回 onCreate 時のままなんで
Intent に URI が存在しない、と。何この超絶トラップ。


しかもそういう仕様だとかしっかりソースにもコメント書いてやがります。

 Note that {@link #getIntent} still returns the original Intent.
 You can use {@link #setIntent} to update it to this new Intent. 

 →getIntent は相変わらず元の Intent 返すかんね。
  更新したかったら setIntent 使ってね。


てことで対応策としては Intent 受け取る Activityで onNewIntent を
オーバーライドするなりして setIntent 呼んでやりゃいいだけの話みたいですが。

@Override
protected void onNewIntent(Intent intent){
    setIntent(intent);
}


それにしてもなんでまたこんな仕様になってるんですかね??

察するに、「単に画面遷移で startActivity 呼ばれた時に更新かけちゃうと
元の intent の情報が消えちゃうから」とか??


ちなみに初回画面作成時は onNewIntent 自体呼ばれないんで、
常に intent の値をチェックするなら最低2箇所に処理書かないといかん、と。

うーん、なんとも初心者には釈然としない話ですなぁ…。
なんか真っ当な事情があっての仕様なのかしらん。

0 件のコメント:

コメントを投稿