CountDownTimer Android issue - java

I'm trying to implement a CountDownTimer in an Android Application. This timer will, while running, countdown from a value, than reset, than countdown from a different value. Switching back and force between values until either a set number of rounds have elapsed or the stop button has been pressed. I can get the CountDownTimer samples to work, but I guess I'm missing something here. Below is the applicable button press code;
CounterState state = CounterState.WORKOUT;
private WorkoutTimer workoutTimer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.workout_stopwatch);
requestWindowFeature(Window.FEATURE_NO_TITLE);
// Set up OnClickListeners
((Button) findViewById(R.id.start_button)).setOnClickListener(this);
((Button) findViewById(R.id.stop_button)).setOnClickListener(this);
((Button) findViewById(R.id.reset_button)).setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.start_button:
if (!timer_running) {
timer_running = true;
Log.d(TAG, "clicked on Start Button");
// If the state is unknown, set it to Workout first
int State = state.getStateValue();
if (State == 0) {
state.setStateValue(1);
}
workoutTimer.start();
}
break;
case R.id.stop_button:
Log.d(TAG, "clicked on Stop Button");
if (timer_running); {
timer_running = false;
workoutTimer.cancel();
}
break;
private class WorkoutTimer extends CountDownTimer{
public WorkoutTimer(long interval) {
super(getThisTime(), interval);
Log.d(TAG, "WorkoutTimer Constructed...");
}
TextView digital_display = (TextView) findViewById(R.id.digital_display);
TextView numOfRounds = (TextView) findViewById(R.id.number_of_rounds);
public void onFinish() {
int State = state.getStateValue();
int roundsLeft = 0;
if (State == 1) {
state.setStateValue(2);
} else {
state.setStateValue(1);
}
decrementRounds();
try {
roundsLeft = Integer.parseInt(numOfRounds.getText().toString());
} catch(NumberFormatException nfe) {
roundsLeft = 999;
}
if (roundsLeft > 0 || roundsLeft != 999) {
workoutTimer.start();
}
}
public void onTick(long millisUntilFinished) {
final long minutes_left = ((millisUntilFinished / 1000) / 60);
final long seconds_left = (millisUntilFinished / 1000) - (minutes_left * 60);
final long millis_left = millisUntilFinished % 100;
String time_left = String.format("%02d:%02d.d", minutes_left, seconds_left,
millis_left);
digital_display.setText(time_left);
}
}
private long getThisTime() {
long time = 0;
TextView workout_time = (TextView) findViewById(R.id.workout_time);
TextView rest_time = (TextView) findViewById(R.id.rest_time);
switch(state) {
case WORKOUT:
try {
time = Integer.parseInt(workout_time.getText().toString());
} catch(NumberFormatException nfe) {
time = 999;
}
// time = 90;
Log.d(TAG, "Workout time = " + time);
break;
case REST:
try {
time = Integer.parseInt(rest_time.getText().toString());
} catch(NumberFormatException nfe) {
time = 999;
}
// time = 30;
Log.d(TAG, "Rest time = " + time);
break;
case UNKNOWN:
time = 0;
break;
}
return time;
}
Everything starts up okay, but crashes when I click either button. If I comment out my calls to the workoutTimer, no crash. I never see my log in the constructor of the workoutTimer class, so obviously I'm missing something here. Any help would be appreciated.
-Ian

You have not initialized your workoutTimer. You need to add the following line in your onCreate method.
workoutTimer = new WorkoutTimer(...);

Related

How to calculate the current millisecond provided if there is old millisecond in java

I making a timer in my android app. I have a scenario where I dont need to stop the timer even if the app is closed. If the timer is running and user closes the app and reopen it after sometime. He should see the latest time on the timer. But currently I am not able to show the latest time. I am only able to show the time when the user killed the app. I am storing the time of the timer and when the user open the app I am putting the stored time back to the timer. But I want to show the latest time. Here what I have done till now. I am using chronometer widget.
MainActivity.class:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = MainActivity.class.getSimpleName();
Chronometer tvTextView;
Button btnStart, btnStop;
private int state = 0; //0 means stop state,1 means play, 2 means pause
SharedPreferences sharedPreferences;
private boolean running = false;
private long pauseOffSet = -1;
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvTextView = findViewById(R.id.textview);
progressBar = findViewById(R.id.puzzleProgressBar);
btnStart = findViewById(R.id.button1);
btnStop = findViewById(R.id.button2);
btnStart.setOnClickListener(this);
btnStop.setOnClickListener(this);
sharedPreferences = getSharedPreferences("myprefs", MODE_PRIVATE);
state = sharedPreferences.getInt("state", 0);
tvTextView.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
#Override
public void onChronometerTick(Chronometer chronometer) {
long time = SystemClock.elapsedRealtime() - chronometer.getBase();
pauseOffSet=time;
Log.e(TAG,"pauseOffSet "+pauseOffSet);
if (time >= 79200000) {
tvTextView.setBase(SystemClock.elapsedRealtime());
tvTextView.stop();
running = false;
progressBar.setProgress(0);
} else {
chronometer.setText(setFormat(time));
int convertTime = (int) time;
progressBar.setProgress(convertTime);
}
}
});
if (state == 1) { // its in play mode
running = true;
tvTextView.setBase(SystemClock.elapsedRealtime() - sharedPreferences.getLong("milli", 0));
tvTextView.start();
} else if (state == 2) { //its in pause mode
running = false;
pauseOffSet = sharedPreferences.getLong("milli", -1);
long time = SystemClock.elapsedRealtime() - pauseOffSet;
tvTextView.setBase(time);
int convertTime = (int) pauseOffSet;
progressBar.setProgress(convertTime);
} else {
running = false;
tvTextView.setBase(SystemClock.elapsedRealtime());
}
}
public void onClick(View v) {
if (btnStart == v) {
if (!running) {
if (pauseOffSet != -1) {
pauseOffSet = sharedPreferences.getLong("milli", -1);
}
tvTextView.setBase(SystemClock.elapsedRealtime() - pauseOffSet);
tvTextView.start();
state = 1;
pauseOffSet = 0;
running = true;
}
} else if (btnStop == v) {
if (running) {
tvTextView.stop();
pauseOffSet = SystemClock.elapsedRealtime() - tvTextView.getBase();
state = 2;
running = false;
}
}
}
#Override
protected void onStop() {
super.onStop();
sharedPreferences.edit().putLong("milli", pauseOffSet).commit();
sharedPreferences.edit().putInt("state", state).commit();
}
#Override
protected void onDestroy() {
Log.e(TAG, "onDestroy called, state: " + state);
super.onDestroy();
}
String setFormat(long time) {
int h = (int) (time / 3600000);
int m = (int) (time - h * 3600000) / 60000;
int s = (int) (time - h * 3600000 - m * 60000) / 1000;
String hh = h < 10 ? "0" + h : h + "";
String mm = m < 10 ? "0" + m : m + "";
String ss = s < 10 ? "0" + s : s + "";
return hh + ":" + mm + ":" + ss;
}
}

Android Broadcast Receiver as inner static class Passing a String

Probably you want to jump to Update 2 and check the code if needed
I am building a barcode scanner and having difficulty in passing data that I have captured from an inner class that extends BroadcastReceiver to MainActivity class, I do understand the difference between static and non static objects, but I got stuck.
Cant invoke my logic method from the inner class.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
protected void onCreate(Bundle savedInstanceState){...}
public void Logic(String result){// Do something...}
//Inner Class
public static class ScanResultReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {...
// data here captured fine!
// Here I want to send my data to MainActivity Logic(result)
Logic(result);
}
}
If I make "Logic()" as Static method, I get a lot of errors regards to calling non static from static method from Toaster/variables..etc
Update
This method is inside MainActivity, I do want to call it from the inner class
public void Logic(String result) throws Exception {
//prepare the results
if (mDecodeResult.decodeValue.substring(0, 1).equals("{") && mDecodeResult.decodeValue.substring(mDecodeResult.decodeValue.length() - 1).equals("}")) {
if (!(mDecodeResult.decodeValue.equals("SCAN AGAIN"))) {
mDecodeResult.decodeValue = mDecodeResult.decodeValue.substring(1);
mDecodeResult.decodeValue = mDecodeResult.decodeValue.substring(0, mDecodeResult.decodeValue.length() - 1);
}
}
if (mDecodeResult.decodeValue.equals("SCAN AGAIN")) {
Toast toast = Toast.makeText(getApplicationContext(),
"No scan data received! Please Scan Again", Toast.LENGTH_SHORT);
toast.show();
} else if (mDecodeResult.decodeValue != null && tourFlag) {
String formattedDate = getTime();
String scanContent = mDecodeResult.decodeValue;
boolean found = false;
if (ForcedOrRandom.equals("Random")) {
String[] b;
for (String l : ToBeScanned) {
b = l.split(":");
if (scanContent.equals(b[0])) {
Log.d("remove", "scanned: " + scanContent);
Log.d("remove", "remove : " + b[0]);
found = true;
}
}
} else if (ForcedOrRandom.equals("Forced")) {
String[] b;
for (String I : FTobeScannedNext) {
b = I.split(":");
if (scanContent.equals(b[0])) {
Log.d("remove", "scanned: " + scanContent);
Log.d("remove", "remove : " + b[0]);
found = true;
}
}
}// end Skip/Forced
if (listLoaded && found) {
theResult[resultCount].setTourID(currentTourId);
theResult[resultCount].setBarcode(scanContent);
BarcodeObject a = getBarcodeInfo(scanContent);
if (ForcedOrRandom.equals("Random")) {
} else {
if (myTimer != null) {
myTimer.cancel();
Timer = (TextView) findViewById(R.id.timertext);
Timer.setText("");
PlayOrPause.setVisibility(View.INVISIBLE);
}
boolean isTimed = a.getForceNextBarCode().equals("");
if (!(isTimed)) {
PlayOrPause = (ImageButton) findViewById(R.id.PlayPause);
PlayOrPause.setVisibility(View.VISIBLE);
PlayOrPause.setImageResource(R.drawable.pause);
final AlertDialog.Builder timealert = new AlertDialog.Builder(this);
PlayOrPause.setEnabled(true);
long duration = Integer.parseInt(a.getForceNextBarCode());
duration = duration * 60000;
myTimer = new CountDownTimer(duration, 1000) {
#Override
public void onTick(long millisuntilFinished) {
int seconds = (int) (millisuntilFinished / 1000) % 60;
int minutes = (int) ((millisuntilFinished / (1000 * 60)) % 60);
Timer = (TextView) findViewById(R.id.timertext);
Timer.setText(minutes + ":" + seconds);
timeLeft = millisuntilFinished;
}
String value = "";
#Override
public void onFinish() {
Timer = (TextView) findViewById(R.id.timertext);
theResult[resultCount].setScanstatus(scanStatusTimeElapsed);
timealert.setTitle("Site Secure");
timealert.setMessage("Time Elapsed! Enter reason");
// Set an EditText view to get user input
final EditText input = new EditText(MainActivity.this);
timealert.setView(input);
timealert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
value = input.getText().toString();
// Do something with value!
while (value.equals("")) {
timealert.setView(input);
timealert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
value = input.getText().toString();
}
});
}
theResult[resultCount].setComments(value);
}
});
timealert.setIcon(android.R.drawable.ic_dialog_alert);
timealert.show();
Timer.setText(R.string.Time_Elapsed);
}
};
myTimer.start();
}
}
theResult[resultCount].setBarcodeID(a.getBarCodeId());
theResult[resultCount].setDateScanned(formattedDate);
theResult[resultCount].setSkipped(getResources().getString(R.string.Scanned));
}// end big if listLoaded && found
contentTxt.setText(scanContent);
Toaster(getResources().getString(R.string.TScan_Complete));
if (mainScanCounter == 0) {
if (tourDecider(scanContent)) {//tour decider is called to determine if this is boolJanamScanner random or forced tour
tourId = scanContent;
if (!(readFileOffline(siteSecurePath + "/doneTourNumber.txt").equals(""))) {
SYNC.setEnabled(true);
}
}
} else if (mainScanCounter > 0) {
if (ForcedOrRandom.equals("Random")) {
ListManager(scanContent);
} else {
ForcedListManager(scanContent);
}
}
} else if (mDecodeResult.decodeValue != null && officerScanFlag) {
TextView officertextview = (TextView) findViewById(R.id.officerid);
UserObject theofficer = getUserInfo(mDecodeResult.decodeValue);
if (theofficer == null) {
popUps("Error", "Invalid Officer ID, Please Rescan", "TITLE");
officerScan.setEnabled(true);
} else if (theofficer != null) {
// officer ID found need to store it for backup
officerId = theofficer.getOfficerid();
makeFileOffline(officerId, "officerID");
officertextview.setText(theofficer.getUsername());
officerScanFlag = false;
startTimersOfficerID = getTime();
tourBtn.setEnabled(true);
}
}
if (mDecodeResult.decodeValue != null && exceptionFlag) {
Log.d("check", "exception was clicked");
String ex_result = mDecodeResult.decodeValue;
for (int i = 0; i < theExceptions.length; i++) {
if (!(theExceptions[i].getBarcode().equals(ex_result))) {
String refnum = theExceptions[i].getRefNum();
i = theExceptions.length;
theResult[resultCount - 1].setException(refnum);
}
}
exceptionFlag = false;
Toaster(getResources().getString(R.string.TScan_Complete));
}
} // Logic Ends
Update 2
Not sure if I need to have another thread for this but I will put what I have found, my issue have narrowed to the following:
I am waiting on an intent called
<action android:name="device.scanner.USERMSG" />
with a permission
android:permission="com.permission.SCANNER_RESULT_RECEIVER"
now my issue
if a user tap button and released in less than .5 second onKeyup() event will be fired before my onReceive() that is inside the static class which is extends BroadcastReceiver, and that causes problem because Logic() will be invoked before updating the String inside onReceive()
if user hold the button long enough, onReceive will be invoked and everything is good and happy.
How can I make sure that onReceive() always invoked first?
public boolean onKeyUp(int keycode, KeyEvent event) {
if (keycode == 221 || keycode == 220 || keycode == 222) {
Logic(result);
}
return true;
}
Move this line of code:
public void Logic(String result){// Do something...}
inside your class ScanResultReceiver and it will work for sure. Your code should look like this:
public static class ScanResultReceiver extends BroadcastReceiver {
public ScanResultReceiver() {
//empty constructor
}
#Override
public void onReceive(Context context, Intent intent) {...
// data here captured fine!
// Here I want to send my data to MainActivity Logic(result)
Logic(result);
}
public void Logic(String result){/* ... */}
}

How to save timer class start time?

I am implementing countup concept in my project..it contains 3 question buttons..if user clicks on first button count up is start. Whenever he presses the 2nd question.. count up should reset. If user returns to first button then count up should update where it paused..
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
long systemTime = System.currentTimeMillis();
Log.d("System Time", String.valueOf(systemTime));
long millis = systemTime - startTime;
Log.d("millis", String.valueOf(millis));
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
qstimer.setText(String.format("%d:%02d", minutes, seconds));
timerHandler.postDelayed(this, 500);
}
};
try this
In your first button(ON) paste this code and in second button(OFF) paste the same code but instead of "i==0" take another variable
if(i == 0){
pauseTime = timeSwap+= timeInMillies;
timeMap.put(keyQuestion, pauseTime);
keyQuestion = q1.getText().toString();
timerStart();
i = 1;
}
else if(i == 1){
myHandler.removeCallbacks(updateTimerMethod);
pauseTime = timeSwap+= timeInMillies;
timeMap.put(keyQuestion, pauseTime);
keyQuestion = q1.getText().toString();
timeSwap = 0L;
timeSwap += timeMap.get(keyQuestion);
startTime = SystemClock.uptimeMillis();
myHandler.postDelayed(updateTimerMethod, 0);
}
Hope it helps.
Add an OnCLickListener to your buttons :
private OnClickListener mOnClickListener = new OnClickListener()
{
#Override
public void onClick(View v)
{
if (mOnButtonClickListener != null)
{
switch (v.getId())
{
case R.id.on:
startTime = SystemClock.elapsedRealtime();
timerHandler.post(timerRunnable);
break;
case R.id.off:
timerHandler.removeCallbacks(timerRunnable);
break;
}
}
}
};
If you want your OFF button to PAUSE the timer you have to store the pause start time and the total paused time:
private OnClickListener mOnClickListener = new OnClickListener()
{
#Override
public void onClick(View v)
{
if (mOnButtonClickListener != null)
{
switch (v.getId())
{
case R.id.on:
if(paused)
{
pausedTime += SystemClock.elapsedRealtime()-pauseStartTime;
}
else
{
startTime = SystemClock.elapsedRealtime();
}
timerHandler.post(timerRunnable);
break;
case R.id.off:
pauseStartTime = SystemClock.elapsedRealtime();
timerHandler.removeCallbacks(timerRunnable);
break;
}
}
}
};
And in your runnable :
long millis = time - startTime - pausedTime;
Hope it helps

Multithreading using a Handler doesn't run past first pass

I am trying to run a simple clock in my activity, the purpose of the project is to create a secondary thread to run our clock on and update our main UI thread using a handler. I thought I had it working but I guess I was looking at something wrong. Either way, here is my code
public class MainActivity extends Activity implements Runnable{
/** VARIABLES **/
private LinearLayout currView;
private TextView clock;
private Typeface icelandFace;
private Calendar cal;
// clock time values
private int clockMins;
private int clockHour;
private int timeOfDay; // am/pm
private String currTimeString;
// for alarm clock
boolean startAlarm = false;
private long alarmStartTime = -1;
private final int DESIRED_ALARM_DURATION = 5;
// clock thread handler, to communicate between our main ui and our secondary ui
// - note to self - rather unclear on the explanation for the suppression for the handler
private Handler handler = new Handler();
// runnable variable for the secondary thread to actually run on
private final Runnable clockRunnable = new Runnable(){
public void run(){
updateUI();
}
};
/** OVERRIDDEN CLASS METHODS **/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
currView = (LinearLayout) findViewById(R.id.main_activity);
clock = (TextView) findViewById(R.id.clock_view);
clock.setTextSize(clock.getTextSize() * 2);
icelandFace = Typeface.createFromAsset(getAssets(), "font/Iceland-Regular.ttf");
clock.setTypeface(icelandFace);
cal = Calendar.getInstance();
// Create New Thread (to run our clock on)
Thread clockThread = new Thread(){
public void run() {
keepTime();
clockMins = cal.get(Calendar.MINUTE);
clockHour = cal.get(Calendar.HOUR);
timeOfDay = cal.get(Calendar.AM_PM);
// Implement the handler for the thread
// NOTE: recall, Message contains data and is passed to our handler
//Message message = handler.obtainMessage();
Bundle bundle = new Bundle();
// start with hours
String timeString = clockHour + ":";
// add minutes
if(clockMins < 10){
timeString = timeString + "0" + clockMins + " ";
}
else{
timeString = timeString + clockMins + " ";
}
// set time of day
if(timeOfDay == 0){
timeString = timeString + "am";
}
else{
timeString = timeString + "pm";
}
// Optional bundle stuff
//bundle.putString("time_string", timeString);
//message.setData(bundle);
Log.d("Runnable", "Tracking time # " + timeString);
currTimeString = timeString;
handler.post(clockRunnable);
}
private void keepTime(){
clockMins = cal.get(Calendar.MINUTE);
clockHour = cal.get(Calendar.HOUR);
timeOfDay = cal.get(Calendar.AM_PM);
checkAlarm(clockHour, clockMins, timeOfDay);
}
private void checkAlarm(int hour, int min, int timeOfDay){
SharedPreferences alarmPref = getSharedPreferences("alarm_preferences", MODE_PRIVATE);
int alarmHour = alarmPref.getInt("alarm_hour", -1);
int alarmMin = alarmPref.getInt("alarm_min", -1);
int alarmTimeOfDay = alarmPref.getInt("alarm_time_of_day", 0);
boolean alarmOn = alarmPref.getBoolean("alarm_on", true);
if(hour == alarmHour && min == alarmMin && timeOfDay == alarmTimeOfDay && alarmOn == true
&& alarmStartTime != -1){
startAlarm = true;
}
return;
}
};
clockThread.start();
}
//TODO: Setup the alarm via the menu that inflates here
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.alarm, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch(item.getItemId())
{
case R.id.alarm_settings:
startActivity(new Intent(this, AlarmPopup.class));
Toast.makeText(this, "Open Up Alarm Dialog", Toast.LENGTH_SHORT).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void run()
{
while (clockRunnable != null)
{
try
{
Thread.sleep(1000);
} catch (InterruptedException e) { };
handler.post(clockRunnable);
}
}
/** PRIVATE METHODS FOR SIMPLIFICATION **/
private void updateUI(){
if(startAlarm == true){
//AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmStartTime = cal.get(Calendar.SECOND);
currView.setBackgroundColor(Color.RED);
}
else if((cal.get(Calendar.SECOND) - alarmStartTime) > DESIRED_ALARM_DURATION){
alarmStartTime = -1;
startAlarm = false;
currView.setBackgroundColor(Color.WHITE);
}
clock.setText(currTimeString);
}
Obviously I am missing something as far as grasping what is going on, but I can't tell what. Create a background thread, run your processes, pass it through the handler to control the variables, and send those variables through your UI update. I used http://developer.android.com/guide/faq/commontasks.html to gain that understanding.
Instead of making the activity implement Runnable, try this:
TimerTask task = new TimerTask() {
#Override
public void run() {
handler.post(clockRunnable);
}
};
Timer timer = new Timer();
timer.schedule(task, 0, 1000);
Even though I would use a different approach registering a BroadcastReceiver to receive tick actions from the system (every second).
Regards.

CountDownTimer trivia game score - Android (java)

I have a trivia game that displays 10 questions and they each have a 10 second timer. I have 2 problems that do not function correctly.
Firstly, If the timer runs out on a question, it displays the next question but the timer does not reset. The textviews stay at "Time's up!" and "Time Elapsed: 10000" instead of restarting the timer on the new question that is displayed.
Lastly, on the Results page the correct score is not displayed in the textview. The percentage textview displays correctly but the score textview displays "android.widget.TextView#416473c" or some other random memory location.
The program never crashes just functions incorrectly. Any code structure or other suggestions is much appreciated! This is my first android mobile app attempt and I am slowly and strugglingly through it. Yet enjoying it! :)
QuesteionView.java
public class QuestionView extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.questionviewmain);
answer1 = (Button)findViewById(R.id.answer1);
answer2 = (Button)findViewById(R.id.answer2);
answer3 = (Button)findViewById(R.id.answer3);
answer4 = (Button)findViewById(R.id.answer4);
question = (TextView)findViewById(R.id.question);
queries = getIntent().getParcelableArrayListExtra("queries");
timer = (TextView)findViewById(R.id.timer);
timeElapsedView = (TextView)findViewById(R.id.timeElapsedView);
cdTimer = new Timer(startTime, interval);
loadQuestion();
}
public void loadQuestion() {
if(i == 9) {
endQuiz();
} else {
if(!timerHasStarted) {
cdTimer.start();
timerHasStarted = true;
} else {
cdTimer.cancel();
timerHasStarted = false;
}
answer = queries.get(i).getCorrectAnswer();
question.setText(queries.get(i).getQuery());
answer1.setText(queries.get(i).getA1());
answer2.setText(queries.get(i).getA2());
answer3.setText(queries.get(i).getA3());
answer4.setText(queries.get(i).getA4());
answer1.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
queries.get(i).setSelectedAnswer(0);
if(answer == 0) {
correctAnswers++;
nextQuestion();
} else {
wrongAnswers++;
nextQuestion();
}
}
});
//same type of code for buttons for answers 2 through 4.
}
}
public void nextQuestion() {
score = score + timeElapsed;
i++;
loadQuestion();
}
public class Timer extends CountDownTimer {
public Timer(long startTime, long interval) {
super(startTime, interval);
}
public void onFinish() {
if(i == 9) {
cdTimer.cancel();
} else {
timer.setText("Time's up!");
timeElapsedView.setText("Time Elapsed: " + String.valueOf(startTime));
wrongAnswers++;
nextQuestion();
}
}
public void onTick(long millisUntilFinished) {
timer.setText("Time remain: " + Long.toString(millisUntilFinished));
timeElapsed = startTime - millisUntilFinished;
timeElapsedView.setText("Time Elapsed: " + Long.toString(timeElapsed));
}
}
public void endQuiz() {
Intent intent = new Intent(QuestionView.this, Results.class);
intent.putExtra("correctAnswers", correctAnswers);
intent.putExtra("wrongAnswers", wrongAnswers);
intent.putExtra("score", score);
intent.putParcelableArrayListExtra("queries", queries);
startActivity(intent);
}
}
Results.java
public class Results extends Activity {
QuestionView qv = new QuestionView();
ArrayList<Question> queryList = qv.getQueries();
int cAnswers;
int wAnswers;
long score;
ArrayList<Question> qs;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.resultsmain);
cAnswers = getIntent().getIntExtra("correctAnswers", -1);
wAnswers = getIntent().getIntExtra("wrongAnswers", -1);
score = getIntent().getLongExtra("score", -1);
qs = getIntent().getParcelableArrayListExtra("queries");
Button mainmenuBtn = (Button)findViewById(R.id.mainmenuBtn);
mainmenuBtn.setText("Main Menu");
mainmenuBtn.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
restart();
}
});
showResults();
}
public void showResults() {
ArrayList<TextView> tList = new ArrayList<TextView>(9);
TextView header = (TextView)findViewById(R.id.header);
header.setText("SUMMARY");
TextView percentage = (TextView)findViewById(R.id.percentage);
percentage.setText(Integer.toString(10 * cAnswers) + "%");
TextView score = (TextView)findViewById(R.id.score);
String s = "" + score;
score.setText(s);
TextView q1 = (TextView)findViewById(R.id.q1);
TextView q2 = (TextView)findViewById(R.id.q2);
TextView q3 = (TextView)findViewById(R.id.q3);
TextView q4 = (TextView)findViewById(R.id.q4);
TextView q5 = (TextView)findViewById(R.id.q5);
TextView q6 = (TextView)findViewById(R.id.q6);
TextView q7 = (TextView)findViewById(R.id.q7);
TextView q8 = (TextView)findViewById(R.id.q8);
TextView q9 = (TextView)findViewById(R.id.q9);
TextView q10 = (TextView)findViewById(R.id.q10);
tList.add(q1);
tList.add(q2);
tList.add(q3);
tList.add(q4);
tList.add(q5);
tList.add(q6);
tList.add(q7);
tList.add(q8);
tList.add(q9);
tList.add(q10);
for(int i = 0; i < tList.size(); i++) {
tList.get(i).setText(qs.get(i).getQuery());
if(qs.get(i).getSelectedAnswer() == qs.get(i).getCorrectAnswer()) {
tList.get(i).setTextColor(Color.GREEN);
} else {
tList.get(i).setTextColor(Color.RED);
}
}
}
public void restart() {
Intent intent = new Intent(Results.this, MainMenu.class);
startActivity(intent);
}
}
From all of that code, this is what I think is happening
Firstly, If the timer runs out on a question, it displays the next question but the timer does not reset. The textviews stay at "Time's up!" and "Time Elapsed: 10000" instead of restarting the timer on the new question that is displayed.
This appears to be due to you not setting your timerHasStarted variable to false after the time runs out so I would set that to false probably when you load your next question or after you show the results.
Lastly, on the Results page the correct score is not displayed in the textview. The percentage textview displays correctly but the score textview displays "android.widget.TextView#416473c" or some other random memory location.
This is because you are setting your q variables to the textview and getting the id. You need something like q1.getText().toString()
You have multiple variables with the same name score. So change it to
TextView score2 = (TextView)findViewById(R.id.score);
String s = "" + score;
score2.setText(s);
the score displays not what you expected because you assigned the String s = "" + score where score is what you named for the Textview which obviously not an integer and not equivalent to the score that the user has. :)

Categories

Resources