Intent投げて返りが欲しいときの注意点

| コメント(0) | トラックバック(0)

 画像をギャラリーから取ってこようと思ってstartActivityForResult使ってごにょごにょやってたらonActivityResultが呼ばれたり呼ばれなかったりしたので調べてみたことをメモ。

 適当なActivityを起動して結果を貰いたいときにはstartActivityForResultを使う。

// 画像取得ボタンの実装
// Intentの帰りを受けるためにActivityクラス内で定義する
@Override
public void onClick(View v) {
    Intent intent = new Intent();

    // 画像取得
    intent.setAction(Intent.ACTION_PICK);
    intent.setType("image/*");
    startActivityForResult(intent, 0);
}

 受け取る方は受け取りたいActivityにonActivityResultを書いとくと読んでもらえる。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 0 && resultCode == RESULT_OK) {
        Uri uri = (Uri)data.getData();
        String imgFileName = uri.getPath();

        (略)
    }
}

 で、適当に作って適当に遊んでたらなんとなく動いたのでコードとか誰ともかぶらなさそうなのに変えようと思って変えてみた。

// 画像取得ボタンの実装
// Intentの帰りを受けるためにActivityクラス内で定義する
@Override
public void onClick(View v) {
    Intent intent = new Intent();

    // 画像取得
    intent.setAction(Intent.ACTION_PICK);
    intent.setType("image/*");
    startActivityForResult(intent, 0xDEADBEAF);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 0xDEADBEAF && resultCode == RESULT_OK) {
        Uri uri = (Uri)data.getData();
        String imgFileName = uri.getPath();

        (略)
    }
}

 でもこれだとonActivityResultが呼ばれない。なんでやねん。
 で、差を見て理由がわからなかったので調べてみた。

 まずstartActivityForResultのコードを見てみた。ソースはAOSPから拾ってきたICSのr1。
 ※markdownで書いてる都合上4スペースを1タブで変換してます。

Activity.java: startActivityForResult

        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }

 上記の通りstartActivityForResultではsendActivityResultで結果を返す。
 sendActivityResultが呼ばれるためにはexecStartActivityからActivityResultが返ってこないといけない。
 execStartActivityの中身を見てみると、ActivityResultオブジェクトを返すところが以下のようになっている。

Instrumentation.java: execStartActivity

                final ActivityMonitor am = mActivityMonitors.get(i);
                if (am.match(who, null, intent)) {
                    am.mHits++;
                    if (am.isBlocking()) {
                        return requestCode >= 0 ? am.getResult() : null;
                    }
                    break;
                }

 ActivityThreadが監視しているActivityMonitorの数だけ上記のコードが回されるんだけど細かいところはおいといて、returnのところを見るとリクエストコードが非負の整数でないと結果を返そうとしていない。
 リクエストコードはstartActivityForResultで渡している値なので、試したコードを再掲すると。

// 画像取得ボタンの実装
// Intentの帰りを受けるためにActivityクラス内で定義する
@Override
public void onClick(View v) {
    Intent intent = new Intent();

    // 画像取得
    intent.setAction(Intent.ACTION_PICK);
    intent.setType("image/*");
    startActivityForResult(intent, 0xDEADBEAF);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 0xDEADBEAF && resultCode == RESULT_OK) {
        Uri uri = (Uri)data.getData();
        String imgFileName = uri.getPath();

        (略)
    }
}

 ばっちりリクエストコードが負の整数!
 そりゃないぜセニョール! と思ってAndroid Developersを確認してみたら。。。

Parameters intent The intent to start. requestCode If >= 0, this code will be returned in onActivityResult() when the activity exits.

 ばっちり書いてあった(ノ∀`)アチャー
 いつものことだけどドキュメントよく読めってことですね。サーセンwwwww

トラックバック(0)

トラックバックURL: http://www.nagatsuki-do.net/blog2/mt-tb.cgi/482

コメントする

このブログ記事について

このページは、あおいたんが2012年2月 6日 22:24に書いたブログ記事です。

ひとつ前のブログ記事は「[渋谷]らーめん金伝丸 特丸」です。

次のブログ記事は「[渋谷]つけ麺大臣 鶏白湯そば」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

OpenID対応しています OpenIDについて
Powered by Movable Type 5.11