Skip to content

Commit dba7af8

Browse files
Merge pull request #7 from D4rK7355608/codex/integrate-consent-check-in-main-activity
Implement Firebase consent dialog
2 parents c901dd0 + 9abeb11 commit dba7af8

File tree

7 files changed

+167
-21
lines changed

7 files changed

+167
-21
lines changed

app/build.gradle

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ android {
1818
vectorDrawables.useSupportLibrary = true
1919
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
2020
resourceConfigurations += ['en', 'de', 'es', 'fr', 'hi', 'hu', 'in', 'it', 'ja', 'ro', 'ru', 'tr', 'sv', 'bg', 'pl', 'uk']
21+
manifestPlaceholders = [
22+
analyticsStorage: true,
23+
adStorage: true,
24+
adUserData: true,
25+
adPersonalization: true
26+
]
2127
}
2228

2329
buildTypes {
@@ -27,11 +33,23 @@ android {
2733
shrinkResources true
2834
debuggable false
2935
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
36+
manifestPlaceholders = [
37+
analyticsStorage: true,
38+
adStorage: true,
39+
adUserData: true,
40+
adPersonalization: true
41+
]
3042
}
3143
debug {
3244
multiDexEnabled true
3345
debuggable true
3446
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
47+
manifestPlaceholders = [
48+
analyticsStorage: false,
49+
adStorage: false,
50+
adUserData: false,
51+
adPersonalization: false
52+
]
3553
}
3654
}
3755

app/src/main/AndroidManifest.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -332,9 +332,9 @@
332332
android:name="com.google.android.gms.ads.AD_MANAGER_APP"
333333
android:value="true" />
334334

335-
<meta-data android:name="google_analytics_default_allow_analytics_storage" android:value="false" />
336-
<meta-data android:name="google_analytics_default_allow_ad_storage" android:value="false" />
337-
<meta-data android:name="google_analytics_default_allow_ad_user_data" android:value="false" />
338-
<meta-data android:name="google_analytics_default_allow_ad_personalization_signals" android:value="false" />
335+
<meta-data android:name="google_analytics_default_allow_analytics_storage" android:value="${analyticsStorage}" />
336+
<meta-data android:name="google_analytics_default_allow_ad_storage" android:value="${adStorage}" />
337+
<meta-data android:name="google_analytics_default_allow_ad_user_data" android:value="${adUserData}" />
338+
<meta-data android:name="google_analytics_default_allow_ad_personalization_signals" android:value="${adPersonalization}" />
339339
</application>
340340
</manifest>

app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/main/MainActivity.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.d4rk.androidtutorials.java.notifications.managers.AppUsageNotificationsManager;
3333
import com.d4rk.androidtutorials.java.ui.components.navigation.BottomSheetMenuFragment;
3434
import com.d4rk.androidtutorials.java.ui.screens.startup.StartupActivity;
35+
import com.d4rk.androidtutorials.java.ui.screens.startup.StartupViewModel;
3536
import com.d4rk.androidtutorials.java.ui.screens.support.SupportActivity;
3637
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeDelegate;
3738
import com.google.android.gms.ads.AdRequest;
@@ -47,6 +48,9 @@
4748
import com.google.android.play.core.install.model.AppUpdateType;
4849
import com.google.android.play.core.install.model.InstallStatus;
4950
import com.google.android.play.core.install.model.UpdateAvailability;
51+
import com.google.android.ump.ConsentInformation;
52+
import com.google.android.ump.ConsentRequestParameters;
53+
import com.google.android.ump.UserMessagingPlatform;
5054

5155
public class MainActivity extends AppCompatActivity {
5256

@@ -61,6 +65,8 @@ public class MainActivity extends AppCompatActivity {
6165
);
6266
private ActivityMainBinding mBinding;
6367
private MainViewModel mainViewModel;
68+
private StartupViewModel startupViewModel;
69+
private ConsentInformation consentInformation;
6470
private NavController navController;
6571
private AppUpdateNotificationsManager appUpdateNotificationsManager;
6672
private AppUpdateManager appUpdateManager;
@@ -74,6 +80,21 @@ protected void onCreate(Bundle savedInstanceState) {
7480
setContentView(mBinding.getRoot());
7581

7682
mainViewModel = new ViewModelProvider(this).get(MainViewModel.class);
83+
startupViewModel = new ViewModelProvider(this).get(StartupViewModel.class);
84+
consentInformation = UserMessagingPlatform.getConsentInformation(this);
85+
ConsentRequestParameters params = new ConsentRequestParameters.Builder()
86+
.setTagForUnderAgeOfConsent(false)
87+
.build();
88+
startupViewModel.requestConsentInfoUpdate(
89+
this,
90+
params,
91+
() -> {
92+
if (consentInformation.isConsentFormAvailable()) {
93+
startupViewModel.loadConsentForm(this, null);
94+
}
95+
},
96+
null
97+
);
7798

7899
setupActionBar();
79100
observeViewModel();

app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/startup/StartupActivity.java

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import com.google.android.ump.ConsentRequestParameters;
1616
import com.google.android.ump.UserMessagingPlatform;
1717
import com.google.firebase.analytics.FirebaseAnalytics;
18+
import com.d4rk.androidtutorials.java.ui.screens.startup.dialogs.ConsentDialogFragment;
1819

1920
import java.util.EnumMap;
2021
import java.util.Map;
@@ -39,26 +40,20 @@ protected void onCreate(Bundle savedInstanceState) {
3940
.setTagForUnderAgeOfConsent(false)
4041
.build();
4142

42-
consentInformation.requestConsentInfoUpdate(
43+
startupViewModel.requestConsentInfoUpdate(
4344
this,
4445
params,
4546
() -> {
4647
if (consentInformation.isConsentFormAvailable()) {
4748
startupViewModel.loadConsentForm(
4849
this,
49-
formError -> {
50-
updateFirebaseConsent(false);
51-
proceedToMainActivity();
52-
}
50+
formError -> updateFirebaseConsent(false, false, false, false)
5351
);
54-
} else {
55-
if (consentInformation.getConsentStatus() == ConsentInformation.ConsentStatus.OBTAINED) {
56-
updateFirebaseConsent(true);
57-
}
58-
proceedToMainActivity();
52+
} else if (consentInformation.getConsentStatus() == ConsentInformation.ConsentStatus.OBTAINED) {
53+
updateFirebaseConsent(true, true, true, true);
5954
}
6055
},
61-
formError -> proceedToMainActivity()
56+
formError -> {}
6257
);
6358

6459
new FastScrollerBuilder(binding.scrollView)
@@ -70,7 +65,14 @@ protected void onCreate(Bundle savedInstanceState) {
7065
Uri.parse("https://sites.google.com/view/d4rk7355608/more/apps/privacy-policy")))
7166
);
7267

73-
binding.floatingButtonAgree.setOnClickListener(v -> proceedToMainActivity());
68+
binding.floatingButtonAgree.setOnClickListener(v -> {
69+
ConsentDialogFragment dialog = new ConsentDialogFragment();
70+
dialog.setConsentListener((analytics, adStorage, adUserData, adPersonalization) -> {
71+
updateFirebaseConsent(analytics, adStorage, adUserData, adPersonalization);
72+
proceedToMainActivity();
73+
});
74+
dialog.show(getSupportFragmentManager(), "consent_dialog");
75+
});
7476

7577
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
7678
requestPermissions(new String[]{Manifest.permission.POST_NOTIFICATIONS}, 1);
@@ -82,12 +84,15 @@ private void proceedToMainActivity() {
8284
finish();
8385
}
8486

85-
private void updateFirebaseConsent(boolean granted) {
87+
private void updateFirebaseConsent(boolean analytics,
88+
boolean adStorage,
89+
boolean adUserData,
90+
boolean adPersonalization) {
8691
Map<FirebaseAnalytics.ConsentType, FirebaseAnalytics.ConsentStatus> consentMap = new EnumMap<>(FirebaseAnalytics.ConsentType.class);
87-
consentMap.put(FirebaseAnalytics.ConsentType.ANALYTICS_STORAGE, granted ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED);
88-
consentMap.put(FirebaseAnalytics.ConsentType.AD_STORAGE, granted ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED);
89-
consentMap.put(FirebaseAnalytics.ConsentType.AD_USER_DATA, granted ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED);
90-
consentMap.put(FirebaseAnalytics.ConsentType.AD_PERSONALIZATION, granted ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED);
92+
consentMap.put(FirebaseAnalytics.ConsentType.ANALYTICS_STORAGE, analytics ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED);
93+
consentMap.put(FirebaseAnalytics.ConsentType.AD_STORAGE, adStorage ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED);
94+
consentMap.put(FirebaseAnalytics.ConsentType.AD_USER_DATA, adUserData ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED);
95+
consentMap.put(FirebaseAnalytics.ConsentType.AD_PERSONALIZATION, adPersonalization ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED);
9196

9297
FirebaseAnalytics.getInstance(this).setConsent(consentMap);
9398
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.d4rk.androidtutorials.java.ui.screens.startup.dialogs;
2+
3+
import android.app.Dialog;
4+
import android.os.Bundle;
5+
import android.view.LayoutInflater;
6+
7+
import androidx.annotation.NonNull;
8+
import androidx.annotation.Nullable;
9+
import androidx.fragment.app.DialogFragment;
10+
11+
import com.d4rk.androidtutorials.java.BuildConfig;
12+
import com.d4rk.androidtutorials.java.R;
13+
import com.d4rk.androidtutorials.java.databinding.DialogConsentBinding;
14+
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
15+
16+
public class ConsentDialogFragment extends DialogFragment {
17+
18+
public interface ConsentListener {
19+
void onConsentSet(boolean analytics, boolean adStorage, boolean adUserData, boolean adPersonalization);
20+
}
21+
22+
private ConsentListener listener;
23+
24+
public void setConsentListener(ConsentListener listener) {
25+
this.listener = listener;
26+
}
27+
28+
@NonNull
29+
@Override
30+
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
31+
DialogConsentBinding binding = DialogConsentBinding.inflate(LayoutInflater.from(requireContext()));
32+
33+
boolean defaultChecked = !BuildConfig.DEBUG;
34+
binding.checkAnalyticsStorage.setChecked(defaultChecked);
35+
binding.checkAdStorage.setChecked(defaultChecked);
36+
binding.checkAdUserData.setChecked(defaultChecked);
37+
binding.checkAdPersonalization.setChecked(defaultChecked);
38+
39+
setCancelable(false);
40+
41+
return new MaterialAlertDialogBuilder(requireContext())
42+
.setTitle(R.string.consent_dialog_title)
43+
.setView(binding.getRoot())
44+
.setCancelable(false)
45+
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
46+
if (listener != null) {
47+
listener.onConsentSet(
48+
binding.checkAnalyticsStorage.isChecked(),
49+
binding.checkAdStorage.isChecked(),
50+
binding.checkAdUserData.isChecked(),
51+
binding.checkAdPersonalization.isChecked()
52+
);
53+
}
54+
})
55+
.create();
56+
}
57+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
android:layout_width="match_parent"
5+
android:layout_height="wrap_content"
6+
android:padding="24dp">
7+
8+
<com.google.android.material.checkbox.MaterialCheckBox
9+
android:id="@+id/check_analytics_storage"
10+
android:layout_width="wrap_content"
11+
android:layout_height="wrap_content"
12+
android:text="@string/analytics_storage"
13+
app:layout_constraintStart_toStartOf="parent"
14+
app:layout_constraintTop_toTopOf="parent" />
15+
16+
<com.google.android.material.checkbox.MaterialCheckBox
17+
android:id="@+id/check_ad_storage"
18+
android:layout_width="wrap_content"
19+
android:layout_height="wrap_content"
20+
android:text="@string/ad_storage"
21+
app:layout_constraintStart_toStartOf="parent"
22+
app:layout_constraintTop_toBottomOf="@id/check_analytics_storage" />
23+
24+
<com.google.android.material.checkbox.MaterialCheckBox
25+
android:id="@+id/check_ad_user_data"
26+
android:layout_width="wrap_content"
27+
android:layout_height="wrap_content"
28+
android:text="@string/ad_user_data"
29+
app:layout_constraintStart_toStartOf="parent"
30+
app:layout_constraintTop_toBottomOf="@id/check_ad_storage" />
31+
32+
<com.google.android.material.checkbox.MaterialCheckBox
33+
android:id="@+id/check_ad_personalization"
34+
android:layout_width="wrap_content"
35+
android:layout_height="wrap_content"
36+
android:text="@string/ad_personalization"
37+
app:layout_constraintStart_toStartOf="parent"
38+
app:layout_constraintTop_toBottomOf="@id/check_ad_user_data" />
39+
40+
</androidx.constraintlayout.widget.ConstraintLayout>

app/src/main/res/values/strings.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,4 +391,9 @@
391391
<string name="error_loading_layout">Error loading layout</string>
392392
<string name="error_loading_code">Error loading code</string>
393393
<string name="snack_general_error">An error occurred while checking for updates</string>
394+
<string name="consent_dialog_title">Data &amp; Ads Consent</string>
395+
<string name="analytics_storage">Analytics storage</string>
396+
<string name="ad_storage">Ad storage</string>
397+
<string name="ad_user_data">Ad user data</string>
398+
<string name="ad_personalization">Ad personalization</string>
394399
</resources>

0 commit comments

Comments
 (0)