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.

Cameron McBride
fonte

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.

Ilya Taranov
fonte
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();
}
Dave S
fonte
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.

onlythoughtworks
fonte
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.

Prashast
fonte
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);
App-SoftwareFactory
fonte