Android Quiz Application with Json Parser, Php and Mysql Database

Android Quiz Application with Json Parser, Php and Mysql Database

In this tutorial we are going to learn how to create an android quiz application with Json parser, Php and Mysql database. This is going to be a long tutorial so relax as we take the journey together.

Most of the concepts you will see here has been covered in some of my previous tutorials and I will suggest you read these two tutorials before you continue – How to Parse JSON in Android and Android Login and Registration with Php and Mysql.

We are going to store our quiz questions and answers in Mysql database which can be local or remote. One advantage of using this concept in android quiz application is that it will afford you the opportunity to add and edit quiz questions and solutions with the need to update your application.

Android quiz application can also be achieved by storing the quiz questions and solutions using android SQLITE database. In this case, the application will not require internet connection to access the database.

If you want a complete Android Quiz App with Web Admin Panel follow this link

If you do not know much about Php and Mysql, kindly read it up w3school.com.

Before we start with the detailed instruction, it is important to know that we will first of all download and install a web server in our system. I am going to use WAMP server but feel free to use whatever web server you are familiar with.

The detail instruction on how to install WAMP can be found on their website.

wampimage

With the web server installed, start your web server and go to PhpMyAdmin. We will create a new database called quiz. In our created database, we will create a single table called quiz_questions. The below script is used to create our users table.

CREATE TABLE IF NOT EXISTS 'quiz_questions' (
'id' bigint(20) NOT NULL AUTO_INCREMENT,
'question' varchar(300) NOT NULL,
'possible_answers' varchar(300) NOT NULL,
'correct_answer' int(5) NOT NULL,
PRIMARY KEY ('id'),
UNIQUE KEY 'question' ('question')
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

The next step is to create our Php project structure. I will make use of Aptana IDE for Php and Mysql development but feel free to use whatever IDE you like the best.

Create a folder called Android_Quiz inside the www folder of your web server. Inside this folder, create another folder called include. The include folder will house our configuration file for database connection.

Create a file called index.php in your project root directory. All the request that comes to the web server will go through this index file.

In our include folder, create three files called config.php, db.php and quiz.php.

When a client sends a request, the index.php file will analyze the request and talk to the database. It will retrieve all the quiz questions present in the quiz_questions table. The data will first be converted to an array and rather will be output as a Json object.

The android application will consume the Json object and we will use android Json parsing API to manipulate the content of the server response.

Open the Php database config file called config.php and paste the following code on it.

<?php

define("DB_HOST", "localhost");

define("DB_USER", "quiz");

define("DB_PASSWORD", "quiz");

define("DB_NAME", "quiz");

?>

This is the database connection details. Please make sure you change this information in accordance with your database server. In the code above we are just defining the database connection properties.

With this in place, we will establish a database connection with our Php application. This is done in the db.php file. Open the file and paste the following code below.

<?php

include_once 'config.php';

class DbConnect{

private $connect;

public function __construct(){
$this->connect = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);

if (mysqli_connect_errno($this->connect)){
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
}

public function getDb(){
return $this->connect;
}
}

The config file was included in the beginning of db.php file. The getDB function returns an instance of our database connection.

Now that we have our database connection, create a quiz.php file. The quiz class contains a function that will query the database to obtain all the quiz questions present in the database.

The quiz class includes the db.php class. Copy and paste the following code in the file.

<?php

include_once 'db.php';

class Quiz{

private $db;

private $db_table = "quiz_questions";

public function __construct(){

$this->db = new DbConnect();

}

public function getAllQuizQuestions(){

$json_array = array();

$query = "select * from quiz_questions";

$result = mysqli_query($this->db->getDb(), $query);

if(mysqli_num_rows($result) > 0){

while ($row = mysqli_fetch_assoc($result)) {

$json_array["quiz_questions"][] = $row;

}

}

return $json_array;

}

}

?>

Now we will finish up with our index.php file. We will include the quiz.php file in the index.php. What it will basically do is to return all the quiz questions store in MYSQL database and output it as a Json object.

Please note that this is a simple tutorial and there is no other measure taken to make sure that the request is not malicious.

The code is below. You can copy it and paste in your own project.

<?php

require_once 'include/quiz.php';

$quizObject = new Quiz();

$json_quiz_objects = $quizObject->getAllQuizQuestions();

echo json_encode($json_quiz_objects);

?>

A simple example of the Json object output from the server is shown below

{"quiz_questions":[{"id":"1","question":"Who is the most popular musician in Nigeria","possible_answers":"Tufac, P Square, Dbanji, Tiwa Savage","correct_answer":"1"},{"id":"2","question":"Who is the winner of 2015 Presidential Election in Nigeria?","possible_answers":"Obasanjo, Goodluck, Buhari, Fashola","correct_answer":"3"}]}

With the web application completed, we will move over to create our android application.

In order to parse JSON object from a remote server source, we are going to need internet access for our application.

It is important to note that when you are working with internet or accessing data from a remote source in android, you will need to add internet permission in your android manifest file.

<uses-permission android:name="android.permission.INTERNET"/>

We are going to use android API for HTTP request. Once we get the Json output as an InputStream, we will convert it to a string. The string object will be pass as a parameter to an instance of JsonObject class.

We will also use an AsyncTask class to make server calls in a background Thread. This is important so that we will not end up blocking the main UI Thread.

Before we start, the first thing I will do is to list the environment and tools I used in this android tutorial but feel free to use whatever environment or tools you are familiar with.

Windows 7

Android Studio

Samsung Galaxy Fame Lite

Min SDK 14

Target SDK 19

To create a new android application project, following the steps as stipulated below.

Go to File menu

Click on New menu

Click on Android Application

Enter Project name: AndroidQuizApplication

Package: com.inducesmile.androidquizapplication

Keep other default selections.

Continue to click on next button until Finish button is active, then click on Finish Button

Once you are done with creating your project, make sure you change the package name if you did not use the same package.

Quiz Design

The first step here is to have a clear view about what we are planning to achieve. In this android quiz application, there will be an intro activity page with a button when a user clicks on the button view it will take the user to the quiz activity page where the user will start taking the quiz. A diagram that illustrate the quiz application is shown below.

quiz

Main Layout

We will start by adding background image to the root layout in our activity_main.xml layout file. The image I used can be found in the project source code below. You can use your own image be changing the above used image.

Add a Button View to the layout as shown in the image above. If you are using Eclipse or Android Studio, you can switch to the design view and drag and drop this View inside your layout file.

You can also copy and paste the following code below into this file if you don’t want to do it yourself.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@drawable/bg"

tools:context=".MainActivity">

<Button

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:id="@+id/button"

android:layout_alignParentBottom="true"

android:layout_alignParentRight="true"

android:layout_alignParentEnd="true"

android:layout_marginRight="32dp"

android:layout_marginEnd="32dp"

android:background="@drawable/mbutton"

android:layout_marginBottom="48dp" />

</RelativeLayout>

The text content of our View components are stored in the strings.xml file. The updated contain of the file is shown below

<resources>

<string name="app_name">Android Quiz Application</string>

<string name="hello_world">Hello world!</string>

<string name="action_settings">Settings</string>

<string name="title_activity_quiz">Quiz Questions</string>

<string name="question">Question 1. How is the first president of Nigeria?</string>

<string name="answer_one">King Ade</string>

<string name="answer_two"> olu Obasanjo</string>

<string name="answer_three">Jona Goodluck</string>

<string name="answer_four"> Atiku Abubakar</string>

<string name="next_questions"> Next Question</string>

<string name="previous_questions"> Previous Question</string>

</resources>

We will make use of few colors in this application so we have to update our color.xml file to include all these colours. This is important because it lets us have a single place where we can change and set colours for our project. The code is shown below.

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="black">#000000</color>
<color name="white">#ffffff</color>
</resources>

 MainActivity.java

In the MainActivity.java file, we will get the instance of our button View and attach and event listener to the button View. When the button is click, it will redirect to the QuizActivity page. The code for the MainActivity.java is shown below.

package inducesmile.com.androidquizapplication;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;

public class MainActivity extends ActionBarActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Button startButton = (Button)findViewById(R.id.button);

startButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Intent intent = new Intent(MainActivity.this, QuizActivity.class);

startActivity(intent);

}

});

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.

getMenuInflater().inflate(R.menu.menu_main, menu);

return true;

}

@Override

public boolean onOptionsItemSelected(MenuItem item) {

// Handle action bar item clicks here. The action bar will

// automatically handle clicks on the Home/Up button, so long

// as you specify a parent activity in AndroidManifest.xml.

int id = item.getItemId();

//noinspection SimplifiableIfStatement

if (id == R.id.action_settings) {

return true;

}

return super.onOptionsItemSelected(item);

}

}

 Quiz Page Layout

We will proceed to the activity_quiz.xml file to create our quiz interface. The quiz interface will contain the following View components

1. TextView – this is hold the quiz questions

2. RadioGroup – A wrapper for RadioButton Views

3. 4 RadioButtons – This will serve as answer options for the quiz.php

4. 2 Buttons – previous and next buttons will be used to change the quiz questions

The following is the code for the layout. You can copy and paste it in your own project.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="inducesmile.com.androidquizapplication.QuizActivity">

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/question"

android:id="@+id/quiz_question"

android:layout_alignParentTop="true"

android:layout_marginLeft="10dp"

android:layout_marginRight="10dp"

android:layout_marginEnd="10dp"

android:layout_marginStart="10dp"

android:layout_marginTop="20dp"

android:textSize="20sp"

android:textColor="#000000"

android:layout_alignParentLeft="true"

android:layout_alignParentStart="true" />

<RadioGroup

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_below="@+id/quiz_question"

android:layout_alignLeft="@+id/quiz_question"

android:layout_alignStart="@+id/quiz_question"

android:layout_marginTop="40dp"

android:id="@+id/radioGroup">

<RadioButton

android:layout_height="wrap_content"

android:layout_width="wrap_content"

android:id="@+id/radio0"

android:textSize="15sp"

android:textColor="#000000"

android:text="@string/app_name"

android:layout_marginBottom="10dp"

android:paddingLeft="20dp"

android:button="@drawable/radio_bg"/>

<RadioButton

android:layout_height="wrap_content"

android:layout_width="wrap_content"

android:id="@+id/radio1"

android:textSize="15sp"

android:textColor="@color/black"

android:text="@string/app_name"

android:layout_marginBottom="10dp"

android:paddingLeft="20dp"

android:button="@drawable/radio_bg"/>

<RadioButton

android:layout_height="wrap_content"

android:layout_width="wrap_content"

android:id="@+id/radio2"

android:textSize="15sp"

android:textColor="@color/black"

android:text="@string/app_name"

android:layout_marginBottom="10dp"

android:paddingLeft="20dp"

android:button="@drawable/radio_bg"/>

<RadioButton

android:layout_height="wrap_content"

android:layout_width="wrap_content"

android:id="@+id/radio3"

android:textSize="15sp"

android:textColor="@color/black"

android:text="@string/app_name"

android:paddingLeft="20dp"

android:button="@drawable/radio_bg"/>

</RadioGroup>

<Button

android:layout_height="wrap_content"

android:layout_width="160dp"

android:gravity="center"

android:id="@+id/nextquiz"

android:textColor="@color/white"

android:text="@string/next_questions"

android:background="@drawable/quizbutton"

android:layout_marginRight="10dp"

android:padding="5dp"

android:layout_alignParentRight="true"

android:layout_alignBaseline="@+id/previousquiz"/>

<Button

android:layout_height="wrap_content"

android:layout_width="160dp"

android:gravity="center"

android:id="@+id/previousquiz"

android:textColor="@color/white"

android:text="@string/previous_questions"

android:background="@drawable/quizbutton"

android:layout_below="@+id/radioGroup"

android:layout_alignLeft="@+id/radioGroup"

android:padding="5dp"

android:layout_marginTop="20dp"

android:layout_alignStart="@+id/radioGroup" />

</RelativeLayout>

We will finally look at the code for the QuizActivity class before we conclude this tutorial.

QuizActivity

The code in the class is huge so I will try as much as possible to explain what each block is doing. But like in MainActivity.java class, we are going to get all the instances of our View controls in QuizActivity.java.

We created an AsyncTask class as an inner class to our Activity class. The AsyncTask class is used to make request to the server since it has its own separate thread and each request call will be interfere with the main UI thread.

In the AsyncTask doInBackground method, the request to the server is sent and server response are passed as a parameter to the onPostExecute method of the class.

A progressbar is used to keep the app on hold until the questions are download from the server.

Once the quiz questions are download, the data is parsed using android built-in Json object and array parser classes. The return data are passed into a domain object each is then stored in a List.

The code of the domain class is shown below.

package inducesmile.com.androidquizapplication;

public class QuizWrapper {

private int id;

private String question;

private String answers;

private int correctAnswer;

public QuizWrapper(int id, String question, String answers, int correctAnswer) {

this.id = id;

this.question = question;

this.answers = answers;

this.correctAnswer = correctAnswer;

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getQuestion() {

return question;

}

public void setQuestion(String question) {

this.question = question;

}

public String getAnswers() {

return answers;

}

public void setAnswers(String answers) {

this.answers = answers;

}

public int getCorrectAnswer() {

return correctAnswer;

}

public void setCorrectAnswer(int correctAnswer) {

this.correctAnswer = correctAnswer;

}

}

The stored data are then set to the quiz questions using question number index. The code for the QuizActivity.java is shown below.

package inducesmile.com.androidquizapplication;

import android.app.ProgressDialog;

import android.content.pm.ActivityInfo;

import android.os.AsyncTask;

import android.os.Bundle;

import android.support.v7.app.ActionBarActivity;

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.widget.Button;

import android.widget.RadioButton;

import android.widget.RadioGroup;

import android.widget.TextView;

import android.widget.Toast;

import org.apache.http.HttpResponse;

import org.apache.http.client.ClientProtocolException;

import org.apache.http.client.HttpClient;

import org.apache.http.client.methods.HttpPost;

import org.apache.http.impl.client.DefaultHttpClient;

import org.apache.http.params.BasicHttpParams;

import org.json.JSONArray;

import org.json.JSONException;

import org.json.JSONObject;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.util.ArrayList;

import java.util.List;

public class QuizActivity extends ActionBarActivity {

private TextView quizQuestion;

private RadioGroup radioGroup;

private RadioButton optionOne;

private RadioButton optionTwo;

private RadioButton optionThree;

private RadioButton optionFour;

private int currentQuizQuestion;

private int quizCount;

private QuizWrapper firstQuestion;

private List<QuizWrapper> parsedObject;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_quiz);

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

quizQuestion = (TextView)findViewById(R.id.quiz_question);

radioGroup = (RadioGroup)findViewById(R.id.radioGroup);

optionOne = (RadioButton)findViewById(R.id.radio0);

optionTwo = (RadioButton)findViewById(R.id.radio1);

optionThree = (RadioButton)findViewById(R.id.radio2);

optionFour = (RadioButton)findViewById(R.id.radio3);

Button previousButton = (Button)findViewById(R.id.previousquiz);

Button nextButton = (Button)findViewById(R.id.nextquiz);

AsyncJsonObject asyncObject = new AsyncJsonObject();

asyncObject.execute("");

nextButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

int radioSelected = radioGroup.getCheckedRadioButtonId();

int userSelection = getSelectedAnswer(radioSelected);

int correctAnswerForQuestion = firstQuestion.getCorrectAnswer();

if(userSelection == correctAnswerForQuestion){

// correct answer

Toast.makeText(QuizActivity.this, "You got the answer correct", Toast.LENGTH_LONG).show();

currentQuizQuestion++;

if(currentQuizQuestion >= quizCount){

Toast.makeText(QuizActivity.this, "End of the Quiz Questions", Toast.LENGTH_LONG).show();

return;

}

else{

firstQuestion = parsedObject.get(currentQuizQuestion);

quizQuestion.setText(firstQuestion.getQuestion());

String[] possibleAnswers = firstQuestion.getAnswers().split(",");

uncheckedRadioButton();

optionOne.setText(possibleAnswers[0]);

optionTwo.setText(possibleAnswers[1]);

optionThree.setText(possibleAnswers[2]);

optionFour.setText(possibleAnswers[3]);

}

}

else{

// failed question

Toast.makeText(QuizActivity.this, "You chose the wrong answer", Toast.LENGTH_LONG).show();

return;

}

}

});

previousButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

currentQuizQuestion--;

if(currentQuizQuestion < 0){

return;

}

uncheckedRadioButton();

firstQuestion = parsedObject.get(currentQuizQuestion);

quizQuestion.setText(firstQuestion.getQuestion());

String[] possibleAnswers = firstQuestion.getAnswers().split(",");

optionOne.setText(possibleAnswers[0]);

optionTwo.setText(possibleAnswers[1]);

optionThree.setText(possibleAnswers[2]);

optionFour.setText(possibleAnswers[3]);

}

});

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.

getMenuInflater().inflate(R.menu.menu_quiz, menu);

return true;

}

@Override

public boolean onOptionsItemSelected(MenuItem item) {

// Handle action bar item clicks here. The action bar will

// automatically handle clicks on the Home/Up button, so long

// as you specify a parent activity in AndroidManifest.xml.

int id = item.getItemId();

//noinspection SimplifiableIfStatement

if (id == R.id.action_settings) {

return true;

}

return super.onOptionsItemSelected(item);

}

private class AsyncJsonObject extends AsyncTask<String, Void, String> {

private ProgressDialog progressDialog;

@Override

protected String doInBackground(String... params) {

HttpClient httpClient = new DefaultHttpClient(new BasicHttpParams());

HttpPost httpPost = new HttpPost("http://10.0.2.2/androidlogin/index.php");

String jsonResult = "";

try {

HttpResponse response = httpClient.execute(httpPost);

jsonResult = inputStreamToString(response.getEntity().getContent()).toString();

System.out.println("Returned Json object " + jsonResult.toString());

} catch (ClientProtocolException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return jsonResult;

}

@Override

protected void onPreExecute() {

// TODO Auto-generated method stub

super.onPreExecute();

progressDialog = ProgressDialog.show(QuizActivity.this, "Downloading Quiz","Wait....", true);

}

@Override

protected void onPostExecute(String result) {

super.onPostExecute(result);

progressDialog.dismiss();

System.out.println("Resulted Value: " + result);

parsedObject = returnParsedJsonObject(result);

if(parsedObject == null){

return;

}

quizCount = parsedObject.size();

firstQuestion = parsedObject.get(0);

quizQuestion.setText(firstQuestion.getQuestion());

String[] possibleAnswers = firstQuestion.getAnswers().split(",");

optionOne.setText(possibleAnswers[0]);

optionTwo.setText(possibleAnswers[1]);

optionThree.setText(possibleAnswers[2]);

optionFour.setText(possibleAnswers[3]);

}

private StringBuilder inputStreamToString(InputStream is) {

String rLine = "";

StringBuilder answer = new StringBuilder();

BufferedReader br = new BufferedReader(new InputStreamReader(is));

try {

while ((rLine = br.readLine()) != null) {

answer.append(rLine);

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return answer;

}

}

private List<QuizWrapper> returnParsedJsonObject(String result){

List<QuizWrapper> jsonObject = new ArrayList<QuizWrapper>();

JSONObject resultObject = null;

JSONArray jsonArray = null;

QuizWrapper newItemObject = null;

try {

resultObject = new JSONObject(result);

System.out.println("Testing the water " + resultObject.toString());

jsonArray = resultObject.optJSONArray("quiz_questions");

} catch (JSONException e) {

e.printStackTrace();

}

for(int i = 0; i < jsonArray.length(); i++){

JSONObject jsonChildNode = null;

try {

jsonChildNode = jsonArray.getJSONObject(i);

int id = jsonChildNode.getInt("id");

String question = jsonChildNode.getString("question");

String answerOptions = jsonChildNode.getString("possible_answers");

int correctAnswer = jsonChildNode.getInt("correct_answer");

newItemObject = new QuizWrapper(id, question, answerOptions, correctAnswer);

jsonObject.add(newItemObject);

} catch (JSONException e) {

e.printStackTrace();

}

}

return jsonObject;

}

private int getSelectedAnswer(int radioSelected){

int answerSelected = 0;

if(radioSelected == R.id.radio0){

answerSelected = 1;

}

if(radioSelected == R.id.radio1){

answerSelected = 2;

}

if(radioSelected == R.id.radio2){

answerSelected = 3;

}

if(radioSelected == R.id.radio3){

answerSelected = 4;

}

return answerSelected;

}

private void uncheckedRadioButton(){

optionOne.setChecked(false);

optionTwo.setChecked(false);

optionThree.setChecked(false);

optionFour.setChecked(false);

}

}

You can download the code for this tutorial below. If you are having hard time downloading the tutorials, kindly contact me.

Remember to subscribe with your email so that you will be among the first to receive our new post once it is published.

OTHER INTERESTING POSTS:

42 Comments

    • Henry
    • Henry
    • Henry
    • Henry
    • Henry
    • Henry
          • Henry
    • Henry
    • Henry
      • Henry

Add a Comment