Repository navigation
Description
Problem Description
In Pigeon's Native Interop generators (useJni: true for Kotlin and useFfi: true for Swift), @HostApi registrations are stored in a process-wide static map keyed only by the instance name (defaultInstanceName by default):
-
Kotlin (
kotlin_generator.dart):
val Instances: MutableMap<String, Registrar> = mutableMapOf() -
Swift (
swift_generator.dart):
static var registered = String:
Unlike platform channels (where <Api>.setUp(binaryMessenger, api) scopes registration to a specific engine's BinaryMessenger), JNI/FFI registrars are process-wide. This causes two problems when multiple FlutterEngine instances run in the same OS process (e.g., background isolates/engines spawned by WorkManager, firebase_messaging, or add-to-app setups):
-
Detaching one engine unregisters the API for all remaining engines:
When a secondFlutterEnginestarts,GeneratedPluginRegistrantinstantiates a second plugin instance and callsonAttachedToEngine, which calls<Api>Registrar().register(this, name)and overwrites the first engine's registration undername. When that secondFlutterEnginefinishes and detaches,onDetachedFromEnginecalls<Api>Registrar().register(null, name), removingnamefrom<Api>Instancesaltogether and breaking subsequent calls from the still-running primary engine (e.g., [shared_preferences_android] Detaching a background engine unregisters the API used by the main engine #194920 / [shared_preferences_android] Keep API registration when another engine detaches packages#13359). -
Plugins with per-engine state overwrite each other:
If a plugin holds per-engine or per-activity state (such asActivityfromActivityAware,TextureRegistry,PlatformViewRegistry, orFlutterAssets), a second headless/backgroundFlutterEngineattaching will overwrite the UI engine's registered<Api>instance in<Api>Instances[name]with an instance that has different (ornull) per-engine state.
Blocked On / Dependencies
To properly scope @HostApi registrations to a specific FlutterEngine instance over JNI/FFI:
- Dart side:
PlatformDispatcher.instance.engineIdis already publicly available viadart:ui(added in Add PlatformDispatcher.engineId #163476). - Native side: The native plugin bindings/registrars (
FlutterPluginBindingon Android,FlutterPluginRegistraron iOS/macOS/Linux/Windows) do not yet publicly expose a non-deprecatedengineIdgetter.
Proposed Solution
1. Short-term (Documentation & Migration Guidance)
Until #195876 is resolved and rolls to stable:
- Update Pigeon's Native Interop documentation and migration guidance (
skills/native-interop-migration/SKILL.md) to clarify that<Api>Registraris currently process-wide, not per-engine. - For plugins whose native implementation only depends on process-wide state (such as Android's
binding.applicationContextor iOS/macOSUserDefaults), document that plugins should not unregister (register(null)) the process-wide singleton when an individual engine detaches inonDetachedFromEngine. - Warn against migrating
@HostApiimplementations that depend on per-engine state (ActivityAware,TextureRegistry,PlatformViewRegistry) away fromBinaryMessengeruntil per-engine native interop registration is supported.
2. Long-term (Engine-Scoped Registration via engineId)
Once engineId is publicly exposed on native plugin bindings/registrars (#195876):
- Update
<Api>Registrar(Kotlin JNI and Swift FFI) to support keying registrations by(engineId, name)in addition to process-widenamefallback. - When registering/unregistering from
onAttachedToEngine/onDetachedFromEngine(orregisterWithRegistrar:), associate the registration with the binding'sengineIdso detaching an engine only removes that engine's registration. - Update Dart's generated
createWithNativeInteropApi()to passPlatformDispatcher.instance.engineIdwhen looking up the host API instance viagetInstance.
Activity
puneetkukreja98 commentedon Nov 3, 2026
@tarrinneal Thanks for reporting this, routing this to team-ecosystem for further investigation.
Update native interop overview and mark Pigeon native interop as prev…
[pigeon] Fix standalone Native Interop @FlutterApi issues (#13609)
[pigeon] Support multi-engine Native Interop registration and instanc…