My app goes live recently on the google play store. I tested it on multiple devices and it works smoothly on all of them. After I launched it, it crashes more frequently. This is the crashlytic data provided by firebase.
Fatal Exception: java.lang.IndexOutOfBoundsException Index: 0, Size: 0
Fatal Exception: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.get(ArrayList.java:437)
at com.supun.mcqapp.QuestionsActivity.setQuestion(QuestionsActivity.java:151)
at com.supun.mcqapp.QuestionsActivity.access$100(QuestionsActivity.java:43)
at com.supun.mcqapp.QuestionsActivity$1.onComplete(QuestionsActivity.java:105)
at com.google.android.gms.tasks.zzj.run(:4)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7561)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:995)
Here is my java code(relevant areas. I just put "********" to identify it easy in the full script)
QuestionsActivity.java:151
private void setQuestion() { timer.setText(String.valueOf(40));
question.setText(questionList.get(0).getQuestion()); **//this is 151 line** option1.setText(questionList.get(0).getOptionA()); option2.setText(questionList.get(0).getOptionB()); option3.setText(questionList.get(0).getOptionC()); option4.setText(questionList.get(0).getOptionD()); qCount.setText(String.valueOf(1)+"/"+ String.valueOf(questionList.size())); startTimer(); quesNum = 0;
}
QuestionsActivity.java:43
public class QuestionsActivity extends AppCompatActivity implements View.OnClickListener
QuestionsActivity.java:105
} setQuestion();
full code -- relevent areas marked with ***** mark.
*********this is QuestionsActivity.java:43 line ********
public class QuestionsActivity extends AppCompatActivity implements View.OnClickListener {
private TextView question, qCount, timer;
private Button option1, option2, option3, option4;
private List<Question> questionList;
private int quesNum;
private CountDownTimer countDown;
private int score;
private FirebaseFirestore firestore;
private int setNo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_questions);
question = findViewById(R.id.question);
qCount = findViewById(R.id.qcount);
timer = findViewById(R.id.timer);
option1 = findViewById(R.id.optin_a_btn);
option2 = findViewById(R.id.optin_b_btn);
option3 = findViewById(R.id.optin_c_btn);
option4 = findViewById(R.id.optin_d_btn);
option1.setOnClickListener(this);
option2.setOnClickListener(this);
option3.setOnClickListener(this);
option4.setOnClickListener(this);
questionList = new ArrayList<>();
setNo = getIntent().getIntExtra("SETNO",1);
//add below line
firestore = FirebaseFirestore.getInstance();
getQuestionList();
score = 0;
}
private void getQuestionList() {
questionList.clear();
firestore.collection("QUIZ").document("CAT" + String.valueOf(category_id)).collection("SET" + String.valueOf(setNo))
.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
Map<String, QueryDocumentSnapshot> questList = new ArrayMap<>();
if (task.isSuccessful()){
QuerySnapshot questions = task.getResult();
for (QueryDocumentSnapshot doc : questions){
questionList.add(new Question(doc.getString("QUESTION"),
doc.getString("A"),
doc.getString("B"),
doc.getString("C"),
doc.getString("D"),
Integer.valueOf(doc.getString("ANSWER"))
));
} setQuestion(); *************105 line
}else {
Toast.makeText(QuestionsActivity.this,task.getException().getMessage(),Toast.LENGTH_SHORT).show();
}
}
});
}
private void setQuestion()
{
timer.setText(String.valueOf(40));
question.setText(questionList.get(0).getQuestion()); *****151 line********
option1.setText(questionList.get(0).getOptionA());
option2.setText(questionList.get(0).getOptionB());
option3.setText(questionList.get(0).getOptionC());
option4.setText(questionList.get(0).getOptionD());
qCount.setText(String.valueOf(1)+"/"+ String.valueOf(questionList.size()));
startTimer();
quesNum = 0;
}
private void startTimer()
{
countDown = new CountDownTimer(40000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
timer.setText(String.valueOf(millisUntilFinished / 1000));
}
@Override
public void onFinish() {
changeQuestion();
}
};
countDown.start();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onClick(View v) {
int selectedOption = 0;
switch (v.getId())
{
case R.id.optin_a_btn:
selectedOption = 1;
break;
case R.id.optin_b_btn:
selectedOption = 2;
break;
case R.id.optin_c_btn:
selectedOption = 3;
break;
case R.id.optin_d_btn:
selectedOption = 4;
break;
default:
}
countDown.cancel();
checkAnswer(selectedOption, v);
}
//Remove tint list
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void checkAnswer(int selectedOption, View view)
{
if(selectedOption == questionList.get(quesNum).getCorrectAns())
{
//Right ans
((Button)view).setBackgroundTintList(ColorStateList.valueOf(Color.BLUE));
score++;
}
else
{
//Wrong ans
((Button)view).setBackgroundTintList(ColorStateList.valueOf(Color.YELLOW));
switch (questionList.get(quesNum).getCorrectAns())
{
case 1:
option1.setBackgroundTintList(ColorStateList.valueOf(Color.BLUE));
break;
case 2:
option2.setBackgroundTintList(ColorStateList.valueOf(Color.BLUE));
break;
case 3:
option3.setBackgroundTintList(ColorStateList.valueOf(Color.BLUE));
break;
case 4:
option4.setBackgroundTintList(ColorStateList.valueOf(Color.BLUE));
break;
}
}
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
changeQuestion();
}
},500);
}
private void changeQuestion()
{
if( quesNum < questionList.size()- 1)
{
quesNum++;
playAnim(question,0,0);
playAnim(option1,0,1);
playAnim(option2,0,2);
playAnim(option3,0,3);
playAnim(option4,0,4);
qCount.setText(String.valueOf(quesNum+1)+"/" + String.valueOf(questionList.size()));
timer.setText(String.valueOf(40));
startTimer();
}
else
{
//score activity
Intent intent = new Intent(QuestionsActivity.this,ScoreActivity.class);
intent.putExtra("SCORE",String.valueOf(score) + "/" + String.valueOf(questionList.size()));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
//QuestionsActivity.this.finish();
}
}
private void playAnim(final View view, final int value, int viewNum)
{
view.animate().alpha(value).scaleX(value).scaleY(value).setDuration(500)
.setStartDelay(100).setInterpolator(new DecelerateInterpolator())
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onAnimationEnd(Animator animation) {
if (value == 0)
{
switch (viewNum)
{
case 0:
((TextView)view).setText(questionList.get(quesNum).getQuestion());
break;
case 1:
((Button)view).setText(questionList.get(quesNum).getOptionA());
break;
case 2:
((Button)view).setText(questionList.get(quesNum).getOptionB());
break;
case 3:
((Button)view).setText(questionList.get(quesNum).getOptionC());
break;
case 4:
((Button)view).setText(questionList.get(quesNum).getOptionD());
break;
}
if (viewNum != 0)
((Button)view).setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#023047")));
playAnim(view,1,viewNum);
}
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
@Override
public void onBackPressed() {
super.onBackPressed();
countDown.cancel();
}
}