He creado un Concurso de aplicaciones para Android utilizando el tutorial aquí: http://automateddeveloper.blogspot.co.uk/2011/06/getting-started-complete-android-app.html

Para cada pregunta, el usuario sólo tendrá 20 segundos para responder. Si él/ella no puede contestar en 20 segundos, un AlertDialog emergente y el juego terminará.

Para ello, he añadido un contador en el OnCreate método de QuestionActivity class:

final TextView myCounter = (TextView) findViewById(R.id.countdown);
    new CountDownTimer(20000, 1000) {

        @Override
        public void onFinish() {
            timeUp();
        }

        @Override
        public void onTick(long millisUntilFinished) {
            myCounter.setText("Time left: "
                    + String.valueOf(millisUntilFinished / 1000));
        }

    }.start();


public void timeUp() {

    AlertDialog.Builder builder = new AlertDialog.Builder(
            QuestionActivity.this);
    builder.setTitle("Times up!")
            .setMessage("Game over")
            .setCancelable(false)
            .setNeutralButton(android.R.string.ok,
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            QuestionActivity.this.finish();
                        }
                    });
    AlertDialog alert = builder.create();
    alert.show();
}

El contador funciona pantallas y funciones en la pantalla correctamente. Después de contestar a una pregunta, la actividad se traslada a la siguiente pregunta y el contador se restablece a sí mismo a los 20 segundos de nuevo.

El problema

La prueba consta de 15 preguntas, después de responder 3 o 4 preguntas, la aplicación se bloquea y me sale el siguiente error:

07-18 00:49:05.530: E/AndroidRuntime(4867): android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.[email protected] is not valid; is your activity running?

Creo que esto se relaciona con la AlertDialog. He buscado este código de error en Stackoverflow y la popular solución es pasar ActivityName.this como el contexto en la construcción de la AlertDialog.

Por desgracia, esto no resuelve el problema.

Creo que el contador es el de fijar un límite de tiempo de 20 segundos para el conjunto de la actividad. Mi requisito es de 20 segundos para cada pregunta.

Sin embargo, el contador se restablece a 20 segundos cuando el usuario pulse la tecla de » Next botón y la actividad se traslada a la siguiente pregunta.

Debería ser restablecer el contador cuando el usuario presiona el Next botón? Aquí está el OnClickListener código para el Next botón

if (currentGame.isGameOver()) {
        Intent i = new Intent(this, EndgameActivity.class);
        startActivity(i);
        finish();
    } else {
        Intent i = new Intent(this, QuestionActivity.class);
        startActivity(i);
                    SHOULD I ADD SOMETHING HERE?
        finish();

Alguien me puede ayudar código de una solución a mi problema?

Aquí es todo el código en QuestionActivity.class

public class QuestionActivity extends SherlockActivity implements
OnClickListener {
private Question currentQ;
private GamePlay currentGame;
private Context context;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.question);
getSupportActionBar().hide();
/**
* Configure current game and get question
*/
currentGame = ((ChuckApplication) getApplication()).getCurrentGame();
currentQ = currentGame.getNextQuestion();
Button nextBtn = (Button) findViewById(R.id.nextBtn);
nextBtn.setOnClickListener(this);
Button quitBtn = (Button) findViewById(R.id.quitBtn);
quitBtn.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
finish();
}
});
//Update the question and answer options..
setQuestions();
final TextView myCounter = (TextView) findViewById(R.id.countdown);
new CountDownTimer(20000, 1000) {
@Override
public void onFinish() {
//myCounter.setText("Time up!");
timeUp(context);
}
@Override
public void onTick(long millisUntilFinished) {
myCounter.setText("Time left: "
+ String.valueOf(millisUntilFinished / 1000));
}
}.start();
}
public void timeUp(Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(
QuestionActivity.this);
builder.setTitle("Times up!")
.setMessage("Game over")
.setCancelable(false)
.setNeutralButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
QuestionActivity.this.finish();
}
});
AlertDialog alert = builder.create();
alert.show();
}
/**
* Method to set the text for the question and answers from the current
* games current question
*/
private void setQuestions() {
//set the question text from current question
String question = Utility.capitalise(currentQ.getQuestion()) + "?";
TextView qText = (TextView) findViewById(R.id.question);
qText.setText(question);
//set the available options
List<String> answers = currentQ.getQuestionOptions();
TextView option1 = (TextView) findViewById(R.id.answer1);
option1.setText(Utility.capitalise(answers.get(0)));
TextView option2 = (TextView) findViewById(R.id.answer2);
option2.setText(Utility.capitalise(answers.get(1)));
TextView option3 = (TextView) findViewById(R.id.answer3);
option3.setText(Utility.capitalise(answers.get(2)));
TextView option4 = (TextView) findViewById(R.id.answer4);
option4.setText(Utility.capitalise(answers.get(3)));
}
public void onClick(View arg0) {
//validate a checkbox has been selected
if (!checkAnswer())
return;
//check if end of game
if (currentGame.isGameOver()) {
Intent i = new Intent(this, EndgameActivity.class);
startActivity(i);
finish();
} else {
Intent i = new Intent(this, QuestionActivity.class);
startActivity(i);
finish();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
return true;
}
return super.onKeyDown(keyCode, event);
}
/**
* Check if a checkbox has been selected, and if it has then check if its
* correct and update gamescore
*/
private boolean checkAnswer() {
String answer = getSelectedAnswer();
if (answer == null) {
//Log.d("Questions", "No Checkbox selection made - returning");
return false;
} else {
//Log.d("Questions",
//"Valid Checkbox selection made - check if correct");
if (currentQ.getAnswer().equalsIgnoreCase(answer)) {
//Log.d("Questions", "Correct Answer!");
currentGame.incrementRightAnswers();
} else {
//Log.d("Questions", "Incorrect Answer!");
currentGame.incrementWrongAnswers();
}
return true;
}
}
private String getSelectedAnswer() {
RadioButton c1 = (RadioButton) findViewById(R.id.answer1);
RadioButton c2 = (RadioButton) findViewById(R.id.answer2);
RadioButton c3 = (RadioButton) findViewById(R.id.answer3);
RadioButton c4 = (RadioButton) findViewById(R.id.answer4);
if (c1.isChecked()) {
return c1.getText().toString();
}
if (c2.isChecked()) {
return c2.getText().toString();
}
if (c3.isChecked()) {
return c3.getText().toString();
}
if (c4.isChecked()) {
return c4.getText().toString();
}
return null;
}
InformationsquelleAutor tiptopjat | 2012-07-18

1 Comentario

  1. 6

    Creo que la actividad no existe en un cierto punto cuando intenta hacer el cuadro de diálogo(probablemente cuando el CountDownTimer está cerca del final?!?).

    De todos modos creo que el acabado y a partir de la misma actividad para cada pregunta no es una buena idea, en lugar de que usted podría utilizar la actividad actual y simplemente reiniciar el temporizador. Por ejemplo:

    public class QuestionActivity extends SherlockActivity implements
    OnClickListener {
    private CountDownTimer mCountDown;
    @Override
    public void onCreate(Bundle savedInstanceState) {
    //...
    mCountDown = new CountDownTimer(20000, 1000) {
    @Override
    public void onFinish() {
    //myCounter.setText("Time up!");
    timeUp(context);
    }
    @Override
    public void onTick(long millisUntilFinished) {
    myCounter.setText("Time left: "
    + String.valueOf(millisUntilFinished / 1000));
    }
    }.start();
    //... 

    y en el onClick de devolución de llamada de hacer lo mismo para la instalación de una nueva pregunta, dejar el veterano y reiniciar el temporizador nuevo:

    //check if end of game
    if (currentGame.isGameOver()) {
    Intent i = new Intent(this, EndgameActivity.class);
    startActivity(i);
    finish();
    } else {
    if (mCountDown != null) { 
    mCountDown.cancel();
    }  
    currentQ = currentGame.getNextQuestion();
    setQuestions();
    mCountDown = new CountDownTimer(20000, 1000) {
    @Override
    public void onFinish() {
    //myCounter.setText("Time up!");
    timeUp(context);
    }
    @Override
    public void onTick(long millisUntilFinished) {
    myCounter.setText("Time left: "
    + String.valueOf(millisUntilFinished / 1000));
    }
    }.start();  
    }

    También, en la devolución de llamada para el Dialog‘s Button me gustaría cerrar el Dialog antes de terminar la Activity:

    ((AlertDialog) dialog).dismiss();
    QuestionActivity.this.finish();
    • Gracias tio. Voy a darle una oportunidad cuando llegue a casa esta noche.
    • He añadido todo el código y el contador problema ha sido corregido. Sin embargo, cuando el cuestionario es largo y empiezo EndgameActivity.class después de 20 segundos puedo obtener un administrador de ventanas$BadTokenException de error. Parece que el temporizador sigue funcionando y tratando de mostrar el AlertDialog. Estoy usando finish() después de iniciar la EndgameActivity actividad. Alguna idea de qué estoy haciendo mal?
    • Agregar el mismo código para detener el temporizador para el caso cuando el juego es más: if (currentGame.isGameOver()) { if (mCountDown != null) { mCountDown.cancel(); } ... y a ver si se soluciona el problema.
    • Problema resuelto! Gracias. Tengo sólo tiene un problema ahora. En mi solución original, los botones de radio para cada pregunta estaría desactivada cuando se muda a una nueva pregunta. Después de la implementación de la solución, el botón de radio seleccionado a partir de la pregunta anterior aún está seleccionado en la siguiente pregunta…
    • Se fija mediante la adición de radioGroup.clearCheck() en el inicio de setQuestions() método.

Dejar respuesta

Please enter your comment!
Please enter your name here