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.
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.
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();
}
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é.
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.