Jak zwrócić wynik (startActivityForResult) z działania TabHost?

275

W moim przykładzie mam 3 klasy: klasa A, główna aktywność. Klasa A wywołuje startActivityForResult:

Intent intent = new Intent(this, ClassB.class);
startActivityForResult(intent, "STRING");

Klasa B, ta klasa to TabActivity:

Intent intent = new Intent(this, ClassC.class);
tabHost.addTab...

Klasa C, ta klasa jest normalną działalnością:

Intent intent = this.getIntent();
intent.putExtra("SOMETHING", "EXTRAS");
this.setResult(RESULT_OK, intent);
finish();

onActivityResult jest wywoływany w klasie A, ale wynik jest kodem RESULT_CANCELEDzamiast, RESULT_OKa zwrócona wartość zamiaru ma wartość null. Jak mogę zwrócić coś z działania w TabHost?

Zdaję sobie sprawę, że problem polega na tym, że moja klasa C faktycznie działa w klasie B, a klasa B wraca z RESULT_CANCELEDpowrotem do klasy A. Po prostu nie znam jeszcze rozwiązania.

Cameron McBride
źródło

Odpowiedzi:

366

O Boże! Po spędzeniu kilku godzin i pobraniu źródeł Androida wreszcie znalazłem rozwiązanie.

Jeśli spojrzysz na klasę Activity, zobaczysz, że ta finish()metoda odsyła wynik tylko wtedy, gdy mParentustawiono właściwość na null. W przeciwnym razie wynik zostanie utracony.

public void finish() {
    if (mParent == null) {
        int resultCode;
        Intent resultData;
        synchronized (this) {
            resultCode = mResultCode;
            resultData = mResultData;
        }
        if (Config.LOGV) Log.v(TAG, "Finishing self: token=" + mToken);
        try {
            if (ActivityManagerNative.getDefault()
                .finishActivity(mToken, resultCode, resultData)) {
                mFinished = true;
            }
        } catch (RemoteException e) {
            // Empty
        }
    } else {
        mParent.finishFromChild(this);
    }
}

Więc moim rozwiązaniem jest ustawienie wyniku na aktywność nadrzędną, jeśli jest obecna, w ten sposób:

Intent data = new Intent();
 [...]
if (getParent() == null) {
    setResult(Activity.RESULT_OK, data);
} else {
    getParent().setResult(Activity.RESULT_OK, data);
}
finish();

Mam nadzieję, że będzie to pomocne, jeśli ktoś ponownie poszuka obejścia tego problemu.

Ilya Taranov
źródło
1
Zamieściłem tutaj zhackowane rozwiązanie, jest proste i wymaga przejrzystej aktywności bez zawartości - uzyskuje normalne funkcje cyklu życia i ułatwia wszystko. stackoverflow.com/questions/7812120/...
CQM
To cudownie! Dziekuję Dziekuję Dziękuję! Działa idealnie i bezproblemowo. Zastąpiłem standardowe metody setResult () dla wszystkich moich działań za pomocą tego małego klejnotu. Dziękuję Ci!
Scott Biggs,
Użyłem twojego rozwiązania, ale mój kod nie wychwytuje metody onactivityresult po powrocie. pomóżcie mi ... czy muszę użyć czegoś innego?
skygeek
11
Dlaczego zwracanie wyniku w działaniu nie udokumentowanym nigdzie w przewodnikach API, wydało mi się dziwne.
alex.p
Cholera! Dobra robota, Illya! Dzięki
Sirelon
64

http://tylenoly.wordpress.com/2010/10/27/how-to-finish-activity-with-results/

Z niewielką modyfikacją „param_result”

/* Start Activity */
public void onClick(View v) {
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setClassName("com.thinoo.ActivityTest", "com.thinoo.ActivityTest.NewActivity");
    startActivityForResult(intent,90);
}
/* Called when the second activity's finished */
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch(requestCode) {
    case 90:
        if (resultCode == RESULT_OK) {
            Bundle res = data.getExtras();
            String result = res.getString("param_result");
            Log.d("FIRST", "result:"+result);
        }
        break;
    }
}

private void finishWithResult()
{
    Bundle conData = new Bundle();
    conData.putString("param_result", "Thanks Thanks");
    Intent intent = new Intent();
    intent.putExtras(conData);
    setResult(RESULT_OK, intent);
    finish();
}
Dave S.
źródło
2
Proste, setResultbyło najważniejsze. Ustaw to na coś lub na przykład wartość RESULT_OKi możesz już iść; setResult(RESULT_OK);. Pomógł mi, +1
Afzaal Ahmad Zeeshan
16

Zamiar.FLAG_ACTIVITY_FORWARD_RESULT?

Jeśli jest ustawiony i ten zamiar jest używany do uruchomienia nowej aktywności z istniejącej, cel odpowiedzi dla istniejącej aktywności zostanie przeniesiony do nowej aktywności.

tylko przemyślenia
źródło
1

Możesz zaimplementować onActivityResult również w klasie B i uruchomić klasę C za pomocą startActivityForResult. Gdy uzyskasz wynik w klasie B, ustaw tam wynik (dla klasy A) na podstawie wyniku z klasy C. Nie wypróbowałem tego, ale myślę, że to powinno zadziałać.

Inną rzeczą, na którą należy zwrócić uwagę, jest to, że Działanie A nie powinno być działaniem typu single Instance. Aby funkcja startActivityForResult działała, klasa B musi być działaniem podrzędnym działania A i nie jest to możliwe w przypadku działania w pojedynczej instancji, nowe działanie (klasa B) rozpoczyna się od nowego zadania.

Prashast
źródło
1
Ponieważ klasa B jest TabActivity, a klasa C to Tab w tym działaniu, nie można wykonać startActivityForResult w klasie B. Żadne z moich działań nie jest działaniem pojedynczym.
Cameron McBride
-1

Aby rozpocząć działanie 2 od działania 1 i uzyskać wynik, możesz użyć startActivityForResult i zaimplementować onActivityResult w działaniu 1, a następnie użyć setResult w działaniu 2.

Intent intent = new Intent(this, Activity2.class);
intent.putExtra(NUMERO1, numero1);
intent.putExtra(NUMERO2, numero2);
//startActivity(intent);
startActivityForResult(intent, MI_REQUEST_CODE);
App-SoftwareFactory
źródło