-
-
Notifications
You must be signed in to change notification settings - Fork 294
TalkBack stops announcing Semantics.liveRegion updates while recording with record plugin #592
Description
Package version
- 6.2.0
Environment
- OS: Android
Describe the bug
On Android API 28 devices, the Semantics.liveRegion feature does not work when the audio source is set to AndroidAudioSource.mic.
I originally reported this issue in the Flutter repository, but I was asked to submit it to the record package instead.
To Reproduce
-
Create a new Flutter project via terminal:
flutter create accessibility_bug_report cd accessibility_bug_report -
Add the required dependencies:
flutter pub add record path_provider path
-
Configure Android Permissions:
Openandroid/app/src/main/AndroidManifest.xmland add the following line inside the<manifest>tag:<uses-permission android:name="android.permission.RECORD_AUDIO" />
-
Replace the content of
lib/main.dartwith code sample bellow -
Run on an Android device:
flutter run
-
Verify with TalkBack:
- Enable TalkBack in Android Settings.
- Launch the app and tap the "Start Mic" button.
- Observe: The screen visually updates with dB values every second, but TalkBack does not announce anything while the microphone is active.
AndroidAudioSource.mic |
AndroidAudioSource.voiceCommunication |
|---|---|
liveRegion is broken |
liveRegion works |
IMG_3627.mp4 |
IMG_3628.mp4 |
I tested this on the latest version of Flutter 3.41.0 using a Samsung Galaxy S8 (Android 9 – API 28) device. When AndroidAudioSource is explicitly set to .mic in the code, or when it is omitted, the liveRegion feature does not work. However, when it is set to .voiceCommunication, liveRegion works as expected.
Source code changes
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:record/record.dart';
import 'package:path/path.dart' as p;
void main() => runApp(const MaterialApp(home: AndroidLiveRegionIssue()));
class AndroidLiveRegionIssue extends StatefulWidget {
const AndroidLiveRegionIssue({super.key});
@override
State<AndroidLiveRegionIssue> createState() => _AndroidLiveRegionIssueState();
}
class _AndroidLiveRegionIssueState extends State<AndroidLiveRegionIssue> {
final AudioRecorder _audioRecorder = AudioRecorder();
StreamSubscription<Amplitude>? _amplitudeSubscription;
bool _isMonitoring = false;
double _currentDb = -160.0;
Future<void> _startMonitoring() async {
if (await _audioRecorder.hasPermission()) {
final tempDir = await getTemporaryDirectory();
final tempPath = p.join(tempDir.path, 'temp_mic.m4a');
await _audioRecorder.start(RecordConfig(
androidConfig: AndroidRecordConfig(
audioSource: AndroidAudioSource.mic, // 👈 Test `mic` or `voiceCommunication`
)
), path: tempPath);
setState(() => _isMonitoring = true);
_amplitudeSubscription = _audioRecorder
.onAmplitudeChanged(const Duration(milliseconds: 1000))
.listen((amp) {
setState(() => _currentDb = amp.current);
});
}
}
@override
void dispose() {
_amplitudeSubscription?.cancel();
_audioRecorder.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Android Accessibility Bug')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Semantics(
liveRegion: true, // TalkBack ignores this once mic is active on Android
child: Text(
_isMonitoring ? "Volume: ${_currentDb.toStringAsFixed(0)} dB" : "Mic is OFF",
style: const TextStyle(fontSize: 32),
),
),
const SizedBox(height: 50),
ElevatedButton(
onPressed: _isMonitoring ? null : _startMonitoring,
child: const Text("Start Mic"),
),
],
),
),
);
}
}flutter doctor -v
❯ flutter doctor -v
[✓] Flutter (Channel stable, 3.41.0, on macOS 26.0 25A354 darwin-arm64, locale ko-KR) [1,084ms]
• Flutter version 3.41.0 on channel stable at /Users/nell/.fvm/versions/stable
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 44a626f4f0 (2 days ago), 2026-02-10 10:16:12 -0800
• Engine revision 3452d735bd
• Dart version 3.11.0
• DevTools version 2.54.1
• Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations,
enable-native-assets, omit-legacy-version-file, enable-lldb-debugging, enable-uiscene-migration
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.1) [2.1s]
• Android SDK at /Users/nell/Library/Android/sdk
• Emulator version 35.4.9.0 (build_id 13025442) (CL:N/A)
• Platform android-36, build-tools 35.0.1
• Java binary at: /Library/Java/JavaVirtualMachines/jdk-17.0.12.jdk/Contents/Home/bin/java
This JDK is specified in your Flutter configuration.
To change the current JDK, run: `flutter config --jdk-dir="path/to/jdk"`.
• Java version Java(TM) SE Runtime Environment (build 17.0.12+8-LTS-286)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 26.0) [1,694ms]
• Xcode at /Applications/Xcode-26.0.0.app/Contents/Developer
• Build 17A324
• CocoaPods version 1.16.2
[✓] Chrome - develop for the web [5ms]
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Connected device (5 available) [6.4s]
• [Test Device 👉] SM G950N (mobile) • ce0317136a2c08f10c • android-arm64 • Android 9 (API 28)
Expected results
On Android, TalkBack should continue to announce updates within the Semantics.liveRegion even when the microphone is active, ensuring that visually impaired users can receive real-time updates.
Actual results
An active microphone session on Android silences all liveRegion announcements.