¿Cómo devolver un resultado (startActivityForResult) de una actividad TabHost?

275

Tengo 3 clases en mi ejemplo: Clase A, la actividad principal. La clase A llama a startActivityForResult:

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

Clase B, esta clase es una TabActivity:

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

Clase C, esta clase es una actividad regular:

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

onActivityResult se llama en la Clase A, pero resultCode es en RESULT_CANCELEDlugar de RESULT_OKy el intento devuelto es nulo. ¿Cómo devuelvo algo de la actividad dentro de un TabHost?

Me doy cuenta de que el problema es que mi Clase C realmente se está ejecutando dentro de la Clase B, y la Clase B es lo que está regresando RESULT_CANCELEDa la Clase A. Todavía no conozco una solución alternativa.

Cameron McBride
fuente

Respuestas:

366

¡Oh Dios! Después de pasar varias horas y descargar las fuentes de Android, finalmente he llegado a una solución.

Si observa la clase Actividad, verá que ese finish()método solo devuelve el resultado si hay una mParentpropiedad establecida en null. De lo contrario, el resultado se pierde.

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

Entonces, mi solución es establecer el resultado de la actividad principal si está presente, así:

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

Espero que sea útil si alguien busca este problema de nuevo.

Ilya Taranov
fuente
1
Publiqué una solución hacky aquí, es simple e implica una actividad transparente sin contenido: obtiene funciones normales del ciclo de vida y hace que todo sea más fácil. stackoverflow.com/questions/7812120/…
CQM
¡Eso es genial! ¡Gracias, gracias, gracias! Funciona perfectamente y con muy poco alboroto. He anulado los métodos regulares setResult () para todas mis actividades con esta pequeña joya. ¡Gracias!
Scott Biggs
Usé su solución, aún así mi código no está captando el método de resultado de actividad cuando regreso. por favor ayúdame ... ¿necesito usar alguna otra cosa?
skygeek
11
¿Por qué devolver un resultado en una Actividad no documentada en ninguna parte de las guías de la API? Me pareció extraño.
alex.p
¡Maldición! Buen trabajo, Illya! Gracias
Sirelon
64

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

Con una ligera modificación para "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
fuente
2
Simple, setResultera lo principal. Póngalo en algo, o en un valor, por ejemplo, RESULT_OKy listo; setResult(RESULT_OK);. Me ayudó, +1
Afzaal Ahmad Zeeshan
16

Intención.FLAG_ACTIVITY_FORWARD_RESULT?

Si se establece y esta intención se está utilizando para lanzar una nueva actividad desde una existente, el objetivo de respuesta de la actividad existente se transferirá a la nueva actividad.

solo pensamientos
fuente
1

También podría implementar un onActivityResult en la Clase B e iniciar la Clase C con startActivityForResult. Una vez que obtenga el resultado en la Clase B, configure el resultado allí (para la Clase A) en función del resultado de la Clase C. No lo he probado, pero creo que debería funcionar.

Otra cosa a tener en cuenta es que la actividad A no debe ser una actividad de una sola entrada. Para que startActivityForResult funcione, su Clase B debe ser una actividad secundaria de la Actividad A y eso no es posible en una actividad de instancia única, la nueva Actividad (Clase B) comienza en una nueva tarea.

Prashast
fuente
1
Dado que la Clase B es una TabActivity y la Clase C es una Tab en esa actividad, no puede hacer un startActivityForResult en la Clase B. Ninguna de mis actividades son Actividades de instancia única.
Cameron McBride
-1

Para iniciar la Actividad 2 desde la Actividad 1 y obtener el resultado, puede usar startActivityForResult e implementar onActivityResult en la Actividad 1 y usar setResult en la Actividad2.

Intent intent = new Intent(this, Activity2.class);
intent.putExtra(NUMERO1, numero1);
intent.putExtra(NUMERO2, numero2);
//startActivity(intent);
startActivityForResult(intent, MI_REQUEST_CODE);
App-SoftwareFactory
fuente