Como retornar um resultado (startActivityForResult) de uma atividade TabHost?


275

Eu tenho 3 aulas no meu exemplo: Classe A, a atividade principal. A classe A chama um startActivityForResult:

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

Classe B, esta classe é uma TabActivity:

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

Classe C, essa classe é uma atividade regular:

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

onActivityResult é chamado na Classe A, mas o resultCode é em RESULT_CANCELEDvez de RESULT_OKe a intenção retornada é nula. Como faço para retornar algo da atividade dentro de um TabHost?

Percebo que o problema é que minha Classe C está na verdade executando dentro da Classe B, e a Classe B é o que está retornando RESULT_CANCELEDà Classe A. Apenas não conheço uma solução alternativa ainda.

Respostas:


366

Oh Deus! Depois de passar várias horas e baixar as fontes do Android, finalmente cheguei a uma solução.

Se você olhar para a classe Activity, verá que esse finish()método só envia o resultado se houver uma mParentpropriedade definida como null. Caso contrário, o resultado será perdido.

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

Portanto, minha solução é definir resultado para a atividade pai, se presente, assim:

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

Espero que seja útil se alguém procurar novamente esse problema.


1
Publiquei uma solução hacky aqui, é simples e envolve uma atividade transparente e sem conteúdo - ela obtém funções normais do ciclo de vida e facilita tudo. stackoverflow.com/questions/7812120/…
CQM

Fantástico! Obrigado, obrigado, obrigado! Funciona perfeitamente e com muito pouco barulho. Substituí os métodos setResult () regulares de todas as minhas atividades com esta pequena jóia. Obrigado!
22812 Scott Scott

Eu usei sua solução, ainda assim, meu código não está capturando o método de resultado da atividade ao retornar. por favor me ajude .. preciso usar mais alguma coisa?
skygeek

11
Por que o retorno de um resultado em uma atividade não documentado em nenhum lugar dos guias da API me pareceu estranho.
alex.p

Droga! Bom trabalho, Illya! Obrigado
Sirelon

64

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

Com uma ligeira modificação 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();
}

2
Simples, setResultfoi a principal coisa. Defina-o como algo ou um valor, por exemplo, RESULT_OKe você estará pronto; setResult(RESULT_OK);. Ajudou-me, +1
Afzaal Ahmad Zeeshan

16

Intent.FLAG_ACTIVITY_FORWARD_RESULT?

Se definido e esse objetivo estiver sendo usado para iniciar uma nova atividade a partir de uma existente, o destino da resposta da atividade existente será transferido para a nova atividade.


1

Você também pode implementar um onActivityResult na Classe B e iniciar a Classe C usando startActivityForResult. Depois de obter o resultado na Classe B, defina o resultado lá (para a Classe A) com base no resultado da Classe C. Não tentei isso, mas acho que isso deve funcionar.

Outra coisa a se observar é que a Atividade A não deve ser uma atividade de Instância única. Para que startActivityForResult funcione, sua Classe B precisa ser uma sub atividade da Atividade A e isso não é possível em uma atividade de instância única, a nova Atividade (Classe B) inicia em uma nova tarefa.


1
Como a Classe B é um TabActivity e a Classe C é uma guia nessa atividade, não é possível executar um startActivityForResult na Classe B. Nenhuma das minhas atividades é Atividades de instância única.
Cameron McBride

-1

Para iniciar a Atividade 2 da Atividade 1 e obter resultado, você pode usar startActivityForResult e implementar onActivityResult na Atividade 1 e usar setResult na Atividade2.

Intent intent = new Intent(this, Activity2.class);
intent.putExtra(NUMERO1, numero1);
intent.putExtra(NUMERO2, numero2);
//startActivity(intent);
startActivityForResult(intent, MI_REQUEST_CODE);
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.