setResult funktioniert nicht, wenn die Taste BACK gedrückt wird

111

Ich versuche, das Ergebnis zu setzen, nachdem die Taste ZURÜCK gedrückt wurde. Ich rufe onDestroy an

Intent data = new Intent();
setResult(RESULT_OK, data) 

Aber wenn es darum geht

onActivityResult(int requestCode, int resultCode, Intent data) 

Der resultCode ist 0 (RESULT_CANCELED) und die Daten sind 'null'.

Wie kann ich das Ergebnis einer Aktivität übergeben, die mit der Schaltfläche ZURÜCK beendet wurde?

alex2k8
quelle

Antworten:

159

Sie müssen die onBackPressed()Methode überschreiben und das Ergebnis vor dem Aufruf der Oberklasse festlegen , d. H.

@Override
public void onBackPressed() {
    Bundle bundle = new Bundle();
    bundle.putString(FIELD_A, mA.getText().toString());
    
    Intent mIntent = new Intent();
    mIntent.putExtras(bundle);
    setResult(RESULT_OK, mIntent);
    super.onBackPressed();
}
n224576
quelle
23
Beachten Sie, dass bei Verwendung dieses Ansatzes der Aufruf von super.onBackPressed () nach dem Aufruf von setResult () wie oben gezeigt erfolgen muss, da sonst das ursprüngliche Problem erneut auftritt!
Jengelsma
1
Das ist die beste Antwort hier. Wenn wir onPause () oder onDestroy () überschreiben, wird onBackPressed () zuerst aufgerufen und das Ergebnis auf 0 gesetzt. Bitte beachten Sie dies!
Marek
oder Sie können das Standardergebnis in onCreate festlegen. Jeder Platz vor finish () ist in Ordnung.
Helin Wang
5
Ich habe einen ähnlichen Ansatz implementiert, aber er funktioniert immer noch nicht. Zum Beispiel habe ich den Anforderungscode und die Absicht funktioniert, aber der resultCode ist immer 0.
Neon Warge
68

ActivityErgebnis muss vorher eingestellt werden finish() es aufgerufen wird. Wenn Sie auf ZURÜCK klicken, wird finish()Ihr Telefon tatsächlich aufgerufen activity, sodass Sie das folgende Snippet verwenden können:

@Override
public void finish() {
    Intent data = new Intent();
    setResult(RESULT_OK, data); 

    super.finish();
}

Wenn Sie rufen NavUtils.navigateUpFromSameTask();in onOptionsItemSelected(), finish()heißt, es wird aber der falsch result code. So müssen Sie rufen finish()nicht navigateUpFromSameTaskin onOptionsItemSelected(). falscher requestCode in onActivityResult

JBM
quelle
Das funktioniert im Fall der OP, aber im Allgemeinen nicht, oder? Es gibt mehr Methoden als finish (), die das Ende des App-Lebenszyklus bewirken (über onPause () und onDestroy ()). Siehe auch meinen Kommentar bei der anderen Antwort.
pjv
Und selbst wenn dies nicht der Fall wäre, würden Sie nicht wissen, wann es in einem API-Update eingeführt wird. Nicht so einfach wie bei einer Änderung des Verhaltens von onPause () oder onDestroy (). Das sind die Methoden , die Sie sind angeblich außer Kraft zu setzen.
pjv
6
@pjv - Ich verstehe nicht, was finishmit onPauseund zu tun hat onDestroy. Diese sind absolut nicht im Zusammenhang mit Ausnahme , dass finishstartet die Beendigung Prozess, onPauseund ein onDestroyTeil von sind.
JBM
20

Wenn Sie einige benutzerdefinierte festlegen möchten RESULT_CODEin onBackPressedFall , dann müssen Sie zuerst die resultund rufen Sie dann die super.onBackPressed()und Sie erhalten die gleiche erhalten RESULT_CODEin der Anrufer Aktivität des onActivityResultVerfahrens

    @Override
    public void onBackPressed()
    {
         setResult(SOME_INTEGER);
         super.onBackPressed();
    }
Khurram Shehzad
quelle
10

Ich habe meinen Code überarbeitet. Anfangs habe ich einige Daten vorbereitet und wie activity resultin eingestellt onDestroy(dies hat nicht funktioniert). Jetzt setze ich activityjedes Mal Daten, wenn die zurückzugebenden Daten aktualisiert werden, und habe nichts drin onDestroy.

alex2k8
quelle
Dies funktioniert nicht für mich, da meine Daten in "onPause"
Bostone
Wenn Ihre Aktivität nach dem Anruf neu erstellt wird setResult(), gehen Ihre Daten verloren.
Jarett Millard
3

Sie sollten onOptionsItemSelected folgendermaßen überschreiben :

@Override
public boolean onOptionsItemSelected(final MenuItem item) {
    switch (item.getItemId()) {
    case android.R.id.home:
        final Intent mIntent = new Intent();
        mIntent.putExtra("param", "value");
        setResult(RESULT_OK, mIntent);
        finish();
        return true;
    default:
        return super.onOptionsItemSelected(item);
    }
}
mdolanci
quelle
2

Verweisen onActivityResult (int, int, Intent) doc

Die Lösung besteht darin, den resultCode auf den Wert Activity.RESULT_CENCELED zu überprüfen . Wenn ja, bedeutet dies, dass entweder ZURÜCK gedrückt wurde oder die Aktivität abgestürzt ist. Hoffe es funktioniert für euch, funktioniert für mich :).

Ankur
quelle
Dies ist die genaue Lösung. Sie müssen den Ergebniscode eingeben. Niemand kann das Ergebnis außer Ihnen im Code festlegen. Wenn das Ergebnis nicht in Ordnung ist, bedeutet dies, dass entweder der Rücken gedrückt oder abgestürzt wird.
John
0

onDestroyist zu spät in der Kette - überschreiben Sie stattdessen onPauseund überprüfen Sie isFinishing(), ob Ihre Aktivität am Ende ihres Lebenszyklus ist.

Roman Nurik
quelle
1
Nein, das ist auch zu spät.
Alex2k8
Ich nenne das eigentlich einen Fehler: code.google.com/p/android/issues/detail?id=1671 . In komplexen Anwendungen gibt es meines Erachtens nur ein Verhalten, das Sie nicht programmieren können.
pjv
Es ist auch sehr eingängig. So sehr, dass ich über einen Zeitraum von 2 Jahren immer wieder den gleichen Fehler mache.
pjv
Eigentlich - das ist noch schlimmer. Und es existiert in JB, während ich codiere. Wenn ich setResult von onPause aus aufrufe, wird es ausgeführt, aber weder resultCode noch Daten werden gesetzt, wenn onActivityReturn ausgeführt wird. Warum?
Bostone
Und deshalb: "Die Implementierung dieser Methode (onPause) muss sehr schnell erfolgen, da die nächste Aktivität erst wieder aufgenommen wird, wenn diese Methode zurückgegeben wird" goo.gl/8S2Y
Bostone
0

Versuchen Sie, onBackPressed (ab Android Level 5) zu überschreiben, oder überschreiben Sie onKeyDown () und fangen Sie KeyEvent.BUTTON_BACK ab (siehe Android-Aktivitätsergebnisse ). Dies ist der Trick für mich.

MrJre
quelle
0

Verlassen Sie sich nicht auf eine Logik, die in onPause einer Aktivität ausgeführt wird, wenn Sie zur ersten zurückkehren. Laut den Dokumenten:

Die Implementierung dieser Methode (onPause) muss sehr schnell erfolgen, da die nächste Aktivität erst wieder aufgenommen wird, wenn diese Methode zurückgegeben wird

Sehen http://goo.gl/8S2Y Informationen finden .

Am sichersten ist es, das Ergebnis festzulegen, nachdem jeder Vorgang zur Änderung des Ergebnisses abgeschlossen ist (wie Sie in Ihrer Antwort erwähnt haben).

Bostone
quelle
0

Ich füge die Antwort ein, die für andere hilfreich sein kann: Wenn ein Set launcheMode mit Android: launchMode = "singleTask" festgelegt wird, kann ich auch das Ergebnis nicht erhalten, sagt der Doc:

     /* <p>Note that this method should only be used with Intent protocols
 * that are defined to return a result.  In other protocols (such as
 * {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may
 * not get the result when you expect.  For example, if the activity you
 * are launching uses the singleTask launch mode, it will not run in your
 * task and thus you will immediately receive a cancel result.
 */

und:

     /* <p>As a special case, if you call startActivityForResult() with a requestCode 
 * >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your
 * activity, then your window will not be displayed until a result is 
 * returned back from the started activity.  This is to avoid visible 
 * flickering when redirecting to another activity. 
 */
banxi1988
quelle