Comment retourner un résultat (startActivityForResult) d'une activité TabHost?

275

J'ai 3 classes dans mon exemple: la classe A, l'activité principale. La classe A appelle un startActivityForResult:

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

Classe B, cette classe est une TabActivity:

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

Classe C, cette classe est une activité régulière:

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

onActivityResult est appelé dans la classe A, mais le resultCode est à la RESULT_CANCELEDplace de RESULT_OKet l'intention retournée est nulle. Comment puis-je retourner quelque chose de l'activité à l'intérieur d'un TabHost?

Je me rends compte que le problème est que ma classe C fonctionne réellement à l'intérieur de la classe B, et la classe B est ce qui RESULT_CANCELEDramène le dos à la classe A. Je ne connais pas encore de solution.

Cameron McBride
la source

Réponses:

366

Oh mon Dieu! Après avoir passé plusieurs heures et téléchargé les sources Android, j'ai finalement trouvé une solution.

Si vous regardez la classe Activity, vous verrez que cette finish()méthode ne renvoie le résultat que si une mParentpropriété est définie sur null. Sinon, le résultat est perdu.

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);
    }
}

Donc ma solution est de définir le résultat sur l'activité parent si elle est présente, comme ça:

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

J'espère que cela sera utile si quelqu'un cherche à nouveau ce problème.

Ilya Taranov
la source
1
J'ai posté une solution hacky ici, c'est simple et implique une activité transparente sans contenu - elle obtient des fonctions de cycle de vie normales et facilite tout. stackoverflow.com/questions/7812120/…
CQM
C'est génial! Merci merci merci! Cela fonctionne parfaitement et avec très peu de bruit. J'ai remplacé les méthodes setResult () habituelles pour toutes mes activités avec ce petit bijou. Je vous remercie!
Scott Biggs
J'ai utilisé votre solution, mon code n'attrape toujours pas la méthode onactivityresult lors du retour. s'il vous plaît aidez-moi .. dois-je utiliser autre chose?
skygeek
11
Pourquoi le retour d'un résultat dans une activité non documentée nulle part dans les guides de l'API m'a-t-il semblé étrange.
alex.p
Zut! Bon travail, Illya! Merci
Sirelon
64

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

Avec une légère modification pour "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
la source
2
Simple, setResultc'était l'essentiel. Réglez-le sur quelque chose, ou une valeur par exemple RESULT_OKet vous êtes prêt à partir; setResult(RESULT_OK);. M'a aidé, +1
Afzaal Ahmad Zeeshan
16

Intention.FLAG_ACTIVITY_FORWARD_RESULT?

Si défini et que cette intention est utilisée pour lancer une nouvelle activité à partir d'une activité existante, la cible de réponse de l'activité existante sera transférée vers la nouvelle activité.

onlythoughtworks
la source
1

Vous pouvez également implémenter un onActivityResult dans la classe B et lancer la classe C à l'aide de startActivityForResult. Une fois que vous obtenez le résultat en classe B, définissez-le (pour la classe A) en fonction du résultat de la classe C. Je n'ai pas essayé cela, mais je pense que cela devrait fonctionner.

Une autre chose à surveiller est que l'activité A ne doit pas être une activité à instance unique. Pour que startActivityForResult fonctionne, votre classe B doit être une sous-activité de l'activité A et ce n'est pas possible dans une activité d'instance unique, la nouvelle activité (classe B) démarre dans une nouvelle tâche.

Prashast
la source
1
Étant donné que la classe B est une TabActivity et la classe C est un onglet dans cette activité, vous ne pouvez pas faire un startActivityForResult dans la classe B. Aucune de mes activités n'est une activité à instance unique.
Cameron McBride
-1

Pour démarrer l'activité 2 à partir de l'activité 1 et obtenir le résultat, vous pouvez utiliser startActivityForResult et implémenter onActivityResult dans l'activité 1 et utiliser setResult dans l'activité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
la source