Intent activity keeps popping - java

I set a timer to this application, so when the timer ends and boxes in Itemdata are still selected, it should call for Thanks.class activity.
However, I realised that it class the Thanks.class activity multiple times.
E.g. if there are 3 selected items, it calls the Thanks.class activity three times.
This is the timer i've declared
//Declare timer
CountDownTimer cTimer = null;
//start timer function
void startTimer() {
cTimer = new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
Intent intent = new Intent(ctx, Thanks.class);
ctx.startActivity(intent);
}
};
cTimer.start();
}
//cancel timer
void cancelTimer() {
if(cTimer!=null)
cTimer.cancel();
}
Here is how I call the function.
#Override
public View getView(final int position, final View view, ViewGroup parent) {
final GridItemData itemData = getItem(position);
inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View itemView = inflater.inflate(R.layout.grid_image, parent, false);
ivGallery = itemView.findViewById(R.id.grid_item_image);
ivGallery.setImageResource(getItem(position).imageUrl);
final MainActivity main = new MainActivity();
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ivGallery = itemView.findViewById(R.id.grid_item_image);
itemData.setSelected(!itemData.isSelected());
startTimer();
if(itemData == getItem(8)) {
AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
customizeAlert(builder, v);
builder.show();
}
else if (itemData == getItem(0)) {
ivGallery.setImageResource(itemData.isSelected()?R.drawable.clickfloor: R.drawable.floor);
}
else if (itemData == getItem(1)) {
ivGallery.setImageResource(itemData.isSelected()?R.drawable.cb: R.drawable.wb);
}
else if (itemData == getItem(2)) {
ivGallery.setImageResource(itemData.isSelected()?R.drawable.cs: R.drawable.s);
}
else if (itemData == getItem(3)) {
ivGallery.setImageResource(itemData.isSelected()?R.drawable.clickothers: R.drawable.others);
}
}
});
return itemView;
}
Please advice me what to do, thank you!

How about starting that CountDownTimer only once?
void startTimer() {
if(cTimer == null) {
cTimer = new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
Intent intent = new Intent(ctx, Thanks.class);
ctx.startActivity(intent);
}
};
cTimer.start();
}
}
Alternatively, just stop the first CountDownTimer, when the second one is about to be started.

Thats because you start a CountdownTimer for each click but you don't check if there is already a CountDownTimer active which needs to be canceled or restarted.
If you expand this to production i would recommend to use AsyncTasks or Courotines for this, because when your CountDownTimer is finished your are maybe no longer allowed to change the UI-State and you will get an IllegalStateException or your findByView will throw a NullPointerException.
With AsyncTasks and Courotines you also don't need to worry about spawning multiple instances of your CountDownTimer.
https://developer.android.com/reference/android/os/AsyncTask

Related

How do I make a Button which restarts a CountdownTimer, when clicked?

I have a function that has a timer that I want to "restart" every time you click the button. I tried doing this but when the button is clicked several times it appears that there are several timers still going on when I only want the one. How do I fix this?
So, onClick => Cancel last timer => Start new timer
public void startService(android.view.View view) {
final SharedPreferences sP = getSharedPreferences("com.example.safetyNet", MODE_PRIVATE);
final Button button = findViewById(R.id.button3);
final Intent transIntent = new Intent(this, CheckPinActivity.class);
CountDownTimer cdt = new CountDownTimer(sP.getInt("TiT", 10) * 1000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
button.setText(String.valueOf(millisUntilFinished).substring(0,2));
}
#Override
public void onFinish() {
if(sP.getBoolean("lockedDown", false) == true){
startActivity(transIntent);
}
}
};
cdt.cancel();
cdt.start();
}
The problem is that, everytime you call the method "startService(android.view.View view) {}", a new CountDownTimer is created, so the previous CountDownTimer that you created is not the same reference as this one.
To solve that, you are going to have to create the CountDownTimer as a class member for your class:
public YourClass {
private CountDownTimer cdt;
.... (do whatever)....
public void startService(android.view.View view) {
final SharedPreferences sP = getSharedPreferences("com.example.safetyNet", MODE_PRIVATE);
final Button button = findViewById(R.id.button3);
final Intent transIntent = new Intent(this, CheckPinActivity.class);
if (cdt == null) {
cdt = new CountDownTimer(sP.getInt("TiT", 10) * 1000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
button.setText(String.valueOf(millisUntilFinished).substring(0,2));
}
#Override
public void onFinish() {
if(sP.getBoolean("lockedDown", false) == true){
startActivity(transIntent);
}
}
};
} else {
cdt.cancel();
}
cdt.start();
}
Hope that helps you

Stopping Ongoing Runnable Android

I am creating a BLE app that needs to continuously start and stop scanning for predefined intervals. The way I have implemented it is with two runnables that call each other as follows:
private Runnable scan = new Runnable() {
#Override
public void run() {
scanHandler.postDelayed(stopScan, SCAN_PERIOD);
mLEScanner.startScan(filters, settings, mScanCallback);
Log.e("BLE_Scanner", "Start Scan");
}
};
private Runnable stopScan = new Runnable() {
#Override
public void run() {
mLEScanner.stopScan(mScanCallback);
scanHandler.postDelayed(scan, STOP_PERIOD);
Log.e("BLE_Scanner", "Stop Scan");
}
};
I am attempting to start the continuous scan and pause on a button click. The start button starts the process fine but I am having trouble with stopping the scanning.
//scan button functionality
scanButton=(Button)findViewById(R.id.scan_button);
scanButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
spinner.setVisibility(View.VISIBLE);
scan.run();
}
});
//stop scan button functionality
stopButton=(Button)findViewById(R.id.stop_button);
stopButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
spinner.setVisibility(View.INVISIBLE);
scanHandler.removeCallbacks(scan);
scanHandler.removeCallbacks(stopScan);
}
});
If I press the stop button during the stop interval the scan will stop. However, if I press the stop button while the scan runnable is running it appears to remove the callbacks for the stopScan runnable while leaving the scan runnable continuously running. What I need is for both of the runnables to stop on the button press. To provide more detail, my entire code is provided below. Thanks for the help.
public class MainActivity extends Activity {
private BluetoothAdapter mBluetoothAdapter;
private int REQUEST_ENABLE_BT = 1;
private static final long SCAN_PERIOD = 5000;
private static final long STOP_PERIOD = 1000;
private BluetoothLeScanner mLEScanner;
private ScanSettings settings;
private List<ScanFilter> filters;
private BluetoothGatt mGatt;
private Button scanButton;
private Button stopButton;
//private String proximityUUID = "0000180f-0000-1000-8000-00805f9b34fb";
private ProgressBar spinner;
private Handler scanHandler;
private String[] filterList = {
"D9:ED:5F:FA:0E:02",
"FF:37:3A:25:56:C7",
"F4:57:89:69:93:91"
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scanHandler = new Handler();
//determine if device supports BLE
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, "BLE Not Supported",
Toast.LENGTH_SHORT).show();
finish();
}
//set up bluetooth manager
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
//scan progress bar
spinner=(ProgressBar)findViewById(R.id.progressBar);
spinner.setVisibility(View.GONE);
//scan button functionality
scanButton=(Button)findViewById(R.id.scan_button);
scanButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
spinner.setVisibility(View.VISIBLE);
scan.run();
}
});
//stop scan button functionality
stopButton=(Button)findViewById(R.id.stop_button);
stopButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
spinner.setVisibility(View.INVISIBLE);
scanHandler.removeCallbacks(scan);
scanHandler.removeCallbacks(stopScan);
}
});
}
#Override
protected void onResume() {
super.onResume();
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
} else {
mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
//scan settings
settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();
//scan filter
//populate the filter list
filters = new ArrayList<ScanFilter>();
for (int i=0; i< filterList.length ; i++) {
ScanFilter filter = new ScanFilter.Builder().setDeviceAddress(filterList[i]).build();
filters.add(filter);
}
}
}
#Override
protected void onPause() {
super.onPause();
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
}
}
#Override
protected void onDestroy() {
if (mGatt == null) {
return;
}
mGatt.close();
mGatt = null;
super.onDestroy();
}
//start scan
private Runnable scan = new Runnable() {
#Override
public void run() {
scanHandler.postDelayed(stopScan, SCAN_PERIOD);
mLEScanner.startScan(filters, settings, mScanCallback);
Log.e("BLE_Scanner", "Start Scan");
}
};
private ScanCallback mScanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
Log.i("callbackType", String.valueOf(callbackType));
Log.i("result", result.toString());
BluetoothDevice device = result.getDevice();
int mRSSI = result.getRssi();
}
#Override
public void onBatchScanResults(List<ScanResult> results) {
for (ScanResult sr : results) {
Log.i("ScanResult - Results", sr.toString());
}
}
#Override
public void onScanFailed(int errorCode) {
Log.e("Scan Failed", "Error Code: " + errorCode);
}
};
//stop scan
private Runnable stopScan = new Runnable() {
#Override
public void run() {
mLEScanner.stopScan(mScanCallback);
scanHandler.postDelayed(scan, STOP_PERIOD);
Log.e("BLE_Scanner", "Stop Scan");
}
};
private static double calculateAccuracy(int txPower, double rssi) {
if (rssi == 0) {
return -1.0; // if we cannot determine accuracy, return -1.
}
double ratio = -rssi*1.0/txPower;
if (ratio < 1.0) {
return Math.pow(ratio,10);
}
else {
double accuracy = (0.89976)*Math.pow(ratio,7.7095) + 0.111;
return accuracy;
}
}
}
I imagine you just want to call startScan immediately on start button press (not in a Runnable, not scheduled through a Handler). The call is asynchronous, so nothing will block, and Android will do all the scanning in another thread. If you then want to schedule a call to stop in the future, then you use the Handler to post a Runnable that calls stopScan at the delay you need.
The button for stopping the scan can also just directly call stopScan() if know that a scan was previously in progress. You might want to use a boolean to gate the call to stopScan only if there was a previous call to startScan().
So, I ended up finding a way to get it to work as intended. I don't know if the way I'm doing things is best practice as I'm new to Android and Java, but this is what worked for me. All I did was call the stopScan method in the stop button after removing the handler callbacks.
//stop scan button functionality
stopButton=(Button)findViewById(R.id.stop_button);
stopButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
spinner.setVisibility(View.INVISIBLE);
scanHandler.removeCallbacksAndMessages(null);
mLEScanner.stopScan(mScanCallback);
}
});

How to Pass a Resource Id as a Parameter; without NullPointerException

Working on an Android app where each activity has its own timer. Originally I had code like this in every class
public void tTimer() {
mTextField = (TextView) findViewById(R.id.countDown_timer);
final CountDownTimer tCounter = new CountDownTimer(7000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
mTextField
.setText("Time Remaining: "
+ String.format(
"%d min, %d sec",
TimeUnit.MILLISECONDS
.toMinutes(millisUntilFinished),
TimeUnit.MILLISECONDS
.toSeconds(millisUntilFinished)
- TimeUnit.MINUTES
.toSeconds(TimeUnit.MILLISECONDS
.toMinutes(millisUntilFinished))));
}
#Override
public void onFinish() {
mTextField.setText("Done!");
Intent i = new Intent (ColdActivity.this, PopUpActivity.class);
startActivity(i);
}
};
Button startButton = (Button) findViewById(R.id.timer_button_start);
/* When the Start Button is touched, the Countdown Timer will start */
startButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(
ColdActivity.this);
builder.setNegativeButton("Dismiss",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
tCounter.start();
// Once the user has been notified that they should increase
// their alarm volume, and they dismiss the notification, the timer
// will start
}
});
builder.setTitle("Notification");
builder.setMessage("It is recommended that you turn your Alarm/Ringtone volume on so that you can hear the alarm when it is finished");
AlertDialog dlg = builder.create();
dlg.show();
}
});
Button stopButton = (Button) findViewById(R.id.timer_button_cancel);
/* When the Stop Button is touched, the Countdown Timer will stop */
stopButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
tCounter.cancel();
}
});
}
I am now trying to create a new class that has a method called tTimer() like in the above code, so that I can instantiate a new object of that class, and then call the method in onCreate(), that way I don't have to rewrite timer code in every class, like I had previously done.
I tried to parameterize the method like this:
CustomTimerActivity cGT = new CustomTimerActivity();
cGT.tTimer(7000, ColdActivity.this, R.id.countDown_timer, R.id.timer_button_start, R.id.timer_button_cancel);
And what I keep getting is a NullPointerException, which points to my class called CustomTimerActivity
Why am I not able to pass the resource Id's as parameters? Or is the NPE coming from something else?
Here is the CustomTimerActivity I made:
public class CustomTimerActivity extends Activity {
TextView mTextField;
int mId;
public void tTimer(long millisecs, final Activity activity1, int tv, int start, int cancel) {
mTextField = (TextView) findViewById(tv);
final CountDownTimer tCounter = new CountDownTimer(millisecs, 1000) {
#Override
public void onTick(long millisUntilFinished) {
mTextField
.setText("Time Remaining: "
+ String.format(
"%d min, %d sec",
TimeUnit.MILLISECONDS
.toMinutes(millisUntilFinished),
TimeUnit.MILLISECONDS
.toSeconds(millisUntilFinished)
- TimeUnit.MINUTES
.toSeconds(TimeUnit.MILLISECONDS
.toMinutes(millisUntilFinished))));
}
#Override
public void onFinish() {
mTextField.setText("Done!");
Intent i = new Intent (activity1, PopUpActivity.class);
startActivity(i);
}
};
Button startButton = (Button) findViewById(start);
/* When the Start Button is touched, the Countdown Timer will start */
startButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(
activity1);
builder.setNegativeButton("Dismiss",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
tCounter.start();
// Once the user has been notified that they should increase
// their alarm volume, and they dismiss the notification, the timer
// will start
}
});
builder.setTitle("Notification");
builder.setMessage("It is recommended that you turn your Alarm/Ringtone volume on so that you can hear the alarm when your tea is finished");
AlertDialog dlg = builder.create();
dlg.show();
}
});
Button stopButton = (Button) findViewById(cancel);
/* When the Stop Button is touched, the Countdown Timer will stop */
stopButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
tCounter.cancel();
}
});
}
}
The issue must be something to do with findViewById() and the Id that is used as input, right?
Here is another NullPointerException I get when the Intent is called.
The Activity has not been initialized in the constructor. Only collect the parameters in the constructor and do the initialization in the onCreate(Bundle) method!
However, if you want to call it from a givin activity, you have to call .findViewById on that class, not on your own class

Android : Restore time in resume

I have question i have a chronometer in my app, when i back to my main window, and get back to Timer activity, I just want to resume a time on chronometer from CountDownTimer, how to to this ? Bundle doesn't help me and similar topics :( I will be very gratefull for any help.
public class Timer extends Activity {
private boolean start = false; // Semafor to button
private Chronometer timer; // Chronometr
private CountDownTimer count; // CountDown class
private final long startTime = 30 * 1000; // High
private final long end = 1 * 1000; //LOw
private ImageButton startB; // Button
private int VIBRATION_TIME = 1000; //vibration time
private Bundle state = new Bundle(); //button state
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
// Show the Up button in the action bar.
getActionBar().setDisplayHomeAsUpEnabled(true);
}
this.timer = ((Chronometer) findViewById(R.id.chronometer1));
count = new MyCountDownTimer(startTime, end);
timer.setText("00:" + String.valueOf(startTime / 1000));
startB = (ImageButton) this.findViewById(R.id.start_pause);
startB.setBackgroundResource(R.drawable.start_button);
startB.setOnClickListener(new View.OnClickListener() {
// click init
#Override
public void onClick(View v) {
start = !start;
if (start == true) {
count.start(); // start count
startB.setBackgroundResource(R.drawable.stop_button);
} else {
count.cancel(); // pause count
startB.setBackgroundResource(R.drawable.start_button);
}
}
});
}
....
#Override
protected void onResume() {
super.onResume();
start = state.getBoolean("Button");
}
#Override
protected void onPause() {
super.onPause();
state.putBoolean("Button", start);
//count.cancel(); I don't wanna this!
}
class MyCountDownTimer extends CountDownTimer {
public MyCountDownTimer(long startTime, long interval) {
super(startTime, interval);
}
#Override
public void onFinish() {
timer.setText("00:00");
// TO DO :
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(VIBRATION_TIME);
startB.setBackgroundResource(R.drawable.start_button);
}
#Override
public void onTick(long millisUntilFinished) {
long tmp = millisUntilFinished / 1000;
timer.setText("00:" + tmp);
}
}
}
Make use of onSaveInstanceState. Override this method, and save your current time into the Bundle. Then, on onCreate, extract the value from the Bundle and apply it to your View.
Hmm yes that is correct what Alex says but I have new idea. CountDownTimer start count, we click backButton activity is killed, but CountDownTimer still counting, but when I use this activity again, I can run new timer and this is crazy, there is any way to do this like that : In create method we check that CountDownTimer is still running and we just update a chronometer, but if not we create everything from new? At now my solutions is tricky: override the onBackPressed() and add this moveTaskToBack(true); but this not back to my mainActivity but return to telephone screen.

Android Quiz Game - Countdown timer for each qstion

I have created a Quiz app for Android using the tutorial here: http://automateddeveloper.blogspot.co.uk/2011/06/getting-started-complete-android-app.html
For each question, the user will only have 20 seconds to answer it. If he/she fails to answer in 20 seconds, an AlertDialog will popup and the game will terminate.
To do this, I have added a counter in the OnCreate method of 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();
}
The counter works displays and functions on screen correctly. After answering a question, the activity moves to the next question and the counter resets itself to 20 seconds again.
The problem
The quiz has 15 questions, after answering 3 or 4 questions, the app crashes and I get the following error:
07-18 00:49:05.530: E/AndroidRuntime(4867): android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy#41533a80 is not valid; is your activity running?
I believe this relates to the AlertDialog. I have looked up this error code on Stackoverflow and the popular solution is to pass ActivityName.this as the context when building the AlertDialog.
Unfortunately this does not solve the problem.
I believe the counter is setting a time limit of 20 seconds for the whole activity. My requirement is 20 seconds for each question.
However, the counter resets to 20 seconds when the user press the' Next button and the activity moves to the next question.
Should I be resetting the counter when the user presses the Next button? Here is the OnClickListener code for the Next button
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();
Can anyone help me code a solution to my problem?
Here is all the code in 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;
}
I think the activity doesn't exist anymore at a certain point when you try to make the dialog(probably when the CountDownTimer is near the end?!?).
Anyway I think finishing and starting the same activity for each question isn't such a good idea, instead you could use the current activity and simply restart the timer. For example:
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();
// ...
and in the onClick callback do the same to setup a new question, stop the old timer and restart the new timer:
//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();
}
Also, in the callback for the Dialog's Button I would first close the Dialog before finishing the Activity:
((AlertDialog) dialog).dismiss();
QuestionActivity.this.finish();

Categories

Resources