Skip to content

feat(firebase): tvOS support for firebase_crashlytics - #8

Merged
MAUstaoglu merged 4 commits into
fluttertv:mainfrom
TheNoumanDev:feat/firebase-crashlytics-tvos
Aug 18, 2026
Merged

feat(firebase): tvOS support for firebase_crashlytics#8
MAUstaoglu merged 4 commits into
fluttertv:mainfrom
TheNoumanDev:feat/firebase-crashlytics-tvos

Conversation

@TheNoumanDev

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds federated firebase_crashlytics_tvos — Firebase Crashlytics for Apple TV, built on the Firebase Apple SDK. Re-exports the firebase_crashlytics Dart API and ships the native tvOS pluginClass; depends on firebase_core_tvos. Full Crashlytics API, no feature disables.

Package(s) touched: firebase_crashlytics_tvos (new)

How was it tested?

Verified against a live Firebase project on both the tvOS simulator and a
physical Apple TV 4K (release/AOT): initializeApp(options:) succeeds, [Firebase/Crashlytics] 12.15.0 starts and fetches settings from …/platforms/tvos/gmp/<app-id>/settings, and a forced FirebaseCrashlytics.instance.crash() was captured and reported to the Crashlytics console on both (uploaded to crashlyticsreports-pa.googleapis.com, appeared as a crash issue). Platform.operatingSystem == "tvos" / Platform.isIOS == true.

  • Ran the package's example/ app
  • Verified on tvOS simulator (version: 26.2) — forced crash reached the Crashlytics console
  • Verified on a physical Apple TV 4K (tvOS 26.2, release/AOT) — forced crash reported to the console (dSYM symbolication is the usual app-side build config, same as iOS)
  • dart analyze is clean for the package

Versioning & changelog

  • version: set to 0.0.1 (new package)
  • Matching ## 0.0.1 entry at the top of CHANGELOG.md
  • No behaviour change (new package)
  • Semver 0.x: initial 0.0.1

Checklist

  • Only firebase_crashlytics_tvos files are touched
  • No secrets, absolute local paths, or TODO/debug leftovers
  • README.md documents tvOS behaviour (no feature limitations; version-alignment note)
  • Sibling-package constraint noted below

Notes for reviewers

  • Version alignment (affects all Firebase _tvos leaf packages): the native code matches firebase_crashlytics 5.2.4 on the firebase_core_platform_interface 7.1.0 train (firebase_core 4.11.x) — this is the latest Crashlytics on that train (5.2.7+ moves to firebase_core 4.13.0 / platform_interface 8.1.0, which the published firebase_core_tvos isn't built for).
  • Manual work beyond the auto-port: podspec deps (Firebase/Crashlytics + firebase_core_tvos, tvOS 15, LIBRARY_NAME defines); <firebase_core/…> imports repointed to <firebase_core_tvos/…>; Dart re-export.

@TheNoumanDev

Copy link
Copy Markdown
Contributor Author

Hey @MAUstaoglu @DenisovAV — this adds firebase_crashlytics_tvos . Would appreciate a review whenever you have time — thanks!

@TheNoumanDev
TheNoumanDev force-pushed the feat/firebase-crashlytics-tvos branch from 37b8a38 to 7ea73ea Compare August 17, 2026 00:15

@DenisovAV DenisovAV left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

The port itself is the most faithful of the set: FLTFirebaseCrashlyticsPlugin.m and all three headers are byte-identical to firebase_crashlytics 5.2.4 apart from repointing the core import at firebase_core_tvos. No stubs, no #if !TARGET_OS_TV, all ten handlers calling real FIRCrashlytics APIs. Podspec consistent with the siblings on mainFirebase/Crashlytics '~> 12.15.0', tvOS 15.0, no Flutter pod.

Two things to change, then I'd merge it.

1. Two files belonging to another PR

packages/firebase_analytics_tvos/example/tvos/Runner/GeneratedPluginRegistrant.h
packages/firebase_analytics_tvos/example/tvos/Runner/GeneratedPluginRegistrant.m

These are build output from #7's example app — they @import firebase_analytics_tvos and register FirebaseAnalyticsPlugin. Worth noting that #7 puts GeneratedPluginRegistrant in its own example/tvos/.gitignore and correctly does not commit them, so merging this would land in main exactly what that package's gitignore says should never be tracked. Your own package handles it right.

There is also an ordering hazard: merged before #7, this creates a packages/firebase_analytics_tvos/ directory containing nothing but those two files. The repo gate reports it as a package missing everything —

R3  firebase_analytics_tvos  pubspec.yaml is missing
R3  firebase_analytics_tvos  tvos/ ships no .podspec
… and three more

— which is the gate doing its job, but easier to just drop the files.

2. Two claims about Crashlytics on tvOS that the SDK does not support

README.md says "All firebase_crashlytics APIs are available (no tvOS feature disables)". True at the plugin's API surface; not true underneath it. From Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h at 12.15.0:

#define CLS_USE_SIGALTSTACK          (!TARGET_OS_WATCH && !TARGET_OS_TV)
#define CLS_MACH_EXCEPTION_SUPPORTED (!TARGET_OS_WATCH && !TARGET_OS_TV)
#define CLS_SIGNAL_SUPPORTED         !TARGET_OS_WATCH

tvOS does install the BSD signal handlers and the uncaught-NSException handler, so ordinary crashes are captured and uploaded — consistent with your device verification, which exercised crash(). But there is no alternate signal stack, which means a stack-overflow crash cannot be reliably captured: the handler would run on the stack that just blew. The Mach exception server is compiled out too. One sentence in the Status section covers it.

The second is sharper. Upstream's podspec does two things this one drops:

system("ruby #{current_dir}/crashlytics_add_upload_symbols -f -p #{project_dir} -n Runner.xcodeproj")
s.user_target_xcconfig = { 'DEBUG_INFORMATION_FORMAT' => 'dwarf-with-dsym' }

On iOS the upload-symbols build phase is injected automatically. Here it is not, and the example's project.pbxproj confirms no such phase exists — so native frames in device crash reports arrive unsymbolicated until a developer wires ${PODS_ROOT}/FirebaseCrashlytics/run by hand.

Dropping the system(...) call was forced, not careless: upstream's script derives project_dir by slicing the path at /.symlinks, which does not exist in flutter-tvos's Podfile layout, so a verbatim port would break pod install. But nothing replaced it, and PORTING_REPORT.md currently says dSYM upload is "the usual app-side build config (same as iOS)" — which is wrong in the one way that matters, since on iOS it is automatic. A short "Symbolication" section with the manual snippet would fix it; restoring user_target_xcconfig for dwarf-with-dsym is cheap and worth doing too.

Worth saying why this is easy to miss: Dart-side recordError reports arrive with frames already stringified, so the console looks healthy while native crashes are unreadable.

@TheNoumanDev
TheNoumanDev requested a review from DenisovAV August 17, 2026 02:38
@TheNoumanDev

Copy link
Copy Markdown
Contributor Author

Thanks for the review — both points addressed:

  1. Dropped the stray filesfirebase_analytics_tvos/example/tvos/Runner/GeneratedPluginRegistrant.{h,m} (build output from feat(firebase): tvOS support for firebase_analytics #7); nothing under firebase_analytics_tvos is tracked here anymore.
  2. Fixed the two claims:
    • Crash coverage: no longer "no feature disables" — now notes ordinary crashes are captured (signal + NSException), but no alternate signal stack (stack-overflow may be missed) and no Mach exception server, per FIRCLSFeatures.h.
    • Symbolication: added a section — auto upload-symbols is dropped on tvOS (.symlinks path missing), so wire ${PODS_ROOT}/FirebaseCrashlytics/run by hand; restored dwarf-with-dsym; fixed the "same as iOS" line.

Native code unchanged (verbatim upstream). Ready for another look.

@DenisovAV DenisovAV left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review — both requests closed, verified against the tree

The stray files are gone: nothing under packages/firebase_analytics_tvos/ is tracked here anymore. The gate is clean on the merged tree and CI is 18/18.

Both documentation fixes landed on substance rather than in form:

  • The README no longer claims "no tvOS feature disables". It now states that ordinary crashes are captured through the signal and NSException handlers, but that there is no alternate signal stack — so stack-overflow crashes may be missed — and that the Mach exception server is off, citing FIRCLSFeatures.h.
  • There is a ## Symbolication (dSYM) section. It explains that the automatic upload-symbols step is dropped on tvOS because upstream's script expects a .symlinks path this layout does not have, and shows how to wire ${PODS_ROOT}/FirebaseCrashlytics/run by hand. dwarf-with-dsym is restored in the podspec, and the "same as iOS" line in PORTING_REPORT.md is corrected.

The native code is still verbatim: the only divergence from firebase_crashlytics 5.2.4 is the core import repointing and #import "FLTFirebasePluginRegistry.h" in quotes rather than angle brackets, which follows from the module layout.

LGTM.

@MAUstaoglu MAUstaoglu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Crashlytics is method-channel rather than pigeon, so there's no generated protocol to drift against upstream — checked 3.8.24 → 3.8.27 and the interface is unchanged. Stray registrant files are gone; that was the one thing making this unmergeable ahead of #7. LGTM.

@TheNoumanDev

Copy link
Copy Markdown
Contributor Author

Hey @MAUstaoglu, rebased on main and resolved the README ports-table conflict from #7. Also reworked the row placement so the remaining Firebase PRs insert at distinct spots in the table; they shouldn't re-conflict as the others land. Thanks for the review, and let me know if anything else is needed! 🙏

@MAUstaoglu
MAUstaoglu merged commit 06adb64 into fluttertv:main Aug 18, 2026
20 checks passed
@TheNoumanDev
TheNoumanDev deleted the feat/firebase-crashlytics-tvos branch August 18, 2026 22:32
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.

3 participants