diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index d0f378f7..68a1defe 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -304,6 +304,26 @@
android:label="@string/navigation_drawer"
android:parentActivityName=".ui.screens.main.MainActivity" />
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/notifications/workers/QuizReminderWorker.java b/app/src/main/java/com/d4rk/androidtutorials/java/notifications/workers/QuizReminderWorker.java
index 42ac40be..356a12dd 100644
--- a/app/src/main/java/com/d4rk/androidtutorials/java/notifications/workers/QuizReminderWorker.java
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/notifications/workers/QuizReminderWorker.java
@@ -4,17 +4,17 @@
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
+import android.content.Intent;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
-import androidx.navigation.NavDeepLinkBuilder;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import com.d4rk.androidtutorials.java.R;
-import com.d4rk.androidtutorials.java.ui.screens.main.MainActivity;
+import com.d4rk.androidtutorials.java.ui.screens.quiz.QuizActivity;
/**
* Worker that displays the daily quiz reminder notification.
@@ -39,11 +39,9 @@ public Result doWork() {
);
manager.createNotificationChannel(channel);
- PendingIntent pendingIntent = new NavDeepLinkBuilder(getApplicationContext())
- .setComponentName(MainActivity.class)
- .setGraph(R.navigation.mobile_navigation)
- .setDestination(R.id.navigation_quiz)
- .createPendingIntent();
+ Intent intent = new Intent(getApplicationContext(), QuizActivity.class);
+ PendingIntent pendingIntent = PendingIntent.getActivity(
+ getApplicationContext(), 0, intent, PendingIntent.FLAG_IMMUTABLE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), channelId)
.setSmallIcon(R.drawable.ic_check_circle)
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/components/navigation/BottomSheetMenuFragment.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/components/navigation/BottomSheetMenuFragment.java
index 5471f37e..0f60de3c 100644
--- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/components/navigation/BottomSheetMenuFragment.java
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/components/navigation/BottomSheetMenuFragment.java
@@ -12,7 +12,7 @@
import com.d4rk.androidtutorials.java.BuildConfig;
import com.d4rk.androidtutorials.java.R;
import com.d4rk.androidtutorials.java.databinding.BottomSheetMenuBinding;
-import androidx.navigation.fragment.NavHostFragment;
+import com.d4rk.androidtutorials.java.ui.screens.settings.SettingsActivity;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
public class BottomSheetMenuFragment extends BottomSheetDialogFragment {
@@ -26,12 +26,8 @@ public View onCreateView(@NonNull LayoutInflater inflater,
binding = BottomSheetMenuBinding.inflate(inflater, container, false);
binding.menuSettings.setOnClickListener(v -> {
- NavHostFragment navHostFragment = (NavHostFragment) requireActivity()
- .getSupportFragmentManager()
- .findFragmentById(R.id.nav_host_fragment_activity_main);
- if (navHostFragment != null) {
- navHostFragment.getNavController().navigate(R.id.navigation_settings);
- }
+ Intent intent = new Intent(requireContext(), SettingsActivity.class);
+ startActivity(intent);
dismiss();
});
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/main/MainActivity.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/main/MainActivity.java
index 28d6de40..69803624 100644
--- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/main/MainActivity.java
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/main/MainActivity.java
@@ -35,6 +35,7 @@
import com.d4rk.androidtutorials.java.ui.components.navigation.BottomSheetMenuFragment;
import com.d4rk.androidtutorials.java.ui.screens.startup.StartupViewModel;
import com.d4rk.androidtutorials.java.ui.screens.startup.dialogs.ConsentDialogFragment;
+import com.d4rk.androidtutorials.java.ui.screens.support.SupportActivity;
import com.d4rk.androidtutorials.java.utils.ConsentUtils;
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeDelegate;
import com.google.android.gms.ads.AdRequest;
@@ -256,9 +257,7 @@ public boolean onCreateOptionsMenu(android.view.Menu menu) {
@Override
public boolean onOptionsItemSelected(android.view.MenuItem item) {
if (item.getItemId() == R.id.support) {
- if (navController != null) {
- navController.navigate(R.id.navigation_support);
- }
+ startActivity(new Intent(this, SupportActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/quiz/QuizFragment.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/quiz/QuizActivity.java
similarity index 69%
rename from app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/quiz/QuizFragment.java
rename to app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/quiz/QuizActivity.java
index d771d234..2dfc4ac2 100644
--- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/quiz/QuizFragment.java
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/quiz/QuizActivity.java
@@ -1,54 +1,60 @@
package com.d4rk.androidtutorials.java.ui.screens.quiz;
import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
+import android.view.MenuItem;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
-import androidx.navigation.fragment.NavHostFragment;
-import com.airbnb.lottie.LottieAnimationView;
import com.d4rk.androidtutorials.java.R;
import com.d4rk.androidtutorials.java.data.model.QuizQuestion;
-import com.d4rk.androidtutorials.java.databinding.FragmentQuizBinding;
+import com.d4rk.androidtutorials.java.databinding.ActivityQuizBinding;
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeDelegate;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+import com.airbnb.lottie.LottieAnimationView;
+/**
+ * Activity that displays a simple multiple-choice quiz.
+ */
import dagger.hilt.android.AndroidEntryPoint;
@AndroidEntryPoint
-public class QuizFragment extends Fragment {
+public class QuizActivity extends AppCompatActivity {
- private FragmentQuizBinding binding;
+ private ActivityQuizBinding binding;
private QuizViewModel viewModel;
- @Nullable
@Override
- public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
- @Nullable Bundle savedInstanceState) {
- binding = FragmentQuizBinding.inflate(inflater, container, false);
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ binding = ActivityQuizBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
- EdgeToEdgeDelegate edgeToEdgeDelegate = new EdgeToEdgeDelegate(requireActivity());
+ EdgeToEdgeDelegate edgeToEdgeDelegate = new EdgeToEdgeDelegate(this);
edgeToEdgeDelegate.applyEdgeToEdge(binding.container);
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
+
viewModel = new ViewModelProvider(this).get(QuizViewModel.class);
if (viewModel.getTotalQuestions() == 0) {
- new MaterialAlertDialogBuilder(requireContext())
+ new MaterialAlertDialogBuilder(this)
.setMessage(R.string.quiz_no_more_questions)
- .setPositiveButton(android.R.string.ok, (d, w) -> NavHostFragment.findNavController(this).popBackStack())
+ .setPositiveButton(android.R.string.ok, (d, w) -> finish())
.setCancelable(false)
.show();
- } else {
- showQuestion(viewModel.getCurrentQuestion());
- binding.buttonNext.setOnClickListener(v -> onNextClicked());
+ return;
}
+ showQuestion(viewModel.getCurrentQuestion());
- return binding.getRoot();
+ binding.buttonNext.setOnClickListener(v -> onNextClicked());
}
private void onNextClicked() {
@@ -88,21 +94,24 @@ private void showQuestion(QuizQuestion question) {
private void showResult() {
int score = viewModel.getScore().getValue();
int total = viewModel.getTotalQuestions();
- View view = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_quiz_result, null, false);
+ View view = LayoutInflater.from(this).inflate(R.layout.dialog_quiz_result, null, false);
TextView textResult = view.findViewById(R.id.text_result);
textResult.setText(getString(R.string.quiz_finished, score, total));
LottieAnimationView animationView = view.findViewById(R.id.animation_success);
animationView.playAnimation();
- new MaterialAlertDialogBuilder(requireContext())
+ new MaterialAlertDialogBuilder(this)
.setView(view)
- .setPositiveButton(android.R.string.ok, (d, w) -> NavHostFragment.findNavController(this).popBackStack())
+ .setPositiveButton(android.R.string.ok, (d, w) -> finish())
.setCancelable(false)
.show();
}
@Override
- public void onDestroyView() {
- super.onDestroyView();
- binding = null;
+ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
}
}
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/settings/SettingsActivity.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/settings/SettingsActivity.java
new file mode 100644
index 00000000..2d52301d
--- /dev/null
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/settings/SettingsActivity.java
@@ -0,0 +1,84 @@
+package com.d4rk.androidtutorials.java.ui.screens.settings;
+
+import android.content.SharedPreferences;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.preference.ListPreference;
+
+import com.d4rk.androidtutorials.java.R;
+import com.d4rk.androidtutorials.java.databinding.ActivitySettingsBinding;
+import com.d4rk.androidtutorials.java.utils.EdgeToEdgeDelegate;
+
+/**
+ * Settings screen that delegates preference change logic to a ViewModel/Repository.
+ */
+import dagger.hilt.android.AndroidEntryPoint;
+
+@AndroidEntryPoint
+public class SettingsActivity extends AppCompatActivity
+ implements SharedPreferences.OnSharedPreferenceChangeListener,
+ androidx.preference.Preference.SummaryProvider {
+
+ private SettingsViewModel settingsViewModel;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ActivitySettingsBinding binding = ActivitySettingsBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
+
+ EdgeToEdgeDelegate edgeToEdgeDelegate = new EdgeToEdgeDelegate(this);
+ edgeToEdgeDelegate.applyEdgeToEdge(binding.container);
+
+ settingsViewModel = new ViewModelProvider(this).get(SettingsViewModel.class);
+ settingsViewModel.applyConsent();
+
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.settings, new SettingsFragment())
+ .commit();
+
+ ActionBar supportActionBar = getSupportActionBar();
+ if (supportActionBar != null) {
+ supportActionBar.setDisplayHomeAsUpEnabled(true);
+ }
+
+ settingsViewModel.registerPreferenceChangeListener(this);
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ boolean changedTheme = settingsViewModel.onPreferenceChanged(key);
+ if (changedTheme) {
+ recreate();
+ }
+ }
+
+ /**
+ * Provide summary for ListPreference if needed
+ */
+ @Override
+ public CharSequence provideSummary(ListPreference preference) {
+ String key = preference.getKey();
+ if (key != null && key.equals(getString(R.string.dark_mode))) {
+ String value = settingsViewModel.getDarkMode();
+ int index = preference.findIndexOfValue(value);
+ if (index >= 0) {
+ CharSequence[] entries = preference.getEntries();
+ if (entries != null && index < entries.length) {
+ return entries[index];
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ settingsViewModel.unregisterPreferenceChangeListener(this);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/support/SupportFragment.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/support/SupportActivity.java
similarity index 74%
rename from app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/support/SupportFragment.java
rename to app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/support/SupportActivity.java
index 38359cd2..7b868013 100644
--- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/support/SupportFragment.java
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/support/SupportActivity.java
@@ -3,18 +3,16 @@
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
+import android.view.MenuItem;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
import com.android.billingclient.api.ProductDetails;
import com.d4rk.androidtutorials.java.data.repository.SupportRepository;
-import com.d4rk.androidtutorials.java.databinding.FragmentSupportBinding;
+import com.d4rk.androidtutorials.java.databinding.ActivitySupportBinding;
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeDelegate;
import com.google.android.gms.ads.AdRequest;
@@ -23,20 +21,26 @@
import dagger.hilt.android.AndroidEntryPoint;
@AndroidEntryPoint
-public class SupportFragment extends Fragment {
+public class SupportActivity extends AppCompatActivity {
- private FragmentSupportBinding binding;
+ private ActivitySupportBinding binding;
private SupportViewModel supportViewModel;
- @Nullable
@Override
- public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
- @Nullable Bundle savedInstanceState) {
- binding = FragmentSupportBinding.inflate(inflater, container, false);
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ binding = ActivitySupportBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
- EdgeToEdgeDelegate edgeToEdgeDelegate = new EdgeToEdgeDelegate(requireActivity());
+
+ EdgeToEdgeDelegate edgeToEdgeDelegate = new EdgeToEdgeDelegate(this);
edgeToEdgeDelegate.applyEdgeToEdge(binding.container);
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
+
supportViewModel = new ViewModelProvider(this).get(SupportViewModel.class);
AdRequest adRequest = supportViewModel.initMobileAds();
@@ -51,8 +55,6 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
binding.buttonNormalDonation.setOnClickListener(v -> initiatePurchase("normal_donation"));
binding.buttonHighDonation.setOnClickListener(v -> initiatePurchase("high_donation"));
binding.buttonExtremeDonation.setOnClickListener(v -> initiatePurchase("extreme_donation"));
-
- return binding.getRoot();
}
private void queryProductDetails() {
@@ -75,13 +77,16 @@ private void queryProductDetails() {
private void initiatePurchase(String productId) {
SupportRepository.BillingFlowLauncher launcher = supportViewModel.initiatePurchase(productId);
if (launcher != null) {
- launcher.launch(requireActivity());
+ launcher.launch(this);
}
}
@Override
- public void onDestroyView() {
- super.onDestroyView();
- binding = null;
+ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_quiz.xml b/app/src/main/res/layout/activity_quiz.xml
similarity index 100%
rename from app/src/main/res/layout/fragment_quiz.xml
rename to app/src/main/res/layout/activity_quiz.xml
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
new file mode 100644
index 00000000..ec7d0231
--- /dev/null
+++ b/app/src/main/res/layout/activity_settings.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_support.xml b/app/src/main/res/layout/activity_support.xml
similarity index 100%
rename from app/src/main/res/layout/fragment_support.xml
rename to app/src/main/res/layout/activity_support.xml
diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml
index 98f3f661..58964ad1 100644
--- a/app/src/main/res/navigation/mobile_navigation.xml
+++ b/app/src/main/res/navigation/mobile_navigation.xml
@@ -17,24 +17,4 @@
android:name="com.d4rk.androidtutorials.java.ui.screens.about.AboutFragment"
android:label="@string/about"
tools:layout="@layout/fragment_about" />
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/xml-v26/shortcuts.xml b/app/src/main/res/xml-v26/shortcuts.xml
index 74cba319..50beaf4d 100644
--- a/app/src/main/res/xml-v26/shortcuts.xml
+++ b/app/src/main/res/xml-v26/shortcuts.xml
@@ -7,8 +7,7 @@
android:shortcutShortLabel="@string/settings">
\ No newline at end of file