Skip to content
Next Next commit
Improve onboarding with data consent and completion screens
  • Loading branch information
MihaiCristianCondrea committed Sep 12, 2025
commit 1a4ae7a0ac2e8d575443f22b3c30e97ae099df7d
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.d4rk.androidtutorials.java.ui.screens.onboarding;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
Expand Down Expand Up @@ -28,6 +30,21 @@ 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);

binding.switchCrashlytics.setOnCheckedChangeListener((buttonView, isChecked) -> {
binding.textDetails.setVisibility(isChecked ? View.VISIBLE : View.GONE);
viewModel.setCrashlyticsEnabled(isChecked);
});

binding.linkPrivacy.setOnClickListener(v -> {
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse("https://d4rk7355608.github.io/profile/#privacy-policy-apps"));
startActivity(intent);
});
}

public void saveSelection() {
viewModel.setCrashlyticsEnabled(binding.switchCrashlytics.isChecked());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Crashlytics consent toggle never disables collection

The new data-consent screen stores the user’s choice in shared preferences (setCrashlyticsEnabled), but the value is never applied to the Crashlytics SDK. There is no code anywhere in the app that reads key_firebase_crashlytics or calls FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(...), so crash reports remain enabled by default regardless of the user’s selection. This presents a privacy/compliance risk because the UI promises a choice that isn’t honored. Consider applying the stored value during app startup and updating the SDK configuration whenever the setting changes.

Useful? React with 👍 / 👎.

}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.d4rk.androidtutorials.java.ui.screens.onboarding;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.d4rk.androidtutorials.java.databinding.FragmentOnboardingDoneBinding;

public class DoneFragment extends Fragment {

private FragmentOnboardingDoneBinding binding;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentOnboardingDoneBinding.inflate(inflater, container, false);
return binding.getRoot();
}

@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,8 @@ public void onPageSelected(int position) {
Fragment fragment = getSupportFragmentManager().findFragmentByTag("f" + currentPosition);
if (fragment instanceof ThemeFragment) {
((ThemeFragment) fragment).saveSelection();
} else if (fragment instanceof StartPageFragment) {
((StartPageFragment) fragment).saveSelection();
} else if (fragment instanceof BottomLabelsFragment) {
((BottomLabelsFragment) fragment).saveSelection();
} else if (fragment instanceof FontFragment) {
((FontFragment) fragment).saveSelection();
} else if (fragment instanceof DataFragment) {
((DataFragment) fragment).saveSelection();
}
}
currentPosition = position;
Expand Down Expand Up @@ -102,12 +98,8 @@ public void onTabReselected(TabLayout.Tab tab) {
Fragment fragment = getSupportFragmentManager().findFragmentByTag("f" + current);
if (fragment instanceof ThemeFragment) {
((ThemeFragment) fragment).saveSelection();
} else if (fragment instanceof StartPageFragment) {
((StartPageFragment) fragment).saveSelection();
} else if (fragment instanceof BottomLabelsFragment) {
((BottomLabelsFragment) fragment).saveSelection();
} else if (fragment instanceof FontFragment) {
((FontFragment) fragment).saveSelection();
} else if (fragment instanceof DataFragment) {
((DataFragment) fragment).saveSelection();
}

if (current < adapter.getItemCount() - 1) {
Expand Down Expand Up @@ -148,19 +140,15 @@ public Fragment createFragment(int position) {
case 0:
return new ThemeFragment();
case 1:
return new StartPageFragment();
case 2:
return new BottomLabelsFragment();
case 3:
return new FontFragment();
default:
return new DataFragment();
default:
return new DoneFragment();
}
}

@Override
public int getItemCount() {
return 5;
return 3;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ public void setMonospaceFont(String value) {
prefs.edit().putString(context.getString(R.string.key_monospace_font), value).apply();
}

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

public void markOnboardingComplete() {
prefs.edit().putBoolean(context.getString(R.string.key_onboarding_complete), true).apply();
}
Expand Down
39 changes: 36 additions & 3 deletions app/src/main/res/layout/fragment_onboarding_data.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,43 @@
android:padding="16dp"
app:cardElevation="0dp">

<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/data_dialog_message" />
android:orientation="vertical">

<com.google.android.material.textview.MaterialTextView
style="@style/TextAppearance.Material3.TitleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="@string/onboarding_data_title" />

<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switchCrashlytics"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/onboarding_data_toggle" />

<com.google.android.material.textview.MaterialTextView
android:id="@+id/textDetails"
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/onboarding_data_active"
android:visibility="gone" />

<com.google.android.material.textview.MaterialTextView
android:id="@+id/linkPrivacy"
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/privacy_policy"
android:textColor="?attr/colorPrimary" />

</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</ScrollView>
48 changes: 48 additions & 0 deletions app/src/main/res/layout/fragment_onboarding_done.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">

<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="24dp"
app:cardElevation="0dp">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">

<ImageView
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginBottom="16dp"
android:src="@drawable/ic_check_circle" />

<com.google.android.material.textview.MaterialTextView
style="@style/TextAppearance.Material3.TitleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="@string/onboarding_done_title" />

<com.google.android.material.textview.MaterialTextView
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/onboarding_done_subtitle" />

</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</ScrollView>
5 changes: 5 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,11 @@
<string name="back">Back</string>
<string name="bottom_navigation_labels">Bottom navigation labels</string>
<string name="data_dialog_message">We collect data to improve your experience.</string>
<string name="onboarding_data_title">Help Us Improve</string>
<string name="onboarding_data_toggle">Allow anonymous usage and crash reports</string>
<string name="onboarding_data_active">Data reporting is active.</string>
<string name="onboarding_done_title">You're All Set!</string>
<string name="onboarding_done_subtitle">Thanks for customizing your experience. Enjoy exploring the app.</string>
<string name="summary_preference_permissions_access_notification_policy">Allows the app to access and modify the device\'s notification policy, controlling how and when notifications are displayed to the user and providing custom notification management features.</string>
<string name="summary_preference_permissions_foreground_service">Allows the app to create and use services that run in the foreground, giving them priority over other background processes and improving performance and reliability.</string>
<string name="summary_preference_settings_language">Set application language.</string>
Expand Down
Loading