Is there an existing issue for this?
Which plugins are affected?
App Installations
Which platforms are affected?
Android
Description
On a fresh install, firebase_app_installations calls EventSink.success() from a Firebase background thread, causing a main-thread exception at TokenChannelStreamHandler.kt:25.
Reproduced in debug and release with the attached minimal project, which uses only Firebase Core and Installations.
Expected: ID-change events are delivered without a thread exception.
Environment: Samsung SM-S936N / Android 16; Dart 3.13.2; AGP 9.1.0 / Gradle 9.3.1.
Disclaimer: This issue report was written by GPT-6 Astra.
Reproducing the issue
- Register a Firebase Android app for
dev.example.installations_thread_mrp.
- Create
.local/firebase.json from config/firebase.example.json and fill in your Firebase configuration.
- Uninstall any previous copy of the MRP, then run:
fvm flutter run --debug --dart-define-from-file=.local/firebase.json
The app subscribes to onIdChange and calls getId() followed by getToken() immediately after Firebase initialization. Leave it untouched and inspect adb logcat: getId() completes, then the native exception occurs.
Core sequence from the MRP (UI and logging omitted; firebaseOptions contains your Firebase app configuration):
await Firebase.initializeApp(options: firebaseOptions);
final installations = FirebaseInstallations.instance;
_subscription = installations.onIdChange.listen((_) {});
// No delay after initialization.
await installations.getId();
await installations.getToken();
flutterfire-installations-mrp.zip
Firebase Core version
4.14.0
Flutter Version
3.47.2
Relevant Log Output
java.lang.RuntimeException: Methods marked with @UiThread must be executed on the main thread. Current thread: Firebase Blocking Thread #0
at io.flutter.embedding.engine.FlutterJNI.ensureRunningOnMainThread(FlutterJNI.java:1695)
at io.flutter.embedding.engine.FlutterJNI.dispatchPlatformMessage(FlutterJNI.java:1177)
at io.flutter.embedding.engine.dart.DartMessenger.send(DartMessenger.java:275)
at io.flutter.embedding.engine.dart.DartExecutor$DefaultBinaryMessenger.send(DartExecutor.java:457)
at io.flutter.embedding.engine.dart.DartExecutor.send(DartExecutor.java:217)
at io.flutter.plugin.common.EventChannel$IncomingStreamRequestHandler$EventSinkImplementation.success(EventChannel.java:251)
at io.flutter.plugins.firebase.installations.firebase_app_installations.TokenChannelStreamHandler.createTokenEventListener$lambda$0(TokenChannelStreamHandler.kt:25)
at io.flutter.plugins.firebase.installations.firebase_app_installations.TokenChannelStreamHandler$$ExternalSyntheticLambda0.onFidChanged(D8$$SyntheticClass:0)
at com.google.firebase.installations.FirebaseInstallations.checkAndUpdateFidListeners(FirebaseInstallations.java:454)
at com.google.firebase.installations.FirebaseInstallations.doNetworkCallIfNecessary(FirebaseInstallations.java:413)
at com.google.firebase.installations.FirebaseInstallations.lambda$doRegistrationOrRefresh$3$com-google-firebase-installations-FirebaseInstallations(FirebaseInstallations.java:382)
at com.google.firebase.installations.FirebaseInstallations$$ExternalSyntheticLambda1.run(D8$$SyntheticClass:0)
at com.google.firebase.concurrent.SequentialExecutor$1.run(SequentialExecutor.java:117)
at com.google.firebase.concurrent.SequentialExecutor$QueueWorker.workOnQueue(SequentialExecutor.java:229)
at com.google.firebase.concurrent.SequentialExecutor$QueueWorker.run(SequentialExecutor.java:174)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1100)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at com.google.firebase.concurrent.CustomThreadFactory.lambda$newThread$0$com-google-firebase-concurrent-CustomThreadFactory(CustomThreadFactory.java:47)
at com.google.firebase.concurrent.CustomThreadFactory$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
at java.lang.Thread.run(Thread.java:1572)
Flutter dependencies
Dependency versions
firebase_core: 4.14.0
firebase_app_installations: 0.4.3
firebase_core_platform_interface: 8.1.1
firebase_app_installations_platform_interface: 0.1.5
_flutterfire_internals: 1.3.77
The complete pubspec.lock is included in the project ZIP.
Additional context and comments
Suggested fix
Dispatch the event on the main looper:
return FidListener { token ->
Handler(Looper.getMainLooper()).post {
events.success(mapOf("token" to token))
}
}
This change resolved the exception in the original application's release build.
Is there an existing issue for this?
Which plugins are affected?
App Installations
Which platforms are affected?
Android
Description
On a fresh install,
firebase_app_installationscallsEventSink.success()from a Firebase background thread, causing a main-thread exception atTokenChannelStreamHandler.kt:25.Reproduced in debug and release with the attached minimal project, which uses only Firebase Core and Installations.
Expected: ID-change events are delivered without a thread exception.
Environment: Samsung SM-S936N / Android 16; Dart 3.13.2; AGP 9.1.0 / Gradle 9.3.1.
Disclaimer: This issue report was written by GPT-6 Astra.
Reproducing the issue
dev.example.installations_thread_mrp..local/firebase.jsonfromconfig/firebase.example.jsonand fill in your Firebase configuration.The app subscribes to
onIdChangeand callsgetId()followed bygetToken()immediately after Firebase initialization. Leave it untouched and inspectadb logcat:getId()completes, then the native exception occurs.Core sequence from the MRP (UI and logging omitted;
firebaseOptionscontains your Firebase app configuration):flutterfire-installations-mrp.zip
Firebase Core version
4.14.0
Flutter Version
3.47.2
Relevant Log Output
Flutter dependencies
Dependency versions
The complete pubspec.lock is included in the project ZIP.
Additional context and comments
Suggested fix
Dispatch the event on the main looper:
This change resolved the exception in the original application's release build.