Skip to content

Commit dd0a05f

Browse files
Merge pull request #495 from appdevforall/chore/ADFA-5337-build-without-google-services
ADFA-5337 chore(build): build without google-services.json (conditional Firebase + analytics off)
2 parents d3211ee + b88112c commit dd0a05f

7 files changed

Lines changed: 67 additions & 16 deletions

File tree

‎controller/app/build.gradle‎

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
plugins {
22
id 'com.android.application'
3-
// ADFA-4466 Phase 1: Firebase Analytics.
4-
id 'com.google.gms.google-services'
3+
// ADFA-4466 Phase 1: Firebase Analytics. The google-services plugin fails the build when
4+
// google-services.json is absent, so it is applied CONDITIONALLY at the bottom of this file
5+
// (present -> Firebase on; absent -> AnalyticsClient compiles out and the build still works).
56
}
67

78
// 1. AUTO-VERSIONING MAP (Must be defined outside the 'android' block)
@@ -24,6 +25,12 @@ def gitShortSha = {
2425
}
2526
ext.gitSha = gitShortSha()
2627

28+
// Firebase is OPTIONAL for local/contributor builds. google-services.json holds the real project keys
29+
// and is gitignored, so a fresh clone doesn't have it. When it's absent we skip the google-services
30+
// plugin (which would otherwise fail the build) and flag AnalyticsClient off via BuildConfig so it never
31+
// touches the uninitialized Firebase SDK. Set the file to enable analytics for a release build.
32+
def hasGoogleServices = file("google-services.json").exists()
33+
2734
android {
2835
// 2. Identity
2936
namespace 'org.iiab.controller'
@@ -45,6 +52,8 @@ android {
4552
: (project.ext.gitSha ? "-${project.ext.gitSha}" : "")
4653
versionName "v0.7.0-beta${ciSuffix}"
4754
buildConfigField "String", "GIT_SHA", "\"${project.ext.gitSha}\""
55+
// True only when google-services.json is present, so AnalyticsClient can compile out cleanly.
56+
buildConfigField "boolean", "ANALYTICS_ENABLED", "${hasGoogleServices}"
4857

4958
setProperty("archivesBaseName", "$applicationId-$versionName")
5059

@@ -753,3 +762,14 @@ task refreshKolibriCatalog {
753762
}
754763
}
755764
}
765+
766+
// ADFA-4466 / build resilience: apply the Firebase google-services plugin only when its config file is
767+
// present. Without it the plugin fails the build; skipping it lets contributors build a working APK with
768+
// analytics compiled out (BuildConfig.ANALYTICS_ENABLED = false). Applied at the bottom, as the plugin
769+
// expects, so it processes the already-configured android block.
770+
if (hasGoogleServices) {
771+
apply plugin: 'com.google.gms.google-services'
772+
logger.lifecycle("K2Go: google-services.json found — Firebase Analytics enabled.")
773+
} else {
774+
logger.lifecycle("K2Go: google-services.json not found — building WITHOUT Firebase (analytics disabled).")
775+
}

‎controller/app/src/main/java/org/iiab/controller/SetupSectionFragment.java‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ private void persistSelectedLanguage() {
206206
* the consent and proceeds. Shown at most once (guarded by a flag).
207207
*/
208208
private void maybeShowAnalyticsEnrollment() {
209+
// ADFA-5337: no analytics compiled in (no google-services.json) → nothing to consent to; skip.
210+
if (!BuildConfig.ANALYTICS_ENABLED) {
211+
completeSetup();
212+
return;
213+
}
209214
SharedPreferences delivery = requireContext().getSharedPreferences(
210215
DELIVERY_PREFS, Context.MODE_PRIVATE);
211216
if (delivery.getBoolean(KEY_ENROLLMENT_SHOWN, false)) {

‎controller/app/src/main/java/org/iiab/controller/analytics/AnalyticsClient.java‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import com.google.firebase.analytics.FirebaseAnalytics;
88

9+
import org.iiab.controller.BuildConfig;
910
import org.iiab.controller.analytics.domain.AnalyticsBuckets;
1011
import org.iiab.controller.delivery.data.AnalyticsConsent;
1112
import org.iiab.controller.delivery.data.InstallId;
@@ -48,6 +49,9 @@ public static AnalyticsClient with(Context ctx) {
4849
* anywhere (e.g. Application start, or right after the consent toggle changes).
4950
*/
5051
public void applyConsent() {
52+
if (!BuildConfig.ANALYTICS_ENABLED) {
53+
return; // built without google-services.json → Firebase not configured; nothing to sync
54+
}
5155
FirebaseAnalytics.getInstance(app).setAnalyticsCollectionEnabled(AnalyticsConsent.isEnabled(app));
5256
}
5357

@@ -179,8 +183,13 @@ public void logModuleInstall(String module, boolean success) {
179183

180184
// ------------------------------------------------------------------- internals
181185

182-
/** True only when the operator opted in; also keeps the SDK flag in sync. */
186+
/** True only when the operator opted in AND Firebase is configured in this build; also keeps the SDK
187+
* flag in sync. When built without google-services.json, this short-circuits so no code path ever
188+
* touches the uninitialized Firebase SDK (every public logging method gates through here). */
183189
private boolean gate() {
190+
if (!BuildConfig.ANALYTICS_ENABLED) {
191+
return false; // no google-services.json → analytics compiled out
192+
}
184193
boolean consent = AnalyticsConsent.isEnabled(app);
185194
FirebaseAnalytics.getInstance(app).setAnalyticsCollectionEnabled(consent);
186195
return consent;

‎controller/app/src/main/java/org/iiab/controller/redesign/SettingsSubFragment.java‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,14 @@ private void buildAbout(Context ctx, LinearLayout list) {
190190
}
191191
});
192192
SettingsUi.row(ctx, list, getString(R.string.k2go_settings_permissions), null, null, v -> openAppSettings(ctx));
193-
SettingsUi.toggle(ctx, list, getString(R.string.k2go_settings_usage_stats), AnalyticsConsent.isEnabled(ctx), checked -> {
194-
AnalyticsConsent.setEnabled(ctx, checked);
195-
org.iiab.controller.analytics.AnalyticsClient.with(ctx).applyConsent();
196-
});
193+
// ADFA-5337: hide the usage-statistics toggle when analytics is compiled out (no
194+
// google-services.json), since there's nothing to share and the switch would do nothing.
195+
if (org.iiab.controller.BuildConfig.ANALYTICS_ENABLED) {
196+
SettingsUi.toggle(ctx, list, getString(R.string.k2go_settings_usage_stats), AnalyticsConsent.isEnabled(ctx), checked -> {
197+
AnalyticsConsent.setEnabled(ctx, checked);
198+
org.iiab.controller.analytics.AnalyticsClient.with(ctx).applyConsent();
199+
});
200+
}
197201
SettingsUi.preview(ctx, list, getString(R.string.k2go_settings_licenses), null);
198202
SettingsUi.preview(ctx, list, getString(R.string.k2go_settings_privacy), null);
199203
}

‎controller/app/src/main/java/org/iiab/controller/redesign/WizardActivity.java‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ private void onPrimary() {
198198
/** One-time usage-stats consent prompt; runs {@code onDone} after the choice (or immediately
199199
* if already asked here or in the legacy flow). Reuses the analytics_enroll_* strings. */
200200
private void maybeAskAnalytics(Runnable onDone) {
201+
// ADFA-5337: no analytics compiled in (no google-services.json) → nothing to consent to; skip.
202+
if (!org.iiab.controller.BuildConfig.ANALYTICS_ENABLED) { onDone.run(); return; }
201203
if (AnalyticsConsent.wasAsked(this)) { onDone.run(); return; }
202204
new MaterialAlertDialogBuilder(this)
203205
.setTitle(R.string.analytics_enroll_title)

‎controller/app/src/main/java/org/iiab/controller/settings/AboutFragment.java‎

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,22 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
3333
TextView versionView = view.findViewById(R.id.about_version);
3434
versionView.setText(getString(R.string.about_version, appVersionName()));
3535

36-
SwitchCompat analytics = view.findViewById(R.id.switch_analytics_consent);
37-
analytics.setChecked(AnalyticsConsent.isEnabled(requireContext()));
38-
analytics.setOnCheckedChangeListener(
39-
(btn, checked) -> {
40-
AnalyticsConsent.setEnabled(requireContext(), checked);
41-
org.iiab.controller.analytics.AnalyticsClient.with(requireContext()).applyConsent();
42-
});
36+
// ADFA-5337: no analytics compiled in (no google-services.json) → hide the whole opt-in block,
37+
// since there's nothing to share and the switch would do nothing.
38+
if (!org.iiab.controller.BuildConfig.ANALYTICS_ENABLED) {
39+
View row = view.findViewById(R.id.analytics_consent_row);
40+
View desc = view.findViewById(R.id.analytics_consent_desc);
41+
if (row != null) row.setVisibility(View.GONE);
42+
if (desc != null) desc.setVisibility(View.GONE);
43+
} else {
44+
SwitchCompat analytics = view.findViewById(R.id.switch_analytics_consent);
45+
analytics.setChecked(AnalyticsConsent.isEnabled(requireContext()));
46+
analytics.setOnCheckedChangeListener(
47+
(btn, checked) -> {
48+
AnalyticsConsent.setEnabled(requireContext(), checked);
49+
org.iiab.controller.analytics.AnalyticsClient.with(requireContext()).applyConsent();
50+
});
51+
}
4352
}
4453

4554
private String appVersionName() {

‎controller/app/src/main/res/layout/fragment_about.xml‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
<View android:layout_width="match_parent" android:layout_height="1dp"
2222
android:layout_marginTop="24dp" android:background="@color/chrome_ripple"/>
2323

24-
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"
24+
<LinearLayout android:id="@+id/analytics_consent_row"
25+
android:layout_width="match_parent" android:layout_height="wrap_content"
2526
android:orientation="horizontal" android:gravity="center_vertical"
2627
android:layout_marginTop="20dp">
2728
<TextView android:layout_width="0dp" android:layout_height="wrap_content"
@@ -32,7 +33,8 @@
3233
android:id="@+id/switch_analytics_consent"
3334
android:layout_width="wrap_content" android:layout_height="wrap_content"/>
3435
</LinearLayout>
35-
<TextView android:layout_width="match_parent" android:layout_height="wrap_content"
36+
<TextView android:id="@+id/analytics_consent_desc"
37+
android:layout_width="match_parent" android:layout_height="wrap_content"
3638
android:layout_marginTop="6dp"
3739
android:text="@string/settings_analytics_desc"
3840
android:textSize="13sp"/>

0 commit comments

Comments
 (0)