Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ android {
vectorDrawables.useSupportLibrary = true
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
resourceConfigurations += ['en', 'de', 'es', 'fr', 'hi', 'hu', 'in', 'it', 'ja', 'ro', 'ru', 'tr', 'sv', 'bg', 'pl', 'uk']
manifestPlaceholders = [
analyticsStorage: true,
adStorage: true,
adUserData: true,
adPersonalization: true
]
}

buildTypes {
Expand All @@ -27,11 +33,23 @@ android {
shrinkResources true
debuggable false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
manifestPlaceholders = [
analyticsStorage: true,
adStorage: true,
adUserData: true,
adPersonalization: true
]
}
debug {
multiDexEnabled true
debuggable true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
manifestPlaceholders = [
analyticsStorage: false,
adStorage: false,
adUserData: false,
adPersonalization: false
]
}
}

Expand Down
8 changes: 4 additions & 4 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -332,9 +332,9 @@
android:name="com.google.android.gms.ads.AD_MANAGER_APP"
android:value="true" />

<meta-data android:name="google_analytics_default_allow_analytics_storage" android:value="false" />
<meta-data android:name="google_analytics_default_allow_ad_storage" android:value="false" />
<meta-data android:name="google_analytics_default_allow_ad_user_data" android:value="false" />
<meta-data android:name="google_analytics_default_allow_ad_personalization_signals" android:value="false" />
<meta-data android:name="google_analytics_default_allow_analytics_storage" android:value="${analyticsStorage}" />
<meta-data android:name="google_analytics_default_allow_ad_storage" android:value="${adStorage}" />
<meta-data android:name="google_analytics_default_allow_ad_user_data" android:value="${adUserData}" />
<meta-data android:name="google_analytics_default_allow_ad_personalization_signals" android:value="${adPersonalization}" />
</application>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.d4rk.androidtutorials.java.notifications.managers.AppUsageNotificationsManager;
import com.d4rk.androidtutorials.java.ui.components.navigation.BottomSheetMenuFragment;
import com.d4rk.androidtutorials.java.ui.screens.startup.StartupActivity;
import com.d4rk.androidtutorials.java.ui.screens.startup.StartupViewModel;
import com.d4rk.androidtutorials.java.ui.screens.support.SupportActivity;
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeDelegate;
import com.google.android.gms.ads.AdRequest;
Expand All @@ -47,6 +48,9 @@
import com.google.android.play.core.install.model.AppUpdateType;
import com.google.android.play.core.install.model.InstallStatus;
import com.google.android.play.core.install.model.UpdateAvailability;
import com.google.android.ump.ConsentInformation;
import com.google.android.ump.ConsentRequestParameters;
import com.google.android.ump.UserMessagingPlatform;

public class MainActivity extends AppCompatActivity {

Expand All @@ -61,6 +65,8 @@ public class MainActivity extends AppCompatActivity {
);
private ActivityMainBinding mBinding;
private MainViewModel mainViewModel;
private StartupViewModel startupViewModel;
private ConsentInformation consentInformation;
private NavController navController;
private AppUpdateNotificationsManager appUpdateNotificationsManager;
private AppUpdateManager appUpdateManager;
Expand All @@ -74,6 +80,21 @@ protected void onCreate(Bundle savedInstanceState) {
setContentView(mBinding.getRoot());

mainViewModel = new ViewModelProvider(this).get(MainViewModel.class);
startupViewModel = new ViewModelProvider(this).get(StartupViewModel.class);
consentInformation = UserMessagingPlatform.getConsentInformation(this);
ConsentRequestParameters params = new ConsentRequestParameters.Builder()
.setTagForUnderAgeOfConsent(false)
.build();
startupViewModel.requestConsentInfoUpdate(
this,
params,
() -> {
if (consentInformation.isConsentFormAvailable()) {
startupViewModel.loadConsentForm(this, null);
}
},
null
);

setupActionBar();
observeViewModel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.google.android.ump.ConsentRequestParameters;
import com.google.android.ump.UserMessagingPlatform;
import com.google.firebase.analytics.FirebaseAnalytics;
import com.d4rk.androidtutorials.java.ui.screens.startup.dialogs.ConsentDialogFragment;

import java.util.EnumMap;
import java.util.Map;
Expand All @@ -39,26 +40,20 @@ protected void onCreate(Bundle savedInstanceState) {
.setTagForUnderAgeOfConsent(false)
.build();

consentInformation.requestConsentInfoUpdate(
startupViewModel.requestConsentInfoUpdate(
this,
params,
() -> {
if (consentInformation.isConsentFormAvailable()) {
startupViewModel.loadConsentForm(
this,
formError -> {
updateFirebaseConsent(false);
proceedToMainActivity();
}
formError -> updateFirebaseConsent(false, false, false, false)
);
} else {
if (consentInformation.getConsentStatus() == ConsentInformation.ConsentStatus.OBTAINED) {
updateFirebaseConsent(true);
}
proceedToMainActivity();
} else if (consentInformation.getConsentStatus() == ConsentInformation.ConsentStatus.OBTAINED) {
updateFirebaseConsent(true, true, true, true);
}
},
formError -> proceedToMainActivity()
formError -> {}
);

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

binding.floatingButtonAgree.setOnClickListener(v -> proceedToMainActivity());
binding.floatingButtonAgree.setOnClickListener(v -> {
ConsentDialogFragment dialog = new ConsentDialogFragment();
dialog.setConsentListener((analytics, adStorage, adUserData, adPersonalization) -> {
updateFirebaseConsent(analytics, adStorage, adUserData, adPersonalization);
proceedToMainActivity();
});
dialog.show(getSupportFragmentManager(), "consent_dialog");
});

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

private void updateFirebaseConsent(boolean granted) {
private void updateFirebaseConsent(boolean analytics,
boolean adStorage,
boolean adUserData,
boolean adPersonalization) {
Map<FirebaseAnalytics.ConsentType, FirebaseAnalytics.ConsentStatus> consentMap = new EnumMap<>(FirebaseAnalytics.ConsentType.class);
consentMap.put(FirebaseAnalytics.ConsentType.ANALYTICS_STORAGE, granted ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED);
consentMap.put(FirebaseAnalytics.ConsentType.AD_STORAGE, granted ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED);
consentMap.put(FirebaseAnalytics.ConsentType.AD_USER_DATA, granted ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED);
consentMap.put(FirebaseAnalytics.ConsentType.AD_PERSONALIZATION, granted ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED);
consentMap.put(FirebaseAnalytics.ConsentType.ANALYTICS_STORAGE, analytics ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED);
consentMap.put(FirebaseAnalytics.ConsentType.AD_STORAGE, adStorage ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED);
consentMap.put(FirebaseAnalytics.ConsentType.AD_USER_DATA, adUserData ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED);
consentMap.put(FirebaseAnalytics.ConsentType.AD_PERSONALIZATION, adPersonalization ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED);

FirebaseAnalytics.getInstance(this).setConsent(consentMap);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.d4rk.androidtutorials.java.ui.screens.startup.dialogs;

import android.app.Dialog;
import android.os.Bundle;
import android.view.LayoutInflater;

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

import com.d4rk.androidtutorials.java.BuildConfig;
import com.d4rk.androidtutorials.java.R;
import com.d4rk.androidtutorials.java.databinding.DialogConsentBinding;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;

public class ConsentDialogFragment extends DialogFragment {

public interface ConsentListener {
void onConsentSet(boolean analytics, boolean adStorage, boolean adUserData, boolean adPersonalization);
}

private ConsentListener listener;

public void setConsentListener(ConsentListener listener) {
this.listener = listener;
}

@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
DialogConsentBinding binding = DialogConsentBinding.inflate(LayoutInflater.from(requireContext()));

boolean defaultChecked = !BuildConfig.DEBUG;
binding.checkAnalyticsStorage.setChecked(defaultChecked);
binding.checkAdStorage.setChecked(defaultChecked);
binding.checkAdUserData.setChecked(defaultChecked);
binding.checkAdPersonalization.setChecked(defaultChecked);

setCancelable(false);

return new MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.consent_dialog_title)
.setView(binding.getRoot())
.setCancelable(false)
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
if (listener != null) {
listener.onConsentSet(
binding.checkAnalyticsStorage.isChecked(),
binding.checkAdStorage.isChecked(),
binding.checkAdUserData.isChecked(),
binding.checkAdPersonalization.isChecked()
);
}
})
.create();
}
}
40 changes: 40 additions & 0 deletions app/src/main/res/layout/dialog_consent.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content"
android:padding="24dp">

<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/check_analytics_storage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/analytics_storage"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/check_ad_storage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ad_storage"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/check_analytics_storage" />

<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/check_ad_user_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ad_user_data"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/check_ad_storage" />

<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/check_ad_personalization"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ad_personalization"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/check_ad_user_data" />

</androidx.constraintlayout.widget.ConstraintLayout>
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 @@ -391,4 +391,9 @@
<string name="error_loading_layout">Error loading layout</string>
<string name="error_loading_code">Error loading code</string>
<string name="snack_general_error">An error occurred while checking for updates</string>
<string name="consent_dialog_title">Data &amp; Ads Consent</string>
<string name="analytics_storage">Analytics storage</string>
<string name="ad_storage">Ad storage</string>
<string name="ad_user_data">Ad user data</string>
<string name="ad_personalization">Ad personalization</string>
</resources>