52
loading...
This website collects cookies to deliver better user experience
build.gradle(.kts)
file, add the mavenCentral()
repository in order to fetch the Appwrite Android SDK.repositories {
mavenCentral()
}
build.gradle(.kts)
file:implementation("io.appwrite:sdk-for-android:0.0.1")
applicationId
in your app-level build.gradle
file. You may also find your package name in your AndroidManifest.xml
file. By registering a new platform, you are allowing your app to communicate with the Appwrite API.File>New>Activity>Empty Activity
and name it QuizActivity. This will create QuizActivity.kt
and activity_quiz.xml
files in their respective folders.app/src/main/res/layout/activity_main.xml
and update the layout as following<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/darkslategray"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:fontFamily="sans-serif-medium"
android:text="Demo Quiz With Android"
android:textColor="@color/darkgray"
android:textSize="24sp"
app:layout_constraintBottom_toTopOf="@+id/btnPlay"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btnPlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Play Now"
style="@style/buttonStyle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
app/src/main/java/com/example/demoquizwithandroid/MainActivity.kt
and update the onCreate
function like so:override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<Button>(R.id.btnPlay)
button.setOnClickListener {
val intent = Intent(this, QuizActivity::class.java)
startActivity(intent)
}
}
app/src/main/res/layout/activity_quiz.xml
and update the layout to the following:<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="24dp"
android:background="@color/darkslategray"
tools:context=".QuizActivity">
<TextView
android:id="@+id/questionNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Question 5/15"
android:textSize="32sp"
android:textStyle="bold"
android:textColor="@color/darkgray"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/dashedLine"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_marginTop="16dp"
android:src="@drawable/dashed_line"
app:layout_constraintTop_toBottomOf="@id/questionNumber"
android:layerType="software" />
<TextView
android:id="@+id/question"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="16dp"
android:text="Question"
android:textColor="@color/white"
android:textSize="26sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/options"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/dashedLine" />
<RadioGroup
android:id="@+id/options"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
app:layout_constraintBottom_toTopOf="@+id/btnNext"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<RadioButton
android:id="@+id/option1"
style="@style/optionRadioButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Option 1"
tools:layout_editor_absoluteX="116dp"
tools:layout_editor_absoluteY="75dp" />
<RadioButton
android:id="@+id/option2"
style="@style/optionRadioButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Option 2" />
<RadioButton
android:id="@+id/option3"
style="@style/optionRadioButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Option 3" />
<RadioButton
android:id="@+id/option4"
style="@style/optionRadioButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Option 4" />
</RadioGroup>
<Button
android:id="@+id/btnNext"
style="@style/buttonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="Next"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
app/src/main/java/com/example/demoquizwithandroid/QuizViewModel.kt
and update it with following code. Make sure to replace YOUR_APPWRITE_ENDPOINT
, YOUR_PROJECT_ID
and YOUR_QUESTIONS_COLLECTION_ID
with your values which can all be found in your Appwrite console.import android.content.Context
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import io.appwrite.Client
import io.appwrite.exceptions.AppwriteException
import io.appwrite.services.Database
import kotlinx.coroutines.launch
import org.json.JSONArray
import org.json.JSONObject
class QuizViewModel : ViewModel() {
private val collectionId = "YOUR_QUESTIONS_COLLECTION_ID" // Replace with your own questions collection id that we created above
private val db by lazy {
Database(client)
}
private val _questions = MutableLiveData<JSONArray>().apply { value = null }
lateinit var client : Client
val questions: LiveData<JSONArray> = _questions;
val selectedQuestion = MutableLiveData<Int>().apply { value = 0}
val correct = MutableLiveData<Int>().apply { value = 0 }
fun create(context: Context) {
client = Client(context)
.setEndpoint("YOUR_APPWRITE_ENDPOINT") // Replace with your own endpoint
.setProject("YOUR_PROJECT_ID") // Replace with your project id
getQuestions()
}
private fun getQuestions() {
viewModelScope.launch {
try {
var response = db.listDocuments(collectionId)
val json = response.body?.string() ?: ""
var que = JSONObject(json)
_questions.postValue( que["documents"] as JSONArray)
} catch(e : AppwriteException) {
Log.e("Get questions",e.message.toString())
}
}
}
}
app/build.gradle
file. These are the dependencies required for LiveData
and ViewModel
to work.dependencies{
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
}
app/src/main/java/com/example/demoquizwithandroid/QuizActivity.kt
with the following code and build your applicationclass QuizActivity : AppCompatActivity() {
private lateinit var viewModel: QuizViewModel
private var currentQuestion : JSONObject? = null;
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_quiz)
viewModel = ViewModelProvider(this).get(QuizViewModel::class.java)
viewModel.create(this)
viewModel.questions.observe(this, {
questions ->
if(questions != null) {
viewModel.selectedQuestion.observe(this, { index ->
findViewById<TextView>(R.id.questionNumber).text = "Question ${(index+1)}/${questions.length()}"
currentQuestion = questions[index] as JSONObject
val options = currentQuestion!!["options"] as JSONArray
findViewById<TextView>(R.id.question).text = currentQuestion!!["question"].toString()
findViewById<RadioButton>(R.id.option1).text = options[0].toString()
findViewById<RadioButton>(R.id.option2).text = options[1].toString()
val option3= findViewById<RadioButton>(R.id.option3)
val option4=findViewById<RadioButton>(R.id.option4)
if(options.length() > 2) {
option4.text = options[3].toString()
option3.text = options[2].toString()
option3.visibility = View.VISIBLE
option4.visibility = View.VISIBLE
} else {
option3.visibility = View.GONE
option4.visibility = View.GONE
}
})
}
})
findViewById<Button>(R.id.btnNext).setOnClickListener {
_ -> onNextClicked()
}
}
private fun onNextClicked() {
if(currentQuestion == null) return
val rbGroup : RadioGroup = findViewById<RadioGroup>(R.id.options)
val rbSelected : RadioButton = findViewById(rbGroup.checkedRadioButtonId) ?: return
val ans: String = rbSelected.text.toString();
if (ans == currentQuestion!!["answer"].toString()) {
viewModel.correct.postValue(viewModel.correct.value?.inc())
}
rbGroup.clearCheck()
if(viewModel.selectedQuestion.value!! >= (viewModel.questions.value!!.length() - 1)) {
//show complete dialog
Log.d("Quiz complete","Quiz complete")
val alertDialog = AlertDialog.Builder(this)
.setTitle("Quiz complete")
.setMessage("Score: ${viewModel.correct.value!!} / ${viewModel.questions.value!!.length()}")
.setNeutralButton("Done", DialogInterface.OnClickListener { _, _ ->
val intent = Intent(this, MainActivity::class.java)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
})
alertDialog.show()
} else {
viewModel.selectedQuestion.postValue(viewModel.selectedQuestion.value?.inc())
}
}
}