I am creating a trivia app. I want the right/wrong animation to occur immediately after the user clicks an answer, and then after 3 seconds, the question to switch automatically(fading into the next question). I tried doing this using Thread.sleep(3000), but the whole program freezes. This is my code so far:
binding.buttonTrue.setOnClickListener(view -> {
checkAnswer(true);
updateQuestion();
//these two calls invoke right/wrong animation
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
changeTheQuestion();
//this invokes fade animation
});
How can I add a period of time between these two animations? Thanks!
Full code:
package com.bawp.trivia;
import android.graphics.Color;
import android.media.AudioAttributes;
import android.media.SoundPool;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import com.bawp.trivia.data.Repository;
import com.bawp.trivia.databinding.ActivityMainBinding;
import com.bawp.trivia.model.Question;
import com.google.android.material.snackbar.Snackbar;
import java.util.ArrayList;
import java.util.List;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
public class MainActivity extends AppCompatActivity {
List<Question> questionList;
Handler mHandler;
private ActivityMainBinding binding;
private int currentQuestionIndex = 0;
SoundPool soundPool;
private int sound1, sound2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
questionList = new Repository().getQuestions(questionArrayList -> {
binding.questionTextview.setText(questionArrayList.get(currentQuestionIndex)
.getAnswer());
updateCounter(questionArrayList);
}
);
mHandler = new Handler();
binding.buttonNext.setOnClickListener(view -> {
currentQuestionIndex = (currentQuestionIndex + 1) % questionList.size();
updateQuestion();
});
binding.buttonTrue.setOnClickListener(view -> {
checkAnswer(true);
updateQuestion();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
changeTheQuestion();
}
}, 3000);
});
binding.buttonFalse.setOnClickListener(view -> {
checkAnswer(true);
updateQuestion();
new Handler().postDelayed(new Runnable() {
public void run() {
changeTheQuestion();
}
}, 3000);
});
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
.build();
soundPool = new SoundPool.Builder()
.setMaxStreams(4)
.setAudioAttributes(audioAttributes)
.build();
sound1 = soundPool.load(this, R.raw.correct, 1);
sound2 = soundPool.load(this, R.raw.wrong, 1);
}
private void checkAnswer(boolean userChoseCorrect) {
boolean answer = questionList.get(currentQuestionIndex).isAnswerTrue();
int snackMessageId = 0;
if (userChoseCorrect == answer) {
snackMessageId = R.string.correct_answer;
fadeAnimation();
soundPool.play(sound1, 1, 1, 0, 0, 1);
} else {
snackMessageId = R.string.incorrect;
shakeAnimation();
soundPool.play(sound2, 1, 1, 0, 0, 1);
}
Snackbar.make(binding.cardView, snackMessageId, Snackbar.LENGTH_SHORT)
.show();
}
private void updateCounter(ArrayList<Question> questionArrayList) {
binding.textViewOutOf.setText(String.format(getString(R.string.text_formatted),
currentQuestionIndex, questionArrayList.size()));
}
private void fadeAnimation() {
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.0f);
alphaAnimation.setDuration(300);
alphaAnimation.setRepeatCount(1);
alphaAnimation.setRepeatMode(Animation.REVERSE);
binding.cardView.setAnimation(alphaAnimation);
alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
binding.questionTextview.setTextColor(Color.GREEN);
}
#Override
public void onAnimationEnd(Animation animation) {
binding.questionTextview.setTextColor(Color.WHITE);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
private void changeTheQuestion() {
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.0f);
alphaAnimation.setDuration(300);
alphaAnimation.setRepeatCount(1);
alphaAnimation.setRepeatMode(Animation.REVERSE);
binding.cardView.setAnimation(alphaAnimation);
alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
binding.questionTextview.setTextColor(Color.BLUE);
}
#Override
public void onAnimationEnd(Animation animation) {
currentQuestionIndex = (currentQuestionIndex + 1) % questionList.size();
updateQuestion();
binding.questionTextview.setTextColor(Color.WHITE);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
private void updateQuestion() {
String question = questionList.get(currentQuestionIndex).getAnswer();
binding.questionTextview.setText(question);
updateCounter((ArrayList<Question>) questionList);
}
private void shakeAnimation() {
Animation shake = AnimationUtils.loadAnimation(MainActivity.this,
R.anim.shake_animation);
binding.cardView.setAnimation(shake);
shake.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
binding.questionTextview.setTextColor(Color.RED);
}
#Override
public void onAnimationEnd(Animation animation) {
binding.questionTextview.setTextColor(Color.WHITE);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
}
Repository.java:
package com.bawp.trivia.data;
import android.util.Log;
import com.android.volley.Request;
import com.android.volley.toolbox.JsonArrayRequest;
import com.bawp.trivia.controller.AppController;
import com.bawp.trivia.model.Question;
import org.json.JSONException;
import java.util.ArrayList;
import java.util.List;
public class Repository {
ArrayList<Question> questionArrayList = new ArrayList<>();
String url = "https://raw.githubusercontent.com/curiousily/simple-quiz/master/script/statements-data.json";
public List<Question> getQuestions( final AnswerListAsyncResponse callBack) {
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET,
url, null, response -> {
for (int i = 0; i < response.length(); i++) {
try {
Question question = new Question(response.getJSONArray(i).get(0).toString(),
response.getJSONArray(i).getBoolean(1));
//Add questions to arraylist/list
questionArrayList.add(question);
//Log.d("Hello", "getQuestions: " + questionArrayList);
} catch (JSONException e) {
e.printStackTrace();
}
}
if (null != callBack) callBack.processFinished(questionArrayList);
}, error -> {
});
AppController.getInstance().addToRequestQueue(jsonArrayRequest);
return questionArrayList;
}
}
You cannot call Thread.sleep() on the main (UI) thread. This will freeze your app and cause your app to crash with ANR (Application Not Responsive) error.
You can just post a Runnable that will run a chunk of code after a certain period of time. Something like this:
new Handler().postDelayed(new Runnable() {
public void run() {
changeTheQuestion();
}
}, 3000);
Related
I created a virtual assistant app in Android Studio and it working fine until I exit the app window and the process stops. I want to make the app run in the background always so when it get's the wake word anytime it will respond. I tried using a Service but I couldn't make it work.
Can you help me please?
This is my code:
package com.eylon.jarvis;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import java.util.ArrayList;
import java.util.Locale;
import ai.picovoice.porcupine.Porcupine;
import ai.picovoice.porcupine.PorcupineActivationException;
import ai.picovoice.porcupine.PorcupineActivationLimitException;
import ai.picovoice.porcupine.PorcupineActivationRefusedException;
import ai.picovoice.porcupine.PorcupineActivationThrottledException;
import ai.picovoice.porcupine.PorcupineException;
import ai.picovoice.porcupine.PorcupineInvalidArgumentException;
import ai.picovoice.porcupine.PorcupineManager;
import ai.picovoice.porcupine.PorcupineManagerCallback;
enum AppState {
STOPPED,
WAKEWORD,
STT
}
public class MainActivity extends AppCompatActivity {
private static final String ACCESS_KEY = "Oc8ZOSkVtJHWKhVW3iGMedHDSCSXn6P4vQtrQBl8hNLXwLmxLhs2AA==";
private PorcupineManager porcupineManager = null;
TextView textView;
ToggleButton button;
private SpeechRecognizer speechRecognizer;
private Intent speechRecognizerIntent;
private AppState currentState;
private void displayError(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
private final PorcupineManagerCallback porcupineManagerCallback = new PorcupineManagerCallback() {
#Override
public void invoke(int keywordIndex) {
runOnUiThread(() -> {
textView.setText("");
try {
// need to stop porcupine manager before speechRecognizer can start listening.
porcupineManager.stop();
} catch (PorcupineException e) {
displayError("Failed to stop Porcupine.");
return;
}
speechRecognizer.startListening(speechRecognizerIntent);
currentState = AppState.STT;
});
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.text1);
button = findViewById(R.id.button1);
if (!SpeechRecognizer.isRecognitionAvailable(this)) {
displayError("Speech Recognition not available.");
}
// Creating the Intent of the Google speech to text and adding extra variables.
speechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, "en-US");
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en-US");
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_ONLY_RETURN_LANGUAGE_PREFERENCE, "en-US");
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Start speaking");
try {
porcupineManager = new PorcupineManager.Builder()
.setAccessKey(ACCESS_KEY)
.setKeyword(Porcupine.BuiltInKeyword.JARVIS)
.setSensitivity(0.7f)
.build(getApplicationContext(), porcupineManagerCallback);
} catch (PorcupineInvalidArgumentException e) {
onPorcupineInitError(
String.format("%s\nEnsure your accessKey '%s' is a valid access key.", e.getMessage(), ACCESS_KEY)
);
} catch (PorcupineActivationException e) {
onPorcupineInitError("AccessKey activation error");
} catch (PorcupineActivationLimitException e) {
onPorcupineInitError("AccessKey reached its device limit");
} catch (PorcupineActivationRefusedException e) {
onPorcupineInitError("AccessKey refused");
} catch (PorcupineActivationThrottledException e) {
onPorcupineInitError("AccessKey has been throttled");
} catch (PorcupineException e) {
onPorcupineInitError("Failed to initialize Porcupine " + e.getMessage());
}
currentState = AppState.STOPPED;
}
private void onPorcupineInitError(final String errorMessage) {
runOnUiThread(() -> {
TextView errorText = findViewById(R.id.text1);
errorText.setText(errorMessage);
ToggleButton recordButton = findViewById(R.id.button1);
recordButton.setChecked(false);
recordButton.setEnabled(false);
});
}
#Override
protected void onStop() {
if (button.isChecked()) {
stopService();
button.toggle();
speechRecognizer.destroy();
}
super.onStop();
}
private boolean hasRecordPermission() {
return ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
== PackageManager.PERMISSION_GRANTED;
}
private void requestRecordPermission() {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO},
0);
}
#SuppressLint("SetTextI18n")
private void playback(int milliSeconds) {
speechRecognizer.stopListening();
currentState = AppState.WAKEWORD;
new Handler(Looper.getMainLooper()).postDelayed(() -> {
if (currentState == AppState.WAKEWORD) {
porcupineManager.start();
textView.setText("Listening for " + Porcupine.BuiltInKeyword.JARVIS + " ...");
}
}, milliSeconds);
}
private void stopService() {
if (porcupineManager != null) {
try {
porcupineManager.stop();
} catch (PorcupineException e) {
displayError("Failed to stop porcupine.");
}
}
textView.setText("");
speechRecognizer.stopListening();
speechRecognizer.destroy();
currentState = AppState.STOPPED;
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults.length == 0 || grantResults[0] == PackageManager.PERMISSION_DENIED) {
displayError("Microphone permission is required for this app!");
requestRecordPermission();
} else {
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
speechRecognizer.setRecognitionListener(new SpeechListener());
playback(0);
}
}
public void process(View view) {
if (button.isChecked()) {
if (hasRecordPermission()) {
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
speechRecognizer.setRecognitionListener(new SpeechListener());
playback(0);
} else {
requestRecordPermission();
}
} else {
stopService();
}
}
private class SpeechListener implements RecognitionListener {
#Override
public void onReadyForSpeech(Bundle params) {
}
#Override
public void onBeginningOfSpeech() {
}
#Override
public void onRmsChanged(float rmsdB) {
}
#Override
public void onBufferReceived(byte[] buffer) {
}
#Override
public void onEndOfSpeech() {
}
#SuppressLint("SwitchIntDef")
#Override
public void onError(int error) {
switch (error) {
case SpeechRecognizer.ERROR_AUDIO:
displayError("Error recording audio.");
break;
case SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS:
displayError("Insufficient permissions.");
break;
case SpeechRecognizer.ERROR_NETWORK_TIMEOUT:
case SpeechRecognizer.ERROR_NETWORK:
displayError("Network Error.");
break;
case SpeechRecognizer.ERROR_NO_MATCH:
if (button.isChecked()) {
displayError("No recognition result matched.");
playback(1000);
}
case SpeechRecognizer.ERROR_CLIENT:
return;
case SpeechRecognizer.ERROR_RECOGNIZER_BUSY:
displayError("Recognition service is busy.");
break;
case SpeechRecognizer.ERROR_SERVER:
displayError("Server Error.");
break;
case SpeechRecognizer.ERROR_SPEECH_TIMEOUT:
displayError("No speech input.");
break;
default:
displayError("Something wrong occurred.");
}
stopService();
button.toggle();
}
#Override
public void onResults(Bundle results) {
ArrayList<String> data = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
audioResponseSelecting(data.get(0).toLowerCase(Locale.ROOT));
textView.setText(data.get(0));
playback(3000);
}
#Override
public void onPartialResults(Bundle partialResults) {
ArrayList<String> data = partialResults.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
audioResponseSelecting(data.get(0).toLowerCase(Locale.ROOT));
textView.setText(data.get(0));
}
#Override
public void onEvent(int eventType, Bundle params) {
}
}
// The response selecting function.
public void audioResponseSelecting(String transcript)
{
if (transcript.equals(("Good morning").toLowerCase(Locale.ROOT)))
{
executeResponse(R.raw.good_morning);
}
else if (transcript.equals(("Who is your creator").toLowerCase(Locale.ROOT)))
{
executeResponse(R.raw.creator);
}
}
// The audio file response execution function.
public void executeResponse(final int audio)
{
MediaPlayer response = MediaPlayer.create(MainActivity.this, audio);
response.start();
}
}
By design, all SpeechRecognizer's methods "must be invoked only from the main application thread."
Main application thread is also referred to as "UI thread".
This means that SpeechRecognizer cannot run in a service.
My timer app is crashing as soon as countDownTimer.cancel() method is called
it is showing null object reference even though I have done it correctly, I can't find the problem.
Please, someone, take a look on the code below : (also I am attaching logcat)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual
method 'void android.os.CountDownTimer.cancel()' on a null object
reference
package com.example.rajdeepkgautam.itimer;
import android.media.MediaPlayer;
import android.os.CountDownTimer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
int max = 600;
int start = 30;
TextView timerTextView;
SeekBar timerSeekBar;
boolean timerActive = false;
Button runButton;
CountDownTimer countDownTimer;
public void resetTimer() {
timerTextView.setText("0:30");
timerSeekBar.setProgress(start);
timerSeekBar.setEnabled(true);
countDownTimer.cancel();
runButton.setText("RUN!");
timerActive = false;
}
public void buttonClicked(View view) {
if(timerActive) {
resetTimer();
} else {
timerActive = true;
runButton.setText("STOP!");
timerSeekBar.setEnabled(false);
CountDownTimer countDownTimer = new CountDownTimer((timerSeekBar.getProgress()*1000) + 100, 1000) {
#Override
public void onTick(long l) {
TimerUpdate((int) l/1000);
}
#Override
public void onFinish() {
MediaPlayer mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.horn);
mediaPlayer.start();
resetTimer();
}
}.start();
}
}
public void TimerUpdate(int TimeLeft) {
int minutes = TimeLeft/60;
int seconds = TimeLeft - (minutes*60);
if(seconds <=9) {
timerTextView.setText(Integer.toString(minutes) + ":" + "0" + Integer.toString(seconds));
} else {
timerTextView.setText(Integer.toString(minutes) + ":" + Integer.toString(seconds));
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
timerSeekBar = findViewById(R.id.timerSeekBar);
timerTextView = findViewById(R.id.timerTextView);
runButton = findViewById(R.id.runButton);
timerSeekBar.setMax(max);
timerSeekBar.setProgress(start);
timerSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
TimerUpdate(i);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
}
It's because of not initializing the countDownTimer. You are creating a local variable and never assigning the instantiated CountDownTimer to the countDownTimer of MainActivity.
Change the line:
CountDownTimer countDownTimer = new CountDownTimer((timerSeekBar.getProgress()*1000) + 100, 1000)
to:
countDownTimer = new CountDownTimer((timerSeekBar.getProgress()*1000) + 100, 1000)
I want to display a TextView during 10 seconds, then make it disappear, every 5 minutes, but I am not able to do it, I have already read this Android CountDownTimer - adding time results in multiple timers running, and many others, but still cant do it, here is what I have tried
private void placeFingerPrint() {
authViewModel.getSession().compose(bindToLifecycle()).subscribe(session -> {
this.session = session;
TextView textView = view.findViewById(R.id.player_finger_print);
MediaItem mediaItem = getPlayingMediaItem();
new CountDownTimer(20000, 10000) {
#Override
public void onTick(long millisUntilFinished) {
if (fingerprint.getChannel() != null && fingerprint.getChannel().contains(mediaItem.getExternalId())) {
textView.setVisibility(View.VISIBLE);
textView.setText(session.getHouseHoldId());
} else {
textView.setVisibility(View.GONE);
}
}
#Override
public void onFinish() {
textView.setVisibility(View.GONE);
start();
}
}.start();
});
We can achieve this using Thread in android. CountDownTimer usually uses if you have a definite end time.
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class ThreadSample extends AppCompatActivity {
Handler uiHandler = new Handler();
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_thread_sample);
textView = findViewById(R.id.textView);
NameCounter runnable = new NameCounter();
new Thread(runnable).start();
}
class NameCounter implements Runnable {
int count = 0;
boolean show = true;
#Override
public void run() {
while (true) { // add your customized condition here to exit from the loop.
uiHandler.post(new Runnable() {
#Override
public void run() {
if (show)
textView.setVisibility(View.VISIBLE);
else
textView.setVisibility(View.GONE);
}
});
try {
if (show) {
Thread.sleep(10000);
show = false;
} else {
Thread.sleep(5000);
show = true;
}
} catch (Exception e) {
Log.e("ERROR", e.getMessage());
}
}
}
}
}
This is my Firebase Database Structure:
enter image description here
I'm fairly new to Java and trying to figure out how to solve this.
So I am making a Quiz app till now everything works fine except I cant retrieve data from Firebase RealTime Database.
My layout:
I have a textView to display the question
4 Buttons to display the options that the user can choose from
When the user clicks on a Button it either the Button Color turns to Red or Green depending on the question answer if it was correct or no.
I added one more textView for the timer which is neglected for no
I can only retrieve data for the Question textView but the buttons does not show anything
My Question Class:
package com.example.android.quizapp;
public class Question
{
public String question,option1,option2,option3,option4,answer;
public Question(String question,String option1,String option2,String option3,String option4,String answer)
{
this.question=question;
this.option1=option1;
this.option2=option2;
this.option3=option3;
this.option4=option4;
this.answer=answer;
}
public Question()
{
}
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public String getOption1() {
return option1;
}
public void setOption1(String option1) {
this.option1 = option1;
}
public String getOption2() {
return option2;
}
public void setOption2(String option2) {
this.option2 = option2;
}
public String getOption3() {
return option3;
}
public void setOption3(String option3) {
this.option3 = option3;
}
public String getOption4() {
return option4;
}
public void setOption4(String option4) {
this.option4 = option4;
}
public String getAnswer() {
return answer;
}
public void setAnswer(String answer) {
this.answer = answer;
}
}
My questions java activity class:
package com.example.android.quizapp;
import android.app.VoiceInteractor;
import android.graphics.Color;
import android.graphics.Path;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
public class questions extends AppCompatActivity
{
TextView txtquestions,timer;
Button OptionA,OptionB,OptionC,OptionD;
int total=0;
int correct=0;
int wrong=0;
DatabaseReference reference;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_questions);
txtquestions=(TextView)findViewById(R.id.Questions);
OptionA=(Button)findViewById(R.id.OptionA);
OptionB=(Button)findViewById(R.id.OptionB);
OptionC=(Button)findViewById(R.id.OptionC);
OptionD=(Button)findViewById(R.id.OptionD);
timer=(TextView)findViewById(R.id.timer);
updateQuestions();
}
private void updateQuestions()
{
total++;
if(total>2)
{
//open the result activity
Toast.makeText(questions.this,"Done",Toast.LENGTH_SHORT).show();
}
else
{
reference=FirebaseDatabase.getInstance().getReference().child("questions").child(String.valueOf(total));
reference.addValueEventListener((new ValueEventListener()
{
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot)
{
final Question question=dataSnapshot.getValue(Question.class);
txtquestions.setText(question.getQuestion());
OptionA.setText(question.getOption1());
OptionB.setText(question.getOption2());
OptionC.setText(question.getOption3());
OptionD.setText(question.getOption4());
OptionA.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if(OptionA.getText().toString().equals(question.getAnswer()))
{
OptionA.setBackgroundColor(Color.GREEN);
Handler handler=new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
correct++;
OptionA.setBackgroundColor(Color.parseColor("#03A9F4"));
updateQuestions();
}
},1500);
}
else
{
//answer if wrong...we will find the correct answer and make it green
wrong++;
OptionA.setBackgroundColor(Color.RED);
if(OptionB.getText().toString().equals(question.getAnswer()))
{
OptionB.setBackgroundColor(Color.GREEN);
}
else if(OptionC.getText().toString().equals(question.getAnswer()))
{
OptionC.setBackgroundColor(Color.GREEN);
}
else if(OptionD.getText().toString().equals(question.getAnswer()))
{
OptionD.setBackgroundColor(Color.GREEN);
}
//Replace all the colors and update the question
Handler handler=new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
OptionA.setBackgroundColor(Color.parseColor("#FDCC12"));
OptionB.setBackgroundColor(Color.parseColor("#FDCC12"));
OptionC.setBackgroundColor(Color.parseColor("#FDCC12"));
OptionD.setBackgroundColor(Color.parseColor("#FDCC12"));
updateQuestions();
}
},1500);
}
}
});
OptionB.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if(OptionB.getText().toString().equals(question.getAnswer()))
{
OptionB.setBackgroundColor(Color.GREEN);
Handler handler=new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
correct++;
OptionB.setBackgroundColor(Color.parseColor("#03A9F4"));
updateQuestions();
}
},1500);
}
else
{
//answer if wrong...we will find the correct answer and make it green
wrong++;
OptionB.setBackgroundColor(Color.RED);
if(OptionA.getText().toString().equals(question.getAnswer()))
{
OptionA.setBackgroundColor(Color.GREEN);
}
else if(OptionC.getText().toString().equals(question.getAnswer()))
{
OptionC.setBackgroundColor(Color.GREEN);
}
else if(OptionD.getText().toString().equals(question.getAnswer()))
{
OptionD.setBackgroundColor(Color.GREEN);
}
//Replace all the colors and update the questions
Handler handler=new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
OptionA.setBackgroundColor(Color.parseColor("#FDCC12"));
OptionB.setBackgroundColor(Color.parseColor("#FDCC12"));
OptionC.setBackgroundColor(Color.parseColor("#FDCC12"));
OptionD.setBackgroundColor(Color.parseColor("#FDCC12"));
updateQuestions();
}
},1500);
}
}
});
OptionC.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if(OptionC.getText().toString().equals(question.getAnswer()))
{
OptionC.setBackgroundColor(Color.GREEN);
Handler handler=new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
correct++;
OptionC.setBackgroundColor(Color.parseColor("#03A9F4"));
updateQuestions();
}
},1500);
}
else
{
//answer if wrong...we will find the correct answer and make it green
wrong++;
OptionC.setBackgroundColor(Color.RED);
if(OptionA.getText().toString().equals(question.getAnswer()))
{
OptionA.setBackgroundColor(Color.GREEN);
}
else if(OptionB.getText().toString().equals(question.getAnswer()))
{
OptionB.setBackgroundColor(Color.GREEN);
}
else if(OptionD.getText().toString().equals(question.getAnswer()))
{
OptionD.setBackgroundColor(Color.GREEN);
}
//Replace all the colors and update the questions
Handler handler=new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
OptionA.setBackgroundColor(Color.parseColor("#FDCC12"));
OptionB.setBackgroundColor(Color.parseColor("#FDCC12"));
OptionC.setBackgroundColor(Color.parseColor("#FDCC12"));
OptionD.setBackgroundColor(Color.parseColor("#FDCC12"));
updateQuestions();
}
},1500);
}
}
});
OptionD.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if(OptionD.getText().toString().equals(question.getAnswer()))
{
OptionD.setBackgroundColor(Color.GREEN);
Handler handler=new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
correct++;
OptionD.setBackgroundColor(Color.parseColor("#03A9F4"));
updateQuestions();
}
},1500);
}
else
{
//answer if wrong...we will find the correct answer and make it green
wrong++;
OptionD.setBackgroundColor(Color.RED);
if(OptionA.getText().toString().equals(question.getAnswer()))
{
OptionA.setBackgroundColor(Color.GREEN);
}
else if(OptionB.getText().toString().equals(question.getAnswer()))
{
OptionB.setBackgroundColor(Color.GREEN);
}
else if(OptionC.getText().toString().equals(question.getAnswer()))
{
OptionC.setBackgroundColor(Color.GREEN);
}
//Replace all the colors and update the questions
Handler handler=new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
OptionA.setBackgroundColor(Color.parseColor("#FDCC12"));
OptionB.setBackgroundColor(Color.parseColor("#FDCC12"));
OptionC.setBackgroundColor(Color.parseColor("#FDCC12"));
OptionD.setBackgroundColor(Color.parseColor("#FDCC12"));
updateQuestions();
}
},1500);
}
}
});
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError)
{
}
}));
}
}
}
I only expect for the Buttons to be able to display data from Firebase database and the colors to work correctly because right now they all turn red when pressed
Problem solved I just needed to import a JSON file into my Database instead of creating it from Firebase Database
Don't know this issue but you can simply do get value in string than you can use the string variable for set Text. like that:
String A, B, C, D;
A = question.getOption1();
B = question.getOption2();
C = question.getOption3();
D = question.getOption4();
OptionA.setText(A);
OptionB.setText(B);
OptionC.setText(C);
OptionD.setText(D);
Just a Suggestion It will be work for you.
Are you sure that the options retrieved from database have values?
As you do not provide more details in your code that retrieves data from Database check if your options have values with :
Log.i("OptionA value: ", question.getOption1());
Check your logcat and tell us what you see.
It seems that the text for you OptionButtons is null. It is normal that all buttons turn red because the answer is compared with null.
I want to change the button color dynamically.
After writing, testing and researching, I found that the display thread should be different then the code, so I used a handler.
I am trying to change the color of a button from default to black for some time and then getting it back to default color,
but it is not happening, it just shows a default button.
Following is my code
import android.content.Intent;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import java.io.IOException;
import java.util.Random;
import android.os.Handler ;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button b1;
Random r = new Random();
int random_selection;
int i;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b1 = (Button) findViewById(R.id.button);
b1.setOnClickListener(this);
main();
}
public void main() {
// Thread t1 = new Thread(new MainActivity());
// this wi run() function
Handler handler1 = new Handler();
handler1.postDelayed(new Runnable() {
#Override
public void run() {
int count = 0;
try {
System.out.println("inside run");
for (i=0;i<4 ;i++ )
// android.widget.Toast.makeText(getBaseContext(), count,android.widget.Toast.LENGTH_SHORT).show();
Handler handler2 = new Handler();
int x = randomgen();
// android.widget.Toast.makeText(getBaseContext(), x,android.widget.Toast.LENGTH_SHORT).show();
if (x == 1) {
b1.setBackgroundColor(Color.BLACK);
handler2.postDelayed(new Runnable() {
#Override
public void run() {
b1.setBackgroundResource(android.R.drawable.btn_default);
}
}, 10000);
} else if (x == 2) {
b2.setBackgroundColor(Color.BLACK);
handler2.postDelayed(new Runnable() {
#Override
public void run() {
b2.setBackgroundResource(android.R.drawable.btn_default);
}
}, 2000);
} else if (x == 3) {
b3.setBackgroundColor(Color.BLACK);
handler2.postDelayed(new Runnable() {
#Override
public void run() {
b3.setBackgroundResource(android.R.drawable.btn_default);
}
}, 2000);
} else if (x == 4) {
b4.setBackgroundColor(Color.BLACK);
handler2.postDelayed(new Runnable() {
#Override
public void run() {
b4.setBackgroundResource(android.R.drawable.btn_default);
}
}, 2000);
}
}
}catch (Exception e) {
System.out.println("inside catch");
e.printStackTrace();
}
}
}, 1000 );
}
public int randomgen() {
random_selection = r.nextInt(4) + 1;
return random_selection;
}
The reason being is your b1.setBackgroundResource(android.R.drawable.btn_default);
is outside of the delayed handler,
Change your function main to this:
public void main() {
int count = 0;
Handler handler1 = new Handler();
handler1.postDelayed(new Runnable() {
Handler handler2 = new Handler();
#Override
public void run() {
try {
System.out.println("inside run");
// android.widget.Toast.makeText(getBaseContext(), x,android.widget.Toast.LENGTH_SHORT).show();
b1.setBackgroundColor(Color.BLACK);
handler2.postDelayed(new Runnable() {
#Override
public void run() {
b1.setBackgroundResource(android.R.drawable.btn_default);
}
}, 2000);
} catch (Exception e) {
System.out.println("inside catch");
e.printStackTrace();
}
}
}, 1000);
}
Use a Thread instead:
b1.setBackgroundColor(Color.BLACK);
new Thread(new Runnable() {
#Override
public void run() {
try { System.sleep(2000) } catch(Exception e) {}
runOnUiThread(new Runnable() {
#Override
public void run() {
b1.setBackgroundResource(android.R.drawable.btn_default);
}
});
}
}).start();