Screen Reader Detection Service
Component Detail
Description
Detects whether a screen reader (VoiceOver or TalkBack) is active on the device and exposes this state as a reactive stream throughout the app. Other services and widgets subscribe to this stream to conditionally adjust behaviour, such as triggering the sensitive field warning only when a screen reader is running.
screen-reader-detection-service
Summaries
The Screen Reader Detection Service is a foundational capability that enables the entire accessibility layer of the application to activate intelligently and only when needed. Rather than applying accessibility-specific flows universally — which can add friction for non-AT users — this service ensures that features such as sensitive field privacy warnings and enhanced focus management are triggered exclusively for users who rely on screen readers. This precision approach protects user privacy, reduces unnecessary UI complexity for the general population, and demonstrates thoughtful, high-quality product design. As a shared service used across multiple features, it provides consistent behaviour and avoids duplicated platform detection logic throughout the codebase.
As a shared infrastructure service consumed by multiple features, Screen Reader Detection Service sits on the critical path for all accessibility-dependent functionality including sensitive field privacy guarding and focus management. It carries no external dependencies, making it one of the safest components to deliver early and unblock downstream teams. The main delivery risk is platform API variability: VoiceOver and TalkBack expose accessibility state differently across OS versions, so testing must cover a matrix of iOS and Android versions rather than a single device. Plan for a regression test suite that runs on CI with real-device farms.
Because this service is shared, any breaking change to its stream contract will require coordinated updates across all consuming components.
Screen Reader Detection Service wraps Flutter's SemanticsBinding.instance.accessibilityFeatures and registers a listener on SemanticsBinding.instance.window.onAccessibilityFeaturesChanged to track state transitions reactively. screenReaderStream() exposes a StreamController
getPlatformReaderName() returns 'VoiceOver' or 'TalkBack' based on Platform.isIOS for use in user-facing copy. Consumers should dispose stream subscriptions in their own lifecycle hooks to avoid leaks.
Responsibilities
- Detect VoiceOver and TalkBack active state at app startup
- Expose a reactive stream for screen reader active/inactive transitions
- Provide a synchronous current-state accessor for non-reactive contexts
- Re-evaluate state when the app returns from background
Interfaces
isScreenReaderActive()
screenReaderStream()
onScreenReaderChanged(callback)
refreshState()
getPlatformReaderName()
Relationships
Dependents (5)
Components that depend on this component
Related Data Entities (1)
Data entities managed by this component