initialize method
Implementation
Future<void> initialize(DigiaConfig config) async {
if (_initialized) {
debugPrint('[Digia] initialize() called more than once — ignored.');
return;
}
_config = config;
_initialized = true;
_sdkState = SDKState.initializing;
// Apply the global font family to all Digia-rendered text (mirrors
// Android setting DigiaFontConfig.fontFamily at the top of init).
EngageFonts.fontFamily = config.fontFamily;
WidgetsBinding.instance.addObserver(this);
// Construct the guide manager now so it registers the showcase controller
// and listens to the orchestrator before any campaign is routed.
_guideManager;
// The whole init runs under one guard (mirrors Android's DigiaInstance):
// any failure leaves the SDK in [SDKState.failed] and resets the
// started flag so a later call can retry.
try {
// Resolve the engage API host from the config (explicit `baseUrl` wins,
// else derived from `environment`) before ANY network call is made —
// campaign fetch, analytics track, and session reporting all read the
// URLs from [DigiaEndpoints]. Mirrors Android's endpoint configuration.
DigiaEndpoints.configure(config);
// Register the host's action override (if any) on the shared runner.
EngageActionRunner.shared.interceptor = config.onAction;
// ── Resolve base URL (sandbox → dev.digia.tech, prod → app.digia.tech) ─
DigiaEndpoints.configure(config);
// ── Fetch + cache engage campaigns ──────────────────────────────────
await PreferencesStore.instance.initialize();
// Resolve the shared session (reused across a relaunch within the timeout)
// before anything reads it — both analytics event grouping and frequency's
// session-scoped caps depend on it.
await SessionManager.instance
.initialize(config.analyticsConfig.sessionTimeoutMs);
await DigiaAnalyticsService.instance
.initialize(config.analyticsConfig, config.apiKey);
_wireSessionReporting(config);
final deviceId = EngageSettings.instance.getUuid();
_submissionReporter = SubmissionReporter(config, deviceId);
final campaigns = await CampaignFetcher(config, deviceId).fetch();
_campaignStore.populate(campaigns);
// ── Ready ───────────────────────────────────────────────────────────
_sdkState = SDKState.ready;
if (_campaignStore.isEmpty) {
debugPrint('[Digia] No campaigns fetched — CampaignStore is empty.');
} else {
_logIfVerbose('Fetched ${campaigns.length} campaign(s).');
}
_flushPendingPayloadIfAny();
_logIfVerbose('Digia initialized with apiKey=${config.apiKey}, '
'environment=${config.environment.name}.');
} catch (e) {
_initialized = false;
_sdkState = SDKState.failed;
debugPrint('[Digia] initialize failed: $e');
// A template presented during init left a CEP slot held (we returned
// `true` from onCampaignTriggered). Init failed so it will never route —
// release the slot, else later in-apps queue forever.
final pending = _pendingPayload;
_pendingPayload = null;
if (pending != null) {
_events.toCep(const ExperienceDismissed(), pending);
}
}
}