Skip to content

[FSSDK-12503] fix: guard static MethodChannel from multi-engine overwrite#103

Open
muzahidul-opti wants to merge 5 commits intomasterfrom
fix/multi-engine-channel
Open

[FSSDK-12503] fix: guard static MethodChannel from multi-engine overwrite#103
muzahidul-opti wants to merge 5 commits intomasterfrom
fix/multi-engine-channel

Conversation

@muzahidul-opti
Copy link
Copy Markdown
Contributor

Summary

  • Fix notification listeners silently breaking when onAttachedToEngine (Android) / register(with:) (iOS) is called more than once
  • Root cause: static MethodChannel was unconditionally overwritten by a second Flutter engine (e.g. Firebase background messaging), causing notification callbacks to route to the wrong engine
  • Fix: guard the channel assignment with a null check; null the channel in onDetachedFromEngine for proper lifecycle

Changes

  • Android OptimizelyFlutterSdkPlugin.java: Early return in onAttachedToEngine if channel already set; set channel = null in onDetachedFromEngine
  • Android FlutterLogbackAppender.java: Guard setChannel() from overwriting active channel
  • iOS SwiftOptimizelyFlutterSdkPlugin.swift: Early return in register(with:) if channel already set
  • iOS OptimizelyFlutterLogger.swift: Guard setChannel() from overwriting active channel

Test plan

  • Run existing Dart unit tests (flutter test) - 140/140 passed, no regressions
  • Run flutter analyze - no issues found
  • Run multi-engine integration test on Android emulator (see flutter-testapp PR)
  • Verify decision notification listener fires after second engine creation
  • Verify track notification listener fires after second engine creation
  • Verify SDK still works normally in single-engine scenario

Fixes FSSDK-12503

🤖 Generated with Claude Code

muzahidul-opti and others added 5 commits April 28, 2026 19:06
When FirebaseMessaging.onBackgroundMessage (or any mechanism that creates
a second FlutterEngine) triggers onAttachedToEngine a second time, the
static channel was unconditionally overwritten. This caused notification
callbacks to route to the wrong engine, silently dropping them.

The fix adds an early return if channel is already set, and nulls the
channel in onDetachedFromEngine so re-attachment works after a real
detach.

Fixes FSSDK-12503

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Same root cause as the main channel fix — the static logger channel
could be overwritten by a second FlutterEngine. The setChannel guard
allows explicit null (cleanup) but prevents overwrite of an active
channel.

Fixes FSSDK-12503

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Same vulnerability as Android — if register(with:) were called twice
(e.g. by a second FlutterEngine), the static channel would be
overwritten. The fix adds an early return if channel is already set.

Fixes FSSDK-12503

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Same pattern as the Android logger fix — prevents a second engine
from overwriting the active logger channel.

Fixes FSSDK-12503

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…annels

Replace the compound null-guard logic with explicit setChannel (only sets
if no active channel) and clearChannel (always clears). This matches the
main plugin's pattern and makes intent immediately obvious.

Callers updated: onDetachedFromEngine now calls clearChannel() instead
of setChannel(null).

Fixes FSSDK-12503

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@muzahidul-opti muzahidul-opti requested a review from jaeopt April 28, 2026 13:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant