web-dev-qa-db-fra.com

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

J'ai trois 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 un 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 RESULT_CANCELED au lieu de RESULT_OK et l'intention renvoyée est null. Comment puis-je retourner quelque chose de l'activité dans 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 que la classe B est ce qui ramène le RESULT_CANCELED à la classe A. Je ne connais pas encore de solution de rechange.

273
Cameron McBride

Oh mon Dieu! Après avoir passé plusieurs heures à télécharger les sources Android, je suis enfin parvenu à une solution.

Si vous regardez la classe d'activité, vous verrez que la méthode finish() ne renvoie le résultat que s'il existe une propriété mParent 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);
    }
}

Ma solution consiste donc à définir le résultat sur l'activité parent si elle est présente, comme ceci:

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 cette solution de contournement.

364
Ilya Taranov

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();
}
64
Dave S

Intent.FLAG_ACTIVITY_FORWARD_RESULT?

Si cette option est définie 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 est transférée vers la nouvelle activité.

16
onlythoughtworks

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 ensuite (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é mono-instance. Pour que startActivityForResult fonctionne, votre classe B doit être une sous-activité de l'activité A et que cela n'est pas possible dans une activité d'instance unique, la nouvelle activité (classe B) démarre dans une nouvelle tâche.

1
Prashast