Skip to content
Prev Previous commit
Next Next commit
Refine onboarding theme handling and integrate consent
  • Loading branch information
MihaiCristianCondrea committed Sep 12, 2025
commit 8c9fda906a6acb5934c40bf65443d1f55b3bb08a
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
import androidx.lifecycle.ViewModelProvider;

import com.d4rk.androidtutorials.java.databinding.FragmentOnboardingDataBinding;
import com.d4rk.androidtutorials.java.utils.ConsentUtils;
import androidx.preference.PreferenceManager;
import android.content.SharedPreferences;
import com.d4rk.androidtutorials.java.R;

public class DataFragment extends Fragment {

Expand All @@ -30,9 +34,27 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewModel = new ViewModelProvider(requireActivity()).get(OnboardingViewModel.class);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext());
String keyAnalytics = getString(R.string.key_consent_analytics);
String keyAdPersonalization = getString(R.string.key_consent_ad_personalization);

binding.switchCrashlytics.setOnCheckedChangeListener((buttonView, isChecked) ->
viewModel.setCrashlyticsEnabled(isChecked));
boolean analytics = prefs.getBoolean(keyAnalytics, true);
boolean ads = prefs.getBoolean(keyAdPersonalization, true);
binding.switchCrashlytics.setChecked(analytics);
binding.switchAds.setChecked(ads);

binding.switchCrashlytics.setOnCheckedChangeListener((buttonView, isChecked) -> {
viewModel.setCrashlyticsEnabled(isChecked);
viewModel.setConsentAnalytics(isChecked);
ConsentUtils.updateFirebaseConsent(requireContext(), isChecked, binding.switchAds.isChecked(), binding.switchAds.isChecked(), binding.switchAds.isChecked());
});

binding.switchAds.setOnCheckedChangeListener((buttonView, isChecked) -> {
viewModel.setConsentAdStorage(isChecked);
viewModel.setConsentAdUserData(isChecked);
viewModel.setConsentAdPersonalization(isChecked);
ConsentUtils.updateFirebaseConsent(requireContext(), binding.switchCrashlytics.isChecked(), isChecked, isChecked, isChecked);
});

binding.linkPrivacy.setOnClickListener(v -> {
Intent intent = new Intent(Intent.ACTION_VIEW,
Expand All @@ -42,7 +64,14 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
}

public void saveSelection() {
viewModel.setCrashlyticsEnabled(binding.switchCrashlytics.isChecked());
boolean analytics = binding.switchCrashlytics.isChecked();
boolean ads = binding.switchAds.isChecked();
viewModel.setCrashlyticsEnabled(analytics);
viewModel.setConsentAnalytics(analytics);
viewModel.setConsentAdStorage(ads);
viewModel.setConsentAdUserData(ads);
viewModel.setConsentAdPersonalization(ads);
ConsentUtils.updateFirebaseConsent(requireContext(), analytics, ads, ads, ads);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import androidx.lifecycle.ViewModelProvider;

import com.d4rk.androidtutorials.java.databinding.FragmentOnboardingDoneBinding;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package com.d4rk.androidtutorials.java.ui.screens.onboarding;

import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;

import androidx.annotation.NonNull;
import androidx.preference.PreferenceManager;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
Expand All @@ -17,8 +15,6 @@
import com.d4rk.androidtutorials.java.R;
import com.d4rk.androidtutorials.java.databinding.ActivityOnboardingBinding;
import com.d4rk.androidtutorials.java.ui.screens.main.MainActivity;
import com.d4rk.androidtutorials.java.ui.screens.startup.dialogs.ConsentDialogFragment;
import com.d4rk.androidtutorials.java.utils.ConsentUtils;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;

Expand All @@ -42,14 +38,9 @@ protected void onCreate(Bundle savedInstanceState) {

adapter = new OnboardingPagerAdapter(this);
binding.viewPager.setAdapter(adapter);

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String keyAnalytics = getString(R.string.key_consent_analytics);
if (!prefs.contains(keyAnalytics)) {
ConsentDialogFragment dialog = new ConsentDialogFragment();
dialog.setConsentListener((a,b,c,d) -> ConsentUtils.updateFirebaseConsent(this, a,b,c,d));
dialog.show(getSupportFragmentManager(), "consent");
}
int startPage = viewModel.getCurrentPage();
binding.viewPager.setCurrentItem(startPage, false);
currentPosition = startPage;

binding.viewPager.registerOnPageChangeCallback(new androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback() {
@Override
Expand All @@ -66,6 +57,7 @@ public void onPageSelected(int position) {
}
}
currentPosition = position;
viewModel.setCurrentPage(position);
}
});

Expand All @@ -80,9 +72,9 @@ public void onPageSelected(int position) {
tab.setCustomView(dot);
}).attach();

TabLayout.Tab firstTab = binding.tabIndicator.getTabAt(0);
if (firstTab != null && firstTab.getCustomView() instanceof ImageView) {
((ImageView) firstTab.getCustomView()).setImageResource(R.drawable.onboarding_dot_selected);
TabLayout.Tab startTab = binding.tabIndicator.getTabAt(startPage);
if (startTab != null && startTab.getCustomView() instanceof ImageView) {
((ImageView) startTab.getCustomView()).setImageResource(R.drawable.onboarding_dot_selected);
}

binding.tabIndicator.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
Expand Down Expand Up @@ -137,7 +129,7 @@ public void onTabReselected(TabLayout.Tab tab) {
}
});

updateButtons(0);
updateButtons(startPage);
}

void finishOnboarding() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class OnboardingViewModel extends ViewModel {

private final Context context;
private final SharedPreferences prefs;
private int currentPage = 0;

@Inject
public OnboardingViewModel(@ApplicationContext Context context) {
Expand All @@ -29,6 +30,19 @@ public void setTheme(String value) {
prefs.edit().putString(context.getString(R.string.key_theme), value).apply();
}

public String getTheme() {
String[] values = context.getResources().getStringArray(R.array.preference_theme_values);
return prefs.getString(context.getString(R.string.key_theme), values[0]);
}

public void setCurrentPage(int page) {
currentPage = page;
}

public int getCurrentPage() {
return currentPage;
}

public void setDefaultTab(String value) {
prefs.edit().putString(context.getString(R.string.key_default_tab), value).apply();
}
Expand All @@ -45,6 +59,22 @@ public void setCrashlyticsEnabled(boolean enabled) {
prefs.edit().putBoolean(context.getString(R.string.key_firebase_crashlytics), enabled).apply();
}

public void setConsentAnalytics(boolean enabled) {
prefs.edit().putBoolean(context.getString(R.string.key_consent_analytics), enabled).apply();
}

public void setConsentAdStorage(boolean enabled) {
prefs.edit().putBoolean(context.getString(R.string.key_consent_ad_storage), enabled).apply();
}

public void setConsentAdUserData(boolean enabled) {
prefs.edit().putBoolean(context.getString(R.string.key_consent_ad_user_data), enabled).apply();
}

public void setConsentAdPersonalization(boolean enabled) {
prefs.edit().putBoolean(context.getString(R.string.key_consent_ad_personalization), enabled).apply();
}

public void markOnboardingComplete() {
prefs.edit().putBoolean(context.getString(R.string.key_onboarding_complete), true).apply();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.appcompat.app.AppCompatDelegate;

import com.d4rk.androidtutorials.java.R;
import com.d4rk.androidtutorials.java.databinding.FragmentOnboardingSelectionBinding;
Expand Down Expand Up @@ -49,7 +49,12 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
binding.optionSecond.radioButton.setId(View.generateViewId());
binding.optionThird.radioButton.setId(View.generateViewId());

selectOption(2);
String themeValue = viewModel.getTheme();
String[] values = getResources().getStringArray(R.array.preference_theme_values);
int index = 2; // default follow system
if (themeValue.equals(values[1])) index = 0;
else if (themeValue.equals(values[2])) index = 1;
setRadioButtons(index);

binding.cardFirst.setOnClickListener(v -> selectOption(0));
binding.cardSecond.setOnClickListener(v -> selectOption(1));
Expand All @@ -60,33 +65,33 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
binding.optionThird.radioButton.setOnClickListener(v -> selectOption(2));
}

private void selectOption(int index) {
private void setRadioButtons(int index) {
binding.optionFirst.radioButton.setChecked(index == 0);
binding.optionSecond.radioButton.setChecked(index == 1);
binding.optionThird.radioButton.setChecked(index == 2);
}

private void selectOption(int index) {
setRadioButtons(index);
int mode;
String[] values = getResources().getStringArray(R.array.preference_theme_values);
String value;
if (index == 0) {
mode = AppCompatDelegate.MODE_NIGHT_NO;
value = values[1];
} else if (index == 1) {
mode = AppCompatDelegate.MODE_NIGHT_YES;
value = values[2];
} else {
mode = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM;
value = values[0];
}
viewModel.setTheme(value);
AppCompatDelegate.setDefaultNightMode(mode);
}

public void saveSelection() {
String[] values = getResources().getStringArray(R.array.preference_theme_values);
String value;
if (binding.optionFirst.radioButton.isChecked()) {
value = values[1];
} else if (binding.optionSecond.radioButton.isChecked()) {
value = values[2];
} else {
value = values[0];
}
viewModel.setTheme(value);
// theme stored on selection
}

@Override
Expand Down

This file was deleted.

14 changes: 12 additions & 2 deletions app/src/main/res/drawable-anydpi/ic_dark_mode.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
<path android:fillColor="#FF000000" android:pathData="M9.37 5.51A7 7 0 0 0 12 19a7 7 0 0 0 6.49-4.5 6.5 6.5 0 0 1 -9.12-9z"/>
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">

<path
android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
<path
android:fillColor="#000000"
android:pathData="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z" />
</vector>
14 changes: 12 additions & 2 deletions app/src/main/res/drawable-anydpi/ic_light_mode.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
<path android:fillColor="#FF000000" android:pathData="M6.76,4.84l-1.8,-1.79 -1.41,1.41 1.79,1.8 1.42,-1.42zM1,11h3v2H1v-2zm10,-9h2v3h-2V2zm7.66,3.05l1.79,-1.8 -1.41,-1.41 -1.8,1.79 1.42,1.42zM17,11h3v2h-3v-2zm-5,5a4,4 0 1,1 0,-8 4,4 0 0,1 0,8zm5.24,1.16l1.8,1.79 1.41,-1.41 -1.79,-1.8 -1.42,1.42zM13,22h-2v-3h2v3zm-7.66,-3.05l-1.79,1.8 1.41,1.41 1.8,-1.79 -1.42,-1.42z"/>
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">

<path
android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
<path
android:fillColor="#000000"
android:pathData="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z" />
</vector>
18 changes: 16 additions & 2 deletions app/src/main/res/drawable-anydpi/ic_system_mode.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
<path android:fillColor="#FF000000" android:pathData="M17,1H7C5.9,1 5,1.9 5,3v18c0,1.1 0.9,2 2,2h10c1.1,0 2-0.9 2-2V3c0-1.1-0.9-2-2-2zm0,18H7V5h10v14z"/>
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">

<group>
<path
android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
</group>
<group>
<path
android:fillColor="#000000"
android:pathData="M12,22c5.52,0,10-4.48,10-10S17.52,2,12,2S2,6.48,2,12S6.48,22,12,22z M13,4.07c3.94,0.49,7,3.85,7,7.93s-3.05,7.44-7,7.93 V4.07z" />
</group>
</vector>
Loading
Loading