ついにFragmentに入門したわけですが、早速ハマったのでメモしておきます。サポートパッケージェ・・・。
※本エントリはandroid.support.v4.app.Fragmentに関する動作について書いています。android.app.Fragmentでは以下に書いている問題は発生しません。
FragmentでstartActivityForResultが使える
Fragmentって便利ですねー。特にActivityにベッタリ書いていた様な実装をFragmentに分けて色々捗らせる事が出来る点がとても助かります。で、Activityに書いていた処理をFragmentに集約する時に問題になるのがstartActivityForResultによって処理を委譲している部分です。
FragmentではstartActivityやstartActivityForResultやonActivityResultが用意されており、FragmentからActivityを起動したり、結果を受け取る事ができます。
という事でまぁ問題なくねーと思いがちですがしかし、FragmentのstartActivityForResultには罠があるんですねーーーー!
リクエストコードは下位16bitの範囲で
まず以下のコードをFragment内で実行してみます。なんの変哲もない、アドレス帳を起動して選択結果を受け取るだけのIntentです。
private final static int REQUEST_CODE = 0x11111; public void pick() { Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI); startActivityForResult(intent, REQUEST_CODE); }
し、死んだー!
Can only use lower 16 bits for requestCode
なにーー!
そうですFragmentではstartActivityForResultの第二引数に与えるリクエストコードを下位16bit以内に収める必要があります。
つまり0x0000〜0xffffまでの間の値にしろ、という事ですね。上記コードは"0x11111"だったのでダメだったんですね。
リクエストコードは下位16bitの範囲で。
onActivityResultが呼ばれないパターン
こういう罠にはまるのは僕くらいのものな気がしますが、サポートパッケージのFragmentのstartActivityForResultではonActivityResultが呼ばれないパターンがあります。
親となるActivity側がonActivityResultをオーバーライドしている場合に起きるのですが・・・。
コードを見てみます。問題無いようなあるような・・・。
親となるActivity側
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data){ switch (requestCode) { case REQUEST_CODE: //なにもしない break; case MOGE: //~処理~ break; } }Fragment側
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_CODE: if(resultCode == Activity.RESULT_OK){ Log.d(TAG, "okkkk!"); } else{ Log.d(TAG, "ooooops!"); } break; } }
このコードの場合Fragment側のonActivityResultが呼ばれません。何故か?
super.onActivityResultを忘れているから!
そうです。親Activity側のsuper.onActivityResultを呼んでませんでした。
サポートパッケージでFragmentを使う場合はActivityではなくFragmentActivityを継承する必要があります。
このFragmentActivityのonActivityResultでFragmentに結果を渡しているのでsuper.onActivityResultを呼んであげないとFragment側にonActivityResultの呼び出しが行かないんですねー。
正しくは
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data){ super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQUEST_CODE: //なにもしない break; case MOGE: //~処理~ break; } }
問答無用でsuper.onActivityResult。
まとめ
コンパーチビリティの為のサポートパッケージですがなかなかどうして、大変ですねー。