├── .gitignore ├── .idea ├── .gitignore ├── .name ├── compiler.xml ├── gradle.xml ├── jarRepositories.xml ├── misc.xml └── runConfigurations.xml ├── app ├── .gitignore ├── build.gradle ├── google-services.json ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── codingstuff │ │ └── quizzyapp │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── codingstuff │ │ │ └── quizzyapp │ │ │ ├── Adapter │ │ │ └── QuizListAdapter.java │ │ │ ├── MainActivity.java │ │ │ ├── Model │ │ │ ├── QuestionModel.java │ │ │ ├── QuizListModel.java │ │ │ └── ResultModel.java │ │ │ ├── repository │ │ │ ├── AuthRepository.java │ │ │ ├── QuestionRepository.java │ │ │ └── QuizListRepository.java │ │ │ ├── viewmodel │ │ │ ├── AuthViewModel.java │ │ │ ├── QuestionViewModel.java │ │ │ └── QuizListViewModel.java │ │ │ └── views │ │ │ ├── DetailFragment.java │ │ │ ├── ListFragment.java │ │ │ ├── Quizragment.java │ │ │ ├── ResultFragment.java │ │ │ ├── SignInFragment.java │ │ │ ├── SignUpFragment.java │ │ │ └── SplashFragment.java │ └── res │ │ ├── drawable-v24 │ │ ├── circular_progressbar.xml │ │ ├── ic_launcher_foreground.xml │ │ ├── splash.png │ │ └── studying.png │ │ ├── drawable │ │ ├── button_bg.xml │ │ ├── edit_bg.xml │ │ ├── ic_baseline_close_24.xml │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── each_quiz.xml │ │ ├── fragment_detail.xml │ │ ├── fragment_list.xml │ │ ├── fragment_quiz.xml │ │ ├── fragment_result.xml │ │ ├── fragment_sign_in.xml │ │ ├── fragment_sign_up.xml │ │ └── fragment_splash.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── navigation │ │ └── nav_graph.xml │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ └── test │ └── java │ └── com │ └── codingstuff │ └── quizzyapp │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | QuizzyApp -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'com.google.gms.google-services' 4 | } 5 | 6 | android { 7 | compileSdkVersion 30 8 | buildToolsVersion "30.0.3" 9 | 10 | defaultConfig { 11 | applicationId "com.codingstuff.quizzyapp" 12 | minSdkVersion 23 13 | targetSdkVersion 30 14 | versionCode 1 15 | versionName "1.0" 16 | 17 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 18 | } 19 | 20 | buildTypes { 21 | release { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 24 | } 25 | } 26 | compileOptions { 27 | sourceCompatibility JavaVersion.VERSION_1_8 28 | targetCompatibility JavaVersion.VERSION_1_8 29 | } 30 | } 31 | 32 | dependencies { 33 | 34 | implementation 'androidx.appcompat:appcompat:1.3.1' 35 | implementation 'com.google.android.material:material:1.4.0' 36 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4' 37 | implementation 'com.google.firebase:firebase-firestore:23.0.3' 38 | implementation 'com.google.firebase:firebase-auth:21.0.1' 39 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 40 | testImplementation 'junit:junit:4.+' 41 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 42 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 43 | 44 | 45 | implementation 'androidx.navigation:navigation-ui:2.3.5' 46 | implementation 'androidx.navigation:navigation-fragment:2.3.5' 47 | 48 | implementation 'com.github.bumptech.glide:glide:4.12.0' 49 | annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' 50 | 51 | apply plugin: "androidx.navigation.safeargs" 52 | } -------------------------------------------------------------------------------- /app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "552399443180", 4 | "project_id": "quizzyapp-36122", 5 | "storage_bucket": "quizzyapp-36122.appspot.com" 6 | }, 7 | "client": [ 8 | { 9 | "client_info": { 10 | "mobilesdk_app_id": "1:552399443180:android:9f84c1bfac3ae9178f01c9", 11 | "android_client_info": { 12 | "package_name": "com.codingstuff.quizzyapp" 13 | } 14 | }, 15 | "oauth_client": [ 16 | { 17 | "client_id": "552399443180-0sdhj47med4fn0ft13qbcj0f4fipkreg.apps.googleusercontent.com", 18 | "client_type": 3 19 | } 20 | ], 21 | "api_key": [ 22 | { 23 | "current_key": "AIzaSyD9SW8jJHMTEkkcVXLIsesKlvBKjk3RA7A" 24 | } 25 | ], 26 | "services": { 27 | "appinvite_service": { 28 | "other_platform_oauth_client": [ 29 | { 30 | "client_id": "552399443180-0sdhj47med4fn0ft13qbcj0f4fipkreg.apps.googleusercontent.com", 31 | "client_type": 3 32 | } 33 | ] 34 | } 35 | } 36 | } 37 | ], 38 | "configuration_version": "1" 39 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/codingstuff/quizzyapp/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("com.codingstuff.quizzyapp", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/Adapter/QuizListAdapter.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.Adapter; 2 | 3 | import android.view.LayoutInflater; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.ImageView; 7 | import android.widget.TextView; 8 | 9 | import androidx.annotation.NonNull; 10 | import androidx.constraintlayout.widget.ConstraintLayout; 11 | import androidx.recyclerview.widget.RecyclerView; 12 | 13 | import com.bumptech.glide.Glide; 14 | import com.codingstuff.quizzyapp.Model.QuizListModel; 15 | import com.codingstuff.quizzyapp.R; 16 | 17 | import java.util.List; 18 | 19 | public class QuizListAdapter extends RecyclerView.Adapter { 20 | 21 | private List quizListModels; 22 | private OnItemClickedListner onItemClickedListner; 23 | 24 | public void setQuizListModels(List quizListModels) { 25 | this.quizListModels = quizListModels; 26 | } 27 | 28 | public QuizListAdapter(OnItemClickedListner onItemClickedListner){ 29 | this.onItemClickedListner = onItemClickedListner; 30 | } 31 | @NonNull 32 | @Override 33 | public QuizListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 34 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.each_quiz , parent , false); 35 | return new QuizListViewHolder(view); 36 | } 37 | 38 | @Override 39 | public void onBindViewHolder(@NonNull QuizListAdapter.QuizListViewHolder holder, int position) { 40 | QuizListModel model = quizListModels.get(position); 41 | holder.title.setText(model.getTitle()); 42 | Glide.with(holder.itemView).load(model.getImage()).into(holder.quizImage); 43 | } 44 | 45 | @Override 46 | public int getItemCount() { 47 | 48 | if (quizListModels == null){ 49 | return 0; 50 | }else{ 51 | return quizListModels.size(); 52 | } 53 | 54 | } 55 | 56 | public class QuizListViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 57 | private TextView title ; 58 | private ImageView quizImage; 59 | private ConstraintLayout constraintLayout; 60 | 61 | public QuizListViewHolder(@NonNull View itemView) { 62 | super(itemView); 63 | 64 | title = itemView.findViewById(R.id.quizTitleList); 65 | quizImage = itemView.findViewById(R.id.quizImageList); 66 | constraintLayout = itemView.findViewById(R.id.constraintLayout); 67 | constraintLayout.setOnClickListener(this); 68 | } 69 | 70 | @Override 71 | public void onClick(View v) { 72 | onItemClickedListner.onItemClick(getAdapterPosition()); 73 | } 74 | } 75 | 76 | public interface OnItemClickedListner { 77 | void onItemClick(int position); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | 6 | public class MainActivity extends AppCompatActivity { 7 | 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | setContentView(R.layout.activity_main); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/Model/QuestionModel.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.Model; 2 | 3 | import com.google.firebase.firestore.DocumentId; 4 | 5 | public class QuestionModel { 6 | 7 | @DocumentId 8 | private String questionId; 9 | private String answer , question , option_a , option_b , option_c; 10 | private long timer; 11 | 12 | public QuestionModel(){} 13 | 14 | public String getQuestionId() { 15 | return questionId; 16 | } 17 | 18 | public void setQuestionId(String questionId) { 19 | this.questionId = questionId; 20 | } 21 | 22 | public String getAnswer() { 23 | return answer; 24 | } 25 | 26 | public void setAnswer(String answer) { 27 | this.answer = answer; 28 | } 29 | 30 | public String getQuestion() { 31 | return question; 32 | } 33 | 34 | public void setQuestion(String question) { 35 | this.question = question; 36 | } 37 | 38 | public String getOption_a() { 39 | return option_a; 40 | } 41 | 42 | public void setOption_a(String option_a) { 43 | this.option_a = option_a; 44 | } 45 | 46 | public String getOption_b() { 47 | return option_b; 48 | } 49 | 50 | public void setOption_b(String option_b) { 51 | this.option_b = option_b; 52 | } 53 | 54 | public String getOption_c() { 55 | return option_c; 56 | } 57 | 58 | public void setOption_c(String option_c) { 59 | this.option_c = option_c; 60 | } 61 | 62 | public long getTimer() { 63 | return timer; 64 | } 65 | 66 | public void setTimer(long timer) { 67 | this.timer = timer; 68 | } 69 | 70 | public QuestionModel(String questionId, String answer, String question, String option_a, String option_b, String option_c, long timer) { 71 | this.questionId = questionId; 72 | this.answer = answer; 73 | this.question = question; 74 | this.option_a = option_a; 75 | this.option_b = option_b; 76 | this.option_c = option_c; 77 | this.timer = timer; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/Model/QuizListModel.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.Model; 2 | 3 | import com.google.firebase.firestore.DocumentId; 4 | 5 | public class QuizListModel { 6 | 7 | @DocumentId 8 | private String quizId; 9 | private String title,image, difficulty; 10 | private long questions; 11 | 12 | public String getQuizId() { 13 | return quizId; 14 | } 15 | 16 | public void setQuizId(String quizId) { 17 | this.quizId = quizId; 18 | } 19 | 20 | public String getTitle() { 21 | return title; 22 | } 23 | 24 | public void setTitle(String title) { 25 | this.title = title; 26 | } 27 | 28 | public String getImage() { 29 | return image; 30 | } 31 | 32 | public void setImage(String image) { 33 | this.image = image; 34 | } 35 | 36 | public String getDifficulty() { 37 | return difficulty; 38 | } 39 | 40 | public void setDifficulty(String difficulty) { 41 | this.difficulty = difficulty; 42 | } 43 | 44 | public long getQuestions() { 45 | return questions; 46 | } 47 | 48 | public void setQuestions(long questions) { 49 | this.questions = questions; 50 | } 51 | 52 | public QuizListModel(){} 53 | public QuizListModel(String quizId, String title, String image, String difficulty, long questions) { 54 | this.quizId = quizId; 55 | this.title = title; 56 | this.image = image; 57 | this.difficulty = difficulty; 58 | this.questions = questions; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/Model/ResultModel.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.Model; 2 | 3 | import com.codingstuff.quizzyapp.views.ResultFragment; 4 | 5 | public class ResultModel { 6 | 7 | private int correct ,wrong, notAnswered; 8 | 9 | public ResultModel(){} 10 | 11 | public int getWrong() { 12 | return wrong; 13 | } 14 | 15 | public int getCorrect() { 16 | return correct; 17 | } 18 | 19 | public int getNotAnswered() { 20 | return notAnswered; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/repository/AuthRepository.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.repository; 2 | 3 | import android.app.Application; 4 | import android.widget.Toast; 5 | 6 | import androidx.annotation.NonNull; 7 | import androidx.lifecycle.MutableLiveData; 8 | 9 | import com.google.android.gms.tasks.OnCompleteListener; 10 | import com.google.android.gms.tasks.Task; 11 | import com.google.firebase.auth.AuthResult; 12 | import com.google.firebase.auth.FirebaseAuth; 13 | import com.google.firebase.auth.FirebaseUser; 14 | 15 | public class AuthRepository { 16 | 17 | private Application application; 18 | private MutableLiveData firebaseUserMutableLiveData; 19 | private FirebaseAuth firebaseAuth; 20 | 21 | public MutableLiveData getFirebaseUserMutableLiveData() { 22 | return firebaseUserMutableLiveData; 23 | } 24 | 25 | public FirebaseUser getCurrentUser() { 26 | return firebaseAuth.getCurrentUser(); 27 | } 28 | 29 | public AuthRepository(Application application){ 30 | this.application = application; 31 | firebaseUserMutableLiveData = new MutableLiveData<>(); 32 | firebaseAuth = FirebaseAuth.getInstance(); 33 | } 34 | 35 | public void signUp(String email , String pass){ 36 | firebaseAuth.createUserWithEmailAndPassword(email, pass).addOnCompleteListener(new OnCompleteListener() { 37 | @Override 38 | public void onComplete(@NonNull Task task) { 39 | if (task.isSuccessful()){ 40 | firebaseUserMutableLiveData.postValue(firebaseAuth.getCurrentUser()); 41 | }else{ 42 | Toast.makeText(application, task.getException().getMessage() , Toast.LENGTH_SHORT).show(); 43 | } 44 | } 45 | }); 46 | } 47 | 48 | public void signIn(String email , String pass){ 49 | firebaseAuth.signInWithEmailAndPassword(email, pass).addOnCompleteListener(new OnCompleteListener() { 50 | @Override 51 | public void onComplete(@NonNull Task task) { 52 | if (task.isSuccessful()){ 53 | firebaseUserMutableLiveData.postValue(firebaseAuth.getCurrentUser()); 54 | }else{ 55 | Toast.makeText(application, task.getException().getMessage() , Toast.LENGTH_SHORT).show(); 56 | } 57 | } 58 | }); 59 | } 60 | public void signOut(){ 61 | firebaseAuth.signOut(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/repository/QuestionRepository.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.repository; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.lifecycle.MutableLiveData; 5 | 6 | import com.codingstuff.quizzyapp.Model.QuestionModel; 7 | import com.codingstuff.quizzyapp.Model.ResultModel; 8 | import com.google.android.gms.tasks.OnCompleteListener; 9 | import com.google.android.gms.tasks.Task; 10 | import com.google.firebase.auth.FirebaseAuth; 11 | import com.google.firebase.firestore.DocumentSnapshot; 12 | import com.google.firebase.firestore.FirebaseFirestore; 13 | import com.google.firebase.firestore.ListenerRegistration; 14 | import com.google.firebase.firestore.QuerySnapshot; 15 | 16 | import java.util.ArrayList; 17 | import java.util.HashMap; 18 | import java.util.List; 19 | 20 | public class QuestionRepository { 21 | 22 | private FirebaseFirestore firebaseFirestore; 23 | private String quizId; 24 | private HashMap resultMap= new HashMap<>(); 25 | private OnQuestionLoad onQuestionLoad; 26 | private OnResultAdded onResultAdded; 27 | private String currentUserId = FirebaseAuth.getInstance().getCurrentUser().getUid(); 28 | private OnResultLoad onResultLoad; 29 | 30 | 31 | public void getResults(){ 32 | firebaseFirestore.collection("Quiz").document(quizId) 33 | .collection("results").document(currentUserId) 34 | .get().addOnCompleteListener(new OnCompleteListener() { 35 | @Override 36 | public void onComplete(@NonNull Task task) { 37 | if (task.isSuccessful()){ 38 | resultMap.put("correct" , task.getResult().getLong("correct")); 39 | resultMap.put("wrong" , task.getResult().getLong("wrong")); 40 | resultMap.put("notAnswered" , task.getResult().getLong("notAnswered")); 41 | onResultLoad.onResultLoad(resultMap); 42 | }else{ 43 | onResultLoad.onError(task.getException()); 44 | } 45 | } 46 | }); 47 | } 48 | 49 | public void addResults(HashMap resultMap){ 50 | firebaseFirestore.collection("Quiz").document(quizId) 51 | .collection("results").document(currentUserId) 52 | .set(resultMap).addOnCompleteListener(new OnCompleteListener() { 53 | @Override 54 | public void onComplete(@NonNull Task task) { 55 | if (task.isSuccessful()){ 56 | onResultAdded.onSubmit(); 57 | }else{ 58 | onResultAdded.onError(task.getException()); 59 | } 60 | } 61 | }); 62 | } 63 | 64 | public void setQuizId(String quizId) { 65 | this.quizId = quizId; 66 | } 67 | 68 | public QuestionRepository(OnQuestionLoad onQuestionLoad , OnResultAdded onResultAdded , OnResultLoad onResultLoad){ 69 | firebaseFirestore = FirebaseFirestore.getInstance(); 70 | this.onQuestionLoad = onQuestionLoad; 71 | this.onResultAdded = onResultAdded; 72 | this.onResultLoad = onResultLoad; 73 | 74 | } 75 | 76 | public void getQuestions(){ 77 | firebaseFirestore.collection("Quiz").document(quizId) 78 | .collection("questions").get().addOnCompleteListener(new OnCompleteListener() { 79 | @Override 80 | public void onComplete(@NonNull Task task) { 81 | if (task.isSuccessful()){ 82 | onQuestionLoad.onLoad(task.getResult().toObjects(QuestionModel.class)); 83 | }else{ 84 | onQuestionLoad.onError(task.getException()); 85 | } 86 | } 87 | }); 88 | } 89 | 90 | public interface OnResultLoad{ 91 | void onResultLoad(HashMap resultMap); 92 | void onError(Exception e); 93 | } 94 | 95 | public interface OnQuestionLoad{ 96 | void onLoad(List questionModels); 97 | void onError(Exception e); 98 | } 99 | public interface OnResultAdded{ 100 | boolean onSubmit(); 101 | void onError(Exception e); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/repository/QuizListRepository.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.repository; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import com.codingstuff.quizzyapp.Model.QuizListModel; 6 | import com.google.android.gms.tasks.OnCompleteListener; 7 | import com.google.android.gms.tasks.Task; 8 | import com.google.firebase.firestore.CollectionReference; 9 | import com.google.firebase.firestore.FirebaseFirestore; 10 | import com.google.firebase.firestore.QuerySnapshot; 11 | 12 | import java.util.List; 13 | 14 | public class QuizListRepository { 15 | 16 | private onFirestoreTaskComplete onFirestoreTaskComplete; 17 | private FirebaseFirestore firebaseFirestore = FirebaseFirestore.getInstance(); 18 | private CollectionReference reference = firebaseFirestore.collection("Quiz"); 19 | 20 | public QuizListRepository(onFirestoreTaskComplete onFirestoreTaskComplete){ 21 | this.onFirestoreTaskComplete = onFirestoreTaskComplete; 22 | } 23 | public void getQuizData(){ 24 | reference.get().addOnCompleteListener(new OnCompleteListener() { 25 | @Override 26 | public void onComplete(@NonNull Task task) { 27 | if (task.isSuccessful()){ 28 | onFirestoreTaskComplete.quizDataLoaded(task.getResult() 29 | .toObjects(QuizListModel.class)); 30 | }else{ 31 | onFirestoreTaskComplete.onError(task.getException()); 32 | } 33 | } 34 | }); 35 | } 36 | 37 | public interface onFirestoreTaskComplete{ 38 | void quizDataLoaded(List quizListModels); 39 | void onError(Exception e); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/viewmodel/AuthViewModel.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.viewmodel; 2 | 3 | import android.app.Application; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.lifecycle.AndroidViewModel; 7 | import androidx.lifecycle.MutableLiveData; 8 | 9 | import com.codingstuff.quizzyapp.repository.AuthRepository; 10 | import com.google.firebase.auth.FirebaseUser; 11 | 12 | public class AuthViewModel extends AndroidViewModel { 13 | 14 | private MutableLiveData firebaseUserMutableLiveData; 15 | private FirebaseUser currentUser; 16 | private AuthRepository repository; 17 | 18 | public MutableLiveData getFirebaseUserMutableLiveData() { 19 | return firebaseUserMutableLiveData; 20 | } 21 | 22 | public FirebaseUser getCurrentUser() { 23 | return currentUser; 24 | } 25 | 26 | public AuthViewModel(@NonNull Application application) { 27 | super(application); 28 | 29 | repository = new AuthRepository(application); 30 | currentUser = repository.getCurrentUser(); 31 | firebaseUserMutableLiveData = repository.getFirebaseUserMutableLiveData(); 32 | } 33 | 34 | public void signUp(String email , String pass){ 35 | repository.signUp(email, pass); 36 | } 37 | public void signIn(String email, String pass){ 38 | repository.signIn(email, pass); 39 | } 40 | public void signOut(){ 41 | repository.signOut(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/viewmodel/QuestionViewModel.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.viewmodel; 2 | 3 | import android.util.Log; 4 | 5 | import androidx.lifecycle.MutableLiveData; 6 | import androidx.lifecycle.ViewModel; 7 | 8 | import com.codingstuff.quizzyapp.Model.QuestionModel; 9 | import com.codingstuff.quizzyapp.Model.ResultModel; 10 | import com.codingstuff.quizzyapp.repository.QuestionRepository; 11 | 12 | import java.util.ArrayList; 13 | import java.util.HashMap; 14 | import java.util.List; 15 | 16 | public class QuestionViewModel extends ViewModel implements QuestionRepository.OnQuestionLoad, QuestionRepository.OnResultAdded, QuestionRepository.OnResultLoad { 17 | 18 | private MutableLiveData> questionMutableLiveData; 19 | private QuestionRepository repository; 20 | private MutableLiveData> resultMutableLiveData; 21 | 22 | public MutableLiveData> getResultMutableLiveData() { 23 | return resultMutableLiveData; 24 | } 25 | 26 | public void getResults(){ 27 | repository.getResults(); 28 | } 29 | 30 | public MutableLiveData> getQuestionMutableLiveData() { 31 | return questionMutableLiveData; 32 | } 33 | 34 | public QuestionViewModel(){ 35 | questionMutableLiveData = new MutableLiveData<>(); 36 | resultMutableLiveData = new MutableLiveData<>(); 37 | repository = new QuestionRepository(this , this , this); 38 | } 39 | public void addResults(HashMap resultMap){ 40 | repository.addResults(resultMap); 41 | } 42 | 43 | public void setQuizId(String quizId){ 44 | repository.setQuizId(quizId); 45 | } 46 | 47 | public void getQuestions(){ 48 | repository.getQuestions(); 49 | } 50 | 51 | @Override 52 | public void onLoad(List questionModels) { 53 | questionMutableLiveData.setValue(questionModels); 54 | } 55 | 56 | @Override 57 | public boolean onSubmit() { 58 | return true; 59 | } 60 | 61 | 62 | @Override 63 | public void onResultLoad(HashMap resultMap) { 64 | resultMutableLiveData.setValue(resultMap); 65 | } 66 | 67 | @Override 68 | public void onError(Exception e) { 69 | Log.d("QuizError", "onError: " + e.getMessage()); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/viewmodel/QuizListViewModel.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.viewmodel; 2 | 3 | import android.util.Log; 4 | 5 | import androidx.lifecycle.MutableLiveData; 6 | import androidx.lifecycle.ViewModel; 7 | 8 | import com.codingstuff.quizzyapp.Model.QuizListModel; 9 | import com.codingstuff.quizzyapp.repository.QuizListRepository; 10 | 11 | import java.util.List; 12 | 13 | public class QuizListViewModel extends ViewModel implements QuizListRepository.onFirestoreTaskComplete { 14 | 15 | private MutableLiveData> quizListLiveData = new MutableLiveData<>(); 16 | 17 | private QuizListRepository repository = new QuizListRepository(this); 18 | 19 | public MutableLiveData> getQuizListLiveData() { 20 | return quizListLiveData; 21 | } 22 | 23 | public QuizListViewModel(){ 24 | repository.getQuizData(); 25 | } 26 | @Override 27 | public void quizDataLoaded(List quizListModels) { 28 | quizListLiveData.setValue(quizListModels); 29 | } 30 | 31 | @Override 32 | public void onError(Exception e) { 33 | Log.d("QuizERROR", "onError: " + e.getMessage()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/views/DetailFragment.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.views; 2 | 3 | import android.media.Image; 4 | import android.os.Bundle; 5 | 6 | import androidx.annotation.NonNull; 7 | import androidx.annotation.Nullable; 8 | import androidx.fragment.app.Fragment; 9 | import androidx.lifecycle.Observer; 10 | import androidx.lifecycle.ViewModel; 11 | import androidx.lifecycle.ViewModelProvider; 12 | import androidx.navigation.NavController; 13 | import androidx.navigation.Navigation; 14 | 15 | import android.os.Handler; 16 | import android.view.LayoutInflater; 17 | import android.view.View; 18 | import android.view.ViewGroup; 19 | import android.widget.Button; 20 | import android.widget.ImageView; 21 | import android.widget.ProgressBar; 22 | import android.widget.TextView; 23 | 24 | import com.bumptech.glide.Glide; 25 | import com.codingstuff.quizzyapp.Model.QuizListModel; 26 | import com.codingstuff.quizzyapp.R; 27 | import com.codingstuff.quizzyapp.viewmodel.QuizListViewModel; 28 | 29 | import java.util.List; 30 | 31 | public class DetailFragment extends Fragment { 32 | 33 | private TextView title , difficulty , totalQuestions; 34 | private Button startQuizBtn; 35 | private NavController navController; 36 | private int position; 37 | private ProgressBar progressBar; 38 | private QuizListViewModel viewModel; 39 | private ImageView topicImage; 40 | private String quizId; 41 | private long totalQueCount; 42 | 43 | 44 | @Override 45 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 46 | Bundle savedInstanceState) { 47 | // Inflate the layout for this fragment 48 | return inflater.inflate(R.layout.fragment_detail, container, false); 49 | } 50 | 51 | @Override 52 | public void onCreate(@Nullable Bundle savedInstanceState) { 53 | super.onCreate(savedInstanceState); 54 | viewModel = new ViewModelProvider(this , ViewModelProvider.AndroidViewModelFactory 55 | .getInstance(getActivity().getApplication())).get(QuizListViewModel.class); 56 | } 57 | 58 | @Override 59 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 60 | super.onViewCreated(view, savedInstanceState); 61 | 62 | title = view.findViewById(R.id.detailFragmentTitle); 63 | difficulty = view.findViewById(R.id.detailFragmentDifficulty); 64 | totalQuestions = view.findViewById(R.id.detailFragmentQuestions); 65 | startQuizBtn = view.findViewById(R.id.startQuizBtn); 66 | progressBar = view.findViewById(R.id.detailProgressBar); 67 | topicImage =view.findViewById(R.id.detailFragmentImage); 68 | navController = Navigation.findNavController(view); 69 | 70 | position = DetailFragmentArgs.fromBundle(getArguments()).getPosition(); 71 | 72 | viewModel.getQuizListLiveData().observe(getViewLifecycleOwner(), new Observer>() { 73 | @Override 74 | public void onChanged(List quizListModels) { 75 | QuizListModel quiz = quizListModels.get(position); 76 | difficulty.setText(quiz.getDifficulty()); 77 | title.setText(quiz.getTitle()); 78 | totalQuestions.setText(String.valueOf(quiz.getQuestions())); 79 | Glide.with(view).load(quiz.getImage()).into(topicImage); 80 | Handler handler = new Handler(); 81 | handler.postDelayed(new Runnable() { 82 | @Override 83 | public void run() { 84 | progressBar.setVisibility(View.GONE); 85 | } 86 | },2000); 87 | 88 | totalQueCount = quiz.getQuestions(); 89 | quizId = quiz.getQuizId(); 90 | } 91 | }); 92 | 93 | startQuizBtn.setOnClickListener(new View.OnClickListener() { 94 | @Override 95 | public void onClick(View v) { 96 | DetailFragmentDirections.ActionDetailFragmentToQuizragment action = 97 | DetailFragmentDirections.actionDetailFragmentToQuizragment(); 98 | 99 | action.setQuizId(quizId); 100 | action.setTotalQueCount(totalQueCount); 101 | navController.navigate(action); 102 | } 103 | }); 104 | } 105 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/views/ListFragment.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.views; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.annotation.Nullable; 7 | import androidx.fragment.app.Fragment; 8 | import androidx.lifecycle.Observer; 9 | import androidx.lifecycle.ViewModelProvider; 10 | import androidx.navigation.NavController; 11 | import androidx.navigation.Navigation; 12 | import androidx.recyclerview.widget.LinearLayoutManager; 13 | import androidx.recyclerview.widget.RecyclerView; 14 | 15 | import android.view.LayoutInflater; 16 | import android.view.View; 17 | import android.view.ViewGroup; 18 | import android.widget.ProgressBar; 19 | 20 | import com.codingstuff.quizzyapp.Adapter.QuizListAdapter; 21 | import com.codingstuff.quizzyapp.Model.QuizListModel; 22 | import com.codingstuff.quizzyapp.R; 23 | import com.codingstuff.quizzyapp.viewmodel.AuthViewModel; 24 | import com.codingstuff.quizzyapp.viewmodel.QuizListViewModel; 25 | 26 | import java.util.List; 27 | 28 | 29 | public class ListFragment extends Fragment implements QuizListAdapter.OnItemClickedListner { 30 | 31 | private RecyclerView recyclerView; 32 | private ProgressBar progressBar; 33 | private NavController navController; 34 | private QuizListViewModel viewModel; 35 | private QuizListAdapter adapter; 36 | 37 | @Override 38 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 39 | Bundle savedInstanceState) { 40 | // Inflate the layout for this fragment 41 | return inflater.inflate(R.layout.fragment_list, container, false); 42 | } 43 | 44 | @Override 45 | public void onCreate(@Nullable Bundle savedInstanceState) { 46 | super.onCreate(savedInstanceState); 47 | 48 | viewModel = new ViewModelProvider(this , ViewModelProvider.AndroidViewModelFactory 49 | .getInstance(getActivity().getApplication())).get(QuizListViewModel.class); 50 | } 51 | 52 | @Override 53 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 54 | super.onViewCreated(view, savedInstanceState); 55 | 56 | recyclerView = view.findViewById(R.id.listQuizRecyclerview); 57 | progressBar = view.findViewById(R.id.quizListProgressbar); 58 | navController = Navigation.findNavController(view); 59 | 60 | recyclerView.setHasFixedSize(true); 61 | recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); 62 | adapter = new QuizListAdapter(this); 63 | 64 | recyclerView.setAdapter(adapter); 65 | 66 | viewModel.getQuizListLiveData().observe(getViewLifecycleOwner(), new Observer>() { 67 | @Override 68 | public void onChanged(List quizListModels) { 69 | progressBar.setVisibility(View.GONE); 70 | adapter.setQuizListModels(quizListModels); 71 | adapter.notifyDataSetChanged(); 72 | } 73 | }); 74 | 75 | } 76 | 77 | @Override 78 | public void onItemClick(int position) { 79 | ListFragmentDirections.ActionListFragmentToDetailFragment action = 80 | ListFragmentDirections.actionListFragmentToDetailFragment(); 81 | action.setPosition(position); 82 | navController.navigate(action); 83 | } 84 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/views/Quizragment.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.views; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.annotation.Nullable; 7 | import androidx.core.content.ContextCompat; 8 | import androidx.fragment.app.Fragment; 9 | import androidx.lifecycle.Observer; 10 | import androidx.lifecycle.ViewModelProvider; 11 | import androidx.navigation.NavController; 12 | import androidx.navigation.Navigation; 13 | 14 | import android.os.CountDownTimer; 15 | import android.view.LayoutInflater; 16 | import android.view.View; 17 | import android.view.ViewGroup; 18 | import android.widget.Button; 19 | import android.widget.ImageView; 20 | import android.widget.ProgressBar; 21 | import android.widget.TextView; 22 | 23 | import com.codingstuff.quizzyapp.Model.QuestionModel; 24 | import com.codingstuff.quizzyapp.R; 25 | import com.codingstuff.quizzyapp.viewmodel.QuestionViewModel; 26 | import com.codingstuff.quizzyapp.viewmodel.QuizListViewModel; 27 | 28 | import java.util.HashMap; 29 | import java.util.List; 30 | 31 | 32 | public class Quizragment extends Fragment implements View.OnClickListener { 33 | 34 | private QuestionViewModel viewModel; 35 | private NavController navController; 36 | private ProgressBar progressBar; 37 | private Button option1Btn , option2Btn , option3Btn , nextQueBtn; 38 | private TextView questionTv , ansFeedBackTv , questionNumberTv , timerCountTv; 39 | private ImageView closeQuizBtn; 40 | private String quizId; 41 | private long totalQuestions; 42 | private int currentQueNo = 0; 43 | private boolean canAnswer = false; 44 | private long timer; 45 | private CountDownTimer countDownTimer; 46 | private int notAnswerd = 0; 47 | private int correctAnswer = 0; 48 | private int wrongAnswer = 0; 49 | private String answer = ""; 50 | 51 | 52 | @Override 53 | public void onCreate(@Nullable Bundle savedInstanceState) { 54 | super.onCreate(savedInstanceState); 55 | 56 | viewModel = new ViewModelProvider(this , ViewModelProvider.AndroidViewModelFactory 57 | .getInstance(getActivity().getApplication())).get(QuestionViewModel.class); 58 | } 59 | 60 | @Override 61 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 62 | Bundle savedInstanceState) { 63 | // Inflate the layout for this fragment 64 | return inflater.inflate(R.layout.fragment_quiz, container, false); 65 | } 66 | 67 | @Override 68 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 69 | super.onViewCreated(view, savedInstanceState); 70 | 71 | navController = Navigation.findNavController(view); 72 | 73 | closeQuizBtn = view.findViewById(R.id.imageView3); 74 | option1Btn = view.findViewById(R.id.option1Btn); 75 | option2Btn = view.findViewById(R.id.option2Btn); 76 | option3Btn = view.findViewById(R.id.option3Btn); 77 | nextQueBtn = view.findViewById(R.id.nextQueBtn); 78 | ansFeedBackTv = view.findViewById(R.id.ansFeedbackTv); 79 | questionTv = view.findViewById(R.id.quizQuestionTv); 80 | timerCountTv = view.findViewById(R.id.countTimeQuiz); 81 | questionNumberTv = view.findViewById(R.id.quizQuestionsCount); 82 | progressBar = view.findViewById(R.id.quizCoutProgressBar); 83 | 84 | quizId = QuizragmentArgs.fromBundle(getArguments()).getQuizId(); 85 | totalQuestions = QuizragmentArgs.fromBundle(getArguments()).getTotalQueCount(); 86 | viewModel.setQuizId(quizId); 87 | viewModel.getQuestions();; 88 | 89 | option1Btn.setOnClickListener(this); 90 | option2Btn.setOnClickListener(this); 91 | option3Btn.setOnClickListener(this); 92 | nextQueBtn.setOnClickListener(this); 93 | 94 | closeQuizBtn.setOnClickListener(new View.OnClickListener() { 95 | @Override 96 | public void onClick(View v) { 97 | navController.navigate(R.id.action_quizragment_to_listFragment); 98 | } 99 | }); 100 | 101 | loadData(); 102 | } 103 | 104 | private void loadData(){ 105 | enableOptions(); 106 | loadQuestions(1); 107 | } 108 | 109 | private void enableOptions(){ 110 | option1Btn.setVisibility(View.VISIBLE); 111 | option2Btn.setVisibility(View.VISIBLE); 112 | option3Btn.setVisibility(View.VISIBLE); 113 | 114 | //enable buttons , hide feedback tv , hide nextQuiz btn 115 | 116 | option1Btn.setEnabled(true); 117 | option2Btn.setEnabled(true); 118 | option3Btn.setEnabled(true); 119 | 120 | ansFeedBackTv.setVisibility(View.INVISIBLE); 121 | nextQueBtn.setVisibility(View.INVISIBLE); 122 | } 123 | 124 | private void loadQuestions(int i){ 125 | 126 | currentQueNo = i; 127 | viewModel.getQuestionMutableLiveData().observe(getViewLifecycleOwner(), new Observer>() { 128 | @Override 129 | public void onChanged(List questionModels) { 130 | questionTv.setText(String.valueOf(currentQueNo) + ") " + questionModels.get(i - 1).getQuestion()); 131 | option1Btn.setText(questionModels.get(i - 1).getOption_a()); 132 | option2Btn.setText(questionModels.get(i - 1).getOption_b()); 133 | option3Btn.setText(questionModels.get(i - 1).getOption_c()); 134 | timer = questionModels.get(i-1).getTimer(); 135 | answer = questionModels.get(i-1).getAnswer(); 136 | 137 | //todo set current que no, to que number tv 138 | questionNumberTv.setText(String.valueOf(currentQueNo)); 139 | startTimer(); 140 | } 141 | }); 142 | 143 | canAnswer = true; 144 | } 145 | 146 | private void startTimer(){ 147 | timerCountTv.setText(String.valueOf(timer)); 148 | progressBar.setVisibility(View.VISIBLE); 149 | 150 | countDownTimer = new CountDownTimer(timer * 1000 , 1000) { 151 | @Override 152 | public void onTick(long millisUntilFinished) { 153 | // update time 154 | timerCountTv.setText(millisUntilFinished / 1000 + ""); 155 | 156 | Long percent = millisUntilFinished/(timer*10); 157 | progressBar.setProgress(percent.intValue()); 158 | } 159 | 160 | @Override 161 | public void onFinish() { 162 | canAnswer = false; 163 | ansFeedBackTv.setText("Times Up !! No answer selected"); 164 | notAnswerd ++; 165 | showNextBtn(); 166 | } 167 | }.start(); 168 | } 169 | 170 | private void showNextBtn() { 171 | if (currentQueNo == totalQuestions){ 172 | nextQueBtn.setText("Submit"); 173 | nextQueBtn.setEnabled(true); 174 | nextQueBtn.setVisibility(View.VISIBLE); 175 | }else{ 176 | nextQueBtn.setVisibility(View.VISIBLE); 177 | nextQueBtn.setEnabled(true); 178 | ansFeedBackTv.setVisibility(View.VISIBLE); 179 | } 180 | } 181 | 182 | @Override 183 | public void onClick(View v) { 184 | switch (v.getId()){ 185 | case R.id.option1Btn: 186 | verifyAnswer(option1Btn); 187 | break; 188 | case R.id.option2Btn: 189 | verifyAnswer(option2Btn); 190 | break; 191 | case R.id.option3Btn: 192 | verifyAnswer(option3Btn); 193 | break; 194 | case R.id.nextQueBtn: 195 | if (currentQueNo == totalQuestions){ 196 | submitResults(); 197 | }else{ 198 | currentQueNo ++; 199 | loadQuestions(currentQueNo); 200 | resetOptions(); 201 | } 202 | break; 203 | } 204 | } 205 | 206 | private void resetOptions(){ 207 | ansFeedBackTv.setVisibility(View.INVISIBLE); 208 | nextQueBtn.setVisibility(View.INVISIBLE); 209 | nextQueBtn.setEnabled(false); 210 | option1Btn.setBackground(ContextCompat.getDrawable(getContext() , R.color.light_sky)); 211 | option2Btn.setBackground(ContextCompat.getDrawable(getContext() , R.color.light_sky)); 212 | option3Btn.setBackground(ContextCompat.getDrawable(getContext() , R.color.light_sky)); 213 | } 214 | 215 | private void submitResults() { 216 | HashMap resultMap = new HashMap<>(); 217 | resultMap.put("correct" , correctAnswer); 218 | resultMap.put("wrong" , wrongAnswer); 219 | resultMap.put("notAnswered" , notAnswerd); 220 | 221 | viewModel.addResults(resultMap); 222 | 223 | QuizragmentDirections.ActionQuizragmentToResultFragment action = 224 | QuizragmentDirections.actionQuizragmentToResultFragment(); 225 | action.setQuizId(quizId); 226 | navController.navigate(action); 227 | 228 | } 229 | 230 | private void verifyAnswer(Button button){ 231 | if (canAnswer){ 232 | if (answer.equals(button.getText())){ 233 | button.setBackground(ContextCompat.getDrawable(getContext() , R.color.green)); 234 | correctAnswer++; 235 | ansFeedBackTv.setText("Correct Answer"); 236 | }else{ 237 | button.setBackground(ContextCompat.getDrawable(getContext() , R.color.red)); 238 | wrongAnswer++; 239 | ansFeedBackTv.setText("Wrong Answer \nCorrect Answer :" + answer); 240 | } 241 | } 242 | canAnswer=false; 243 | countDownTimer.cancel(); 244 | showNextBtn(); 245 | } 246 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/views/ResultFragment.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.views; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.annotation.Nullable; 7 | import androidx.fragment.app.Fragment; 8 | import androidx.lifecycle.Observer; 9 | import androidx.lifecycle.ViewModelProvider; 10 | import androidx.navigation.NavController; 11 | import androidx.navigation.Navigation; 12 | 13 | import android.view.LayoutInflater; 14 | import android.view.View; 15 | import android.view.ViewGroup; 16 | import android.widget.Button; 17 | import android.widget.ProgressBar; 18 | import android.widget.TextView; 19 | import android.widget.Toast; 20 | 21 | import com.codingstuff.quizzyapp.Model.ResultModel; 22 | import com.codingstuff.quizzyapp.R; 23 | import com.codingstuff.quizzyapp.viewmodel.QuestionViewModel; 24 | import com.google.android.gms.tasks.OnCompleteListener; 25 | import com.google.android.gms.tasks.Task; 26 | import com.google.firebase.auth.FirebaseAuth; 27 | import com.google.firebase.firestore.DocumentSnapshot; 28 | import com.google.firebase.firestore.FirebaseFirestore; 29 | 30 | import java.util.HashMap; 31 | import java.util.Objects; 32 | 33 | 34 | public class ResultFragment extends Fragment { 35 | 36 | private NavController navController; 37 | private QuestionViewModel viewModel; 38 | private TextView correctAnswer , wrongAnswer , notAnswered; 39 | private TextView percentTv; 40 | private ProgressBar scoreProgressbar; 41 | private String quizId; 42 | private Button homeBtn; 43 | 44 | @Override 45 | public void onCreate(@Nullable Bundle savedInstanceState) { 46 | super.onCreate(savedInstanceState); 47 | 48 | viewModel = new ViewModelProvider(this , ViewModelProvider.AndroidViewModelFactory 49 | .getInstance(getActivity().getApplication())).get(QuestionViewModel.class); 50 | } 51 | @Override 52 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 53 | Bundle savedInstanceState) { 54 | // Inflate the layout for this fragment 55 | return inflater.inflate(R.layout.fragment_result, container, false); 56 | } 57 | 58 | @Override 59 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 60 | super.onViewCreated(view, savedInstanceState); 61 | 62 | navController = Navigation.findNavController(view); 63 | correctAnswer = view.findViewById(R.id.correctAnswerTv); 64 | wrongAnswer = view.findViewById(R.id.wrongAnswersTv); 65 | notAnswered = view.findViewById(R.id.notAnsweredTv); 66 | percentTv = view.findViewById(R.id.resultPercentageTv); 67 | scoreProgressbar = view.findViewById(R.id.resultCoutProgressBar); 68 | homeBtn = view.findViewById(R.id.home_btn); 69 | 70 | 71 | homeBtn.setOnClickListener(new View.OnClickListener() { 72 | @Override 73 | public void onClick(View v) { 74 | navController.navigate(R.id.action_resultFragment_to_listFragment); 75 | } 76 | }); 77 | 78 | quizId = ResultFragmentArgs.fromBundle(getArguments()).getQuizId(); 79 | 80 | viewModel.setQuizId(quizId); 81 | viewModel.getResults(); 82 | viewModel.getResultMutableLiveData().observe(getViewLifecycleOwner(), new Observer>() { 83 | @Override 84 | public void onChanged(HashMap stringLongHashMap) { 85 | 86 | Long correct = stringLongHashMap.get("correct"); 87 | Long wrong = stringLongHashMap.get("wrong"); 88 | Long noAnswer = stringLongHashMap.get("notAnswered"); 89 | 90 | correctAnswer.setText(correct.toString()); 91 | wrongAnswer.setText(wrong.toString()); 92 | notAnswered.setText(noAnswer.toString()); 93 | 94 | Long total = correct + wrong + noAnswer; 95 | Long percent = (correct*100)/total; 96 | 97 | percentTv.setText(String.valueOf(percent)); 98 | scoreProgressbar.setProgress(percent.intValue()); 99 | 100 | } 101 | }); 102 | 103 | } 104 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/views/SignInFragment.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.views; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.annotation.Nullable; 7 | import androidx.fragment.app.Fragment; 8 | import androidx.lifecycle.Observer; 9 | import androidx.lifecycle.ViewModelProvider; 10 | import androidx.navigation.NavController; 11 | import androidx.navigation.Navigation; 12 | 13 | import android.view.LayoutInflater; 14 | import android.view.View; 15 | import android.view.ViewGroup; 16 | import android.widget.Button; 17 | import android.widget.EditText; 18 | import android.widget.TextView; 19 | import android.widget.Toast; 20 | 21 | import com.codingstuff.quizzyapp.R; 22 | import com.codingstuff.quizzyapp.viewmodel.AuthViewModel; 23 | import com.google.firebase.auth.FirebaseUser; 24 | 25 | 26 | public class SignInFragment extends Fragment { 27 | private AuthViewModel viewModel; 28 | private NavController navController; 29 | private EditText editEmail , editPass; 30 | private TextView signUpText; 31 | private Button signInBtn; 32 | @Override 33 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 34 | Bundle savedInstanceState) { 35 | // Inflate the layout for this fragment 36 | return inflater.inflate(R.layout.fragment_sign_in, container, false); 37 | } 38 | 39 | @Override 40 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 41 | super.onViewCreated(view, savedInstanceState); 42 | 43 | navController = Navigation.findNavController(view); 44 | editEmail = view.findViewById(R.id.emailEditSignIN); 45 | editPass = view.findViewById(R.id.passEditSignIn); 46 | signUpText = view.findViewById(R.id.signUpText); 47 | signInBtn = view.findViewById(R.id.signInBtn); 48 | 49 | signUpText.setOnClickListener(new View.OnClickListener() { 50 | @Override 51 | public void onClick(View v) { 52 | navController.navigate(R.id.action_signInFragment_to_signUpFragment); 53 | } 54 | }); 55 | 56 | signInBtn.setOnClickListener(new View.OnClickListener() { 57 | @Override 58 | public void onClick(View v) { 59 | String email = editEmail.getText().toString(); 60 | String pass = editPass.getText().toString(); 61 | if (!email.isEmpty() && !pass.isEmpty()){ 62 | viewModel.signIn(email , pass); 63 | Toast.makeText(getContext(), "Login Successfully", Toast.LENGTH_SHORT).show(); 64 | viewModel.getFirebaseUserMutableLiveData().observe(getViewLifecycleOwner(), new Observer() { 65 | @Override 66 | public void onChanged(FirebaseUser firebaseUser) { 67 | if (firebaseUser !=null){ 68 | navController.navigate(R.id.action_signInFragment_to_listFragment); 69 | } 70 | } 71 | }); 72 | }else{ 73 | Toast.makeText(getContext(), "Please Enter Email and Pass", Toast.LENGTH_SHORT).show(); 74 | } 75 | } 76 | }); 77 | } 78 | 79 | @Override 80 | public void onCreate(@Nullable Bundle savedInstanceState) { 81 | super.onCreate(savedInstanceState); 82 | 83 | viewModel = new ViewModelProvider(this , ViewModelProvider.AndroidViewModelFactory 84 | .getInstance(getActivity().getApplication())).get(AuthViewModel.class); 85 | 86 | } 87 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/views/SignUpFragment.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.views; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.annotation.Nullable; 7 | import androidx.fragment.app.Fragment; 8 | import androidx.lifecycle.Observer; 9 | import androidx.lifecycle.ViewModelProvider; 10 | import androidx.navigation.NavController; 11 | import androidx.navigation.Navigation; 12 | 13 | import android.os.Handler; 14 | import android.view.LayoutInflater; 15 | import android.view.View; 16 | import android.view.ViewGroup; 17 | import android.widget.Button; 18 | import android.widget.EditText; 19 | import android.widget.TextView; 20 | import android.widget.Toast; 21 | 22 | import com.codingstuff.quizzyapp.R; 23 | import com.codingstuff.quizzyapp.viewmodel.AuthViewModel; 24 | import com.google.firebase.auth.FirebaseUser; 25 | 26 | public class SignUpFragment extends Fragment { 27 | 28 | private AuthViewModel viewModel; 29 | private NavController navController; 30 | private EditText editEmail , editPass; 31 | private TextView signInText; 32 | private Button signUpBtn; 33 | 34 | 35 | @Override 36 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 37 | Bundle savedInstanceState) { 38 | // Inflate the layout for this fragment 39 | return inflater.inflate(R.layout.fragment_sign_up, container, false); 40 | } 41 | 42 | @Override 43 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 44 | super.onViewCreated(view, savedInstanceState); 45 | 46 | navController = Navigation.findNavController(view); 47 | editEmail = view.findViewById(R.id.editEmailSignUp); 48 | editPass = view.findViewById(R.id.editPassSignUp); 49 | signInText = view.findViewById(R.id.signInText); 50 | signUpBtn = view.findViewById(R.id.signUpBtn); 51 | 52 | signInText.setOnClickListener(new View.OnClickListener() { 53 | @Override 54 | public void onClick(View v) { 55 | navController.navigate(R.id.action_signUpFragment_to_signInFragment); 56 | } 57 | }); 58 | 59 | signUpBtn.setOnClickListener(new View.OnClickListener() { 60 | @Override 61 | public void onClick(View v) { 62 | String email = editEmail.getText().toString(); 63 | String pass = editPass.getText().toString(); 64 | if (!email.isEmpty() && !pass.isEmpty()){ 65 | viewModel.signUp(email , pass); 66 | Toast.makeText(getContext(), "Registered Successfully", Toast.LENGTH_SHORT).show(); 67 | viewModel.getFirebaseUserMutableLiveData().observe(getViewLifecycleOwner(), new Observer() { 68 | @Override 69 | public void onChanged(FirebaseUser firebaseUser) { 70 | if (firebaseUser !=null){ 71 | navController.navigate(R.id.action_signUpFragment_to_signInFragment); 72 | } 73 | } 74 | }); 75 | }else{ 76 | Toast.makeText(getContext(), "Please Enter Email and Pass", Toast.LENGTH_SHORT).show(); 77 | } 78 | } 79 | }); 80 | } 81 | 82 | @Override 83 | public void onCreate(@Nullable Bundle savedInstanceState) { 84 | super.onCreate(savedInstanceState); 85 | 86 | viewModel = new ViewModelProvider(this , ViewModelProvider.AndroidViewModelFactory 87 | .getInstance(getActivity().getApplication())).get(AuthViewModel.class); 88 | 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/quizzyapp/views/SplashFragment.java: -------------------------------------------------------------------------------- 1 | package com.codingstuff.quizzyapp.views; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.annotation.Nullable; 7 | import androidx.fragment.app.Fragment; 8 | import androidx.lifecycle.ViewModelProvider; 9 | import androidx.navigation.NavController; 10 | import androidx.navigation.Navigation; 11 | 12 | import android.os.Handler; 13 | import android.view.LayoutInflater; 14 | import android.view.View; 15 | import android.view.ViewGroup; 16 | 17 | import com.codingstuff.quizzyapp.R; 18 | import com.codingstuff.quizzyapp.viewmodel.AuthViewModel; 19 | 20 | public class SplashFragment extends Fragment { 21 | 22 | 23 | private AuthViewModel viewModel; 24 | private NavController navController; 25 | 26 | @Override 27 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 28 | Bundle savedInstanceState) { 29 | // Inflate the layout for this fragment 30 | return inflater.inflate(R.layout.fragment_splash, container, false); 31 | } 32 | 33 | @Override 34 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 35 | super.onViewCreated(view, savedInstanceState); 36 | 37 | viewModel = new ViewModelProvider(this , ViewModelProvider.AndroidViewModelFactory 38 | .getInstance(getActivity().getApplication())).get(AuthViewModel.class); 39 | navController = Navigation.findNavController(view); 40 | } 41 | 42 | @Override 43 | public void onCreate(@Nullable Bundle savedInstanceState) { 44 | super.onCreate(savedInstanceState); 45 | 46 | Handler handler = new Handler(); 47 | handler.postDelayed(new Runnable() { 48 | @Override 49 | public void run() { 50 | if (viewModel.getCurrentUser() != null){ 51 | navController.navigate(R.id.action_splashFragment_to_listFragment); 52 | }else{ 53 | navController.navigate(R.id.action_splashFragment_to_signInFragment); 54 | } 55 | } 56 | }, 4000); 57 | 58 | } 59 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/circular_progressbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 14 | 15 | 16 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingSTUFF070/Quizzy-App-MVVM-/8cb3c907d6dd09e6dc16047ab011c6eeab4cb26f/app/src/main/res/drawable-v24/splash.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/studying.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingSTUFF070/Quizzy-App-MVVM-/8cb3c907d6dd09e6dc16047ab011c6eeab4cb26f/app/src/main/res/drawable-v24/studying.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/edit_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_close_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/each_quiz.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 20 | 21 | 24 | 25 | 34 | 35 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 21 | 22 | 34 | 35 | 45 | 46 | 56 | 57 | 67 | 68 | 77 | 78 |