You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Flutter应用后台持续麦克风录制功能?

Flutter后台持续音频录制实现方案

问题背景

基于Flutter开发音频录制应用,使用flutter_sound和path_provider实现基础录制逻辑,但应用进入后台几秒后麦克风停止采集,返回前台录制恢复正常。需实现后台持续录音,同时了解iOS和Android的权限配置与限制规避方案。

现有实现代码

import 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Audio Recorder',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: AudioRecorderWidget(),
    );
  }
}

class AudioRecorderWidget extends StatefulWidget {
  @override
  _AudioRecorderWidgetState createState() => _AudioRecorderWidgetState();
}

class _AudioRecorderWidgetState extends State<AudioRecorderWidget> {
  final FlutterSoundRecorder _recorder = FlutterSoundRecorder();
  final FlutterSoundPlayer _player = FlutterSoundPlayer();
  bool isRecording = false;
  String? filePath;

  @override
  void initState() {
    super.initState();
    initAudio();
  }

  Future<void> initAudio() async {
    await _recorder.openRecorder();
    await _player.openPlayer();
  }

  Future<void> startRecording() async {
    try {
      Directory appDocDir = await getApplicationDocumentsDirectory();
      filePath = '${appDocDir.path}/recorded_audio.aac';
      await _recorder.startRecorder(toFile: filePath);
      setState(() {
        isRecording = true;
      });
    } catch (e) {
      print("Error starting recording: $e");
    }
  }

  Future<void> stopRecording() async {
    try {
      await _recorder.stopRecorder();
      setState(() {
        isRecording = false;
      });
    } catch (e) {
      print("Error stopping recording: $e");
    }
  }

  Future<void> playRecording() async {
    if (filePath != null) {
      await _player.startPlayer(fromURI: filePath);
    }
  }

  @override
  void dispose() {
    _recorder.closeRecorder();
    _player.closePlayer();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Audio Recorder')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: isRecording ? null : startRecording,
              child: Text('Start Recording'),
            ),
            ElevatedButton(
              onPressed: isRecording ? stopRecording : null,
              child: Text('Stop Recording'),
            ),
            ElevatedButton(
              onPressed: !isRecording && filePath != null ? playRecording : null,
              child: Text('Play Recording'),
            ),
            if (isRecording)
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: CircularProgressIndicator(),
              ),
          ],
        ),
      ),
    );
  }
}

遇到的问题

应用进入后台后几秒内麦克风停止采集,返回前台后录制恢复正常。

已尝试方案

  • 了解过画中画模式保持应用活跃,但希望探索其他方案;
  • 查询Flutter官方文档未找到后台持续录音的直接实现方法。

解决方案

一、权限配置(iOS + Android)

Android 端

  1. 添加权限到AndroidManifest.xml
    在android/app/src/main/AndroidManifest.xml中添加以下权限:
    <!-- 基础录音权限 -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <!-- Android 10+ 后台录音权限 -->
    <uses-permission android:name="android.permission.RECORD_AUDIO_BACKGROUND" />
    <!-- 申请忽略电池优化权限 -->
    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
    
  2. 声明前台服务类型
    在<application>标签内添加服务声明,指定麦克风类型的前台服务:
    <service
        android:name="com.dooboolab.fluttersound.FlutterSoundRecorderService"
        android:foregroundServiceType="microphone" />
    
    Android 12+要求后台访问麦克风必须使用microphone类型的前台服务,避免系统终止进程。
  3. 主动请求忽略电池优化
    在代码中添加请求逻辑,避免系统因省电策略终止后台录制:
    import 'package:permission_handler/permission_handler.dart';
    
    Future<void> requestBatteryOptimization() async {
      if (await Permission.ignoreBatteryOptimizations.isDenied) {
        await Permission.ignoreBatteryOptimizations.request();
      }
    }
    
    可在应用初始化或开始录制前调用该方法。

iOS 端

  1. 添加权限到Info.plist
    在ios/Runner/Info.plist中添加麦克风权限说明和后台音频模式:
    <!-- 麦克风权限说明 -->
    <key>NSMicrophoneUsageDescription</key>
    <string>需要访问麦克风进行音频录制</string>
    <!-- 开启后台音频模式 -->
    <key>UIBackgroundModes</key>
    <array>
        <string>audio</string>
    </array>
    
    开启audio后台模式后,iOS允许应用在后台持续处理音频录制。
  2. 配置音频会话
    初始化阶段配置正确的音频会话类别,确保后台录音权限生效:
    import 'package:audio_session/audio_session.dart';
    
    Future<void> initAudioSession() async {
      final session = await AudioSession.instance;
      await session.configure(AudioSessionConfiguration(
        avAudioSessionCategory: AVAudioSessionCategory.playAndRecord,
        avAudioSessionCategoryOptions: AVAudioSessionCategoryOptions.allowBluetooth | AVAudioSessionCategoryOptions.mixWithOthers,
        avAudioSessionMode: AVAudioSessionMode.spokenAudio,
      ));
      await session.setActive(true);
    }
    
    在initAudio()方法中先调用该配置,再打开flutter_sound录制器。

二、Flutter Sound 配置优化

调用startRecorder时指定合适的音频源,并确保启用后台支持:

await _recorder.startRecorder(
  toFile: filePath,
  audioSource: AudioSource.microphone,
  codec: Codec.aacADTS,
);

三、备选方案

如果flutter_sound后台支持不稳定,可使用audio_service包结合原生录制逻辑,将录制任务放在后台服务中执行,不受前台生命周期影响。


内容的提问来源于stack exchange,提问作者Ashish Tandon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 18:35:05