読者です 読者をやめる 読者になる 読者になる

@neiraza

2匹の怪獣が寝た後にプログラマーしてる、最近はサイバーエージェントでゼミ長もしてる僕のネタ帳

Androidで遷移元へ帰ろう→コールバックされない→恥死

ものすごくハマーン様だったので、ここに記す。

道を見失う

やりたいこと

ある画面上(遷移元)で、設定画面(遷移先)を呼び出した後、遷移元の画面に戻る。
Androidだと設定画面は、PreferenceActivity を使って作ると思う。

つまり

Activity A から PreferenceActivity Bを呼び出し、
onKeyDownKeyEvent.KEYCODE_BACKをハンドリングしたり、
適当な「戻る」ボタンとか用意して、戻られ。

やっちまったこと

戻るってことは、遷移元のonActivityResultが呼ばれんだろ?って思ってた自分。

実装

遷移先でオプションメニューのとこに「戻る」を用意して、戻ろうかと。

遷移先
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    Log.d("bakakato", "どうしましたかご主人様");
    int itemId = item.getItemId();
    switch (itemId) {
        case R.id.hoge:
            Log.d("bakakato", "ぼく、戻りたいんです。あの頃に。");
            Intent intent = new Intent();
            intent.putExtra(BUTA, "飛べない豚は本当に屑でどうしようもない糞豚野郎");
            this.setResult(RESULT_OK, intent);
            this.finish();
            return true;
        default:
            Log.d("bakakato", "default");
            return super.onOptionsItemSelected(item);
    }
}
遷移元
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    switch (resultCode) {
        case RESULT_OK:
            Log.d("bakakato", "result ok");
            break;
        case RESULT_CANCELED:
            Log.d("bakakato", "esult canceled");
            break;
        default:
            Log.d("bakakato", "default");
    }
}

結果

挙動だけでいうと、遷移元に戻ってます。
でも、onActivityResult氏を通りませんhhh

運良く道が開けるも・・・と思った矢先の3重苦

やっちまった その1

仕様的にコールバック受ける必要ないし、BACKキーと同じ実装で良いわけで。
何やってんだよタハーとか思いつつ、実装部分をみると・・・

やっちまった その2

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        saveSettings();
    }
    return super.onKeyDown(keyCode, event);
}

エクレアより前の時代か、死にたいw
あー、開いてはいけないパンドラの箱だったのかもorz
エクレア以降って、dispatchKeyEventでやるって通説ですよね?

やっちまった その3

年末に落としたAndroidのソース(Activity部分)を読めばOKOK・・・、
落としたソースがサーバから消えた、もう死にたい。

ソースはこんな感じだったはず

Activity#onKeyDownの中で、Build.VERSION_CODES.ECLAIRとかしながら、
エクレアより前だとonBackPressedが呼ばれて、
エクレア以降だとonBackPressedが呼ばれずフラグ立ててから、
最終的にonBackPressedが呼ばれるとかだったような。

本題に戻る

「戻る」をタップしたら、遷移元に戻るってのは、
BACKキーで戻ると同意ってことで、こんな実装で解決。

遷移先
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    Log.d("bakakato", "どうしましたかご主人様");
    int itemId = item.getItemId();
    switch (itemId) {
        case R.id.hoge:
            Log.d("bakakato", "ぼく、戻りたいんです。あの頃に。");
            <span style="color: #cc0000">this.finish();</span>
            return true;
        default:
            Log.d("bakakato", "default");
            return super.onOptionsItemSelected(item);
    }
}
遷移元
//@Override
//public void onActivityResult(int requestCode, int resultCode, Intent intent) {}

未解決事項を整理

onActivityResultが呼ばれません隊長

たぶん、なんだけど

僕の実装て、Activity A から PreferenceActivity Bに遷移する際に、
コールバックして欲しいんだよねって、熱いメッセージが無いんじゃないかと。
onResumeの前に呼ばれるはずなんだしね。

僕の実装。なんでこんな感じなのかは置いといて。

遷移先(B)
@Override
public static void actionSettings(Context context, String buta) {
    Intent i = new Intent(context, B.class);
    intent.putExtra(BUTA, buta);
    context.startActivity(i);
}
遷移元(A)
private void hoge() {
    B.actionSettings(context, buta);
}

Context#startActivityのリファレンス見たけど、やる気ゼロッテ感じ。

Launch a new activity. You will not receive any information about when the activity exits.
Note that if this method is being called from outside of an Activity Context, then the Intent must include the FLAG_ACTIVITY_NEW_TASK launch flag. This is because, without being started from an existing Activity, there is no existing task in which to place the new activity and thus it needs to be placed in its own separate task.
This method throws ActivityNotFoundException if there was no Activity found to run the given Intent.

http://developer.android.com/reference/android/content/Context.html#startActivity(android.content.Intent)

Activity#startActivityも見たけど、一緒。
あれ、Context#startActivityForResultってあったけ。

Launch an activity for which you would like a result when it finished. When this activity exits, your onActivityResult() method will be called with the given requestCode.

http://developer.android.com/reference/android/app/Activity.html#startActivityForResult(android.content.Intent, int)

oh...

呼ばれていないのはなく、呼ばないやつを使ってたことか。
Contextクラスには、コールバックを呼ぶやつは実装されていないみたいだし。


まじ、消え去りたい。