Challenge 1: Non-Fatal Error Reporting — Solution class NoteRepositoryImpl @Inject constructor( private val dao: NoteDao, private val api: NoteApiService ) : NoteRepository { override val notes: Flow> = dao.getAllNotes() override suspend fun refresh() { try { val remoteNotes = api.getNotes() remoteNotes.forEach { dao.insert(it) } } catch (e: IOException) { FirebaseCrashlytics.getInstance().recordException(e) // Fall back to cached data, same as before — no behavior change } } } // Why this doesn't change user-facing behavior, but is still valuable: // // The user still sees exactly the same thing as before this line was // added: whatever notes are already cached in Room, with no error // message, no crash, no visible sign anything went wrong at all (per // Course 2 Chapter 8's offline-first design). What changes is entirely // invisible to the user and visible only in the Firebase console: the // developer now has real, aggregated data on how OFTEN this network // failure actually happens to real users in the field — a single // occurrence, or a widespread pattern (e.g. a spike after a specific // API change) that would otherwise be completely invisible, since a // gracefully-handled error by definition produces no crash report and // no support ticket on its own. Notes: - recordException(e) is specifically for exceptions that were already CAUGHT and handled — it's a deliberate signal ("this happened, and I handled it, but I still want to know about it"), distinct from a fatal, uncaught crash that Crashlytics reports automatically with no code required. - Adding this doesn't require changing the catch block's actual recovery logic at all — it's purely additive, which is why it's safe to sprinkle into already-correct error-handling code without risk of altering behavior.