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

Android锁屏时MediaRecorder无法录音,已申请WakeLock仍无效如何解决

解决方案

1. 补全前台服务的必要配置

Android 8.0及以上版本要求前台服务必须在启动后5秒内调用startForeground()展示通知,同时需要在清单文件中声明对应权限和服务属性,否则熄屏后系统会降低进程优先级,收回麦克风访问权限。

清单文件配置

在AndroidManifest.xml中添加如下声明:

<!-- 基础权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- 前台服务权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- Android 12+ 前台麦克风权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />

<!-- 服务配置 -->
<service
    android:name=".BackgroundService"
    android:exported="false"
    android:foregroundServiceType="microphone" />

前台服务初始化

在Service的onCreate方法最开头添加前台服务启动逻辑,不要等到定时器触发再执行:

@Override
public void onCreate() {
    super.onCreate();
    // 第一步:启动前台服务
    String channelId = "record_service_channel";
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel(
                channelId,
                "录音服务",
                NotificationManager.IMPORTANCE_LOW
        );
        NotificationManager manager = getSystemService(NotificationManager.class);
        manager.createNotificationChannel(channel);
    }
    Notification notification = new NotificationCompat.Builder(this, channelId)
            .setContentTitle("正在录音")
            .setContentText("录音服务运行中")
            .setSmallIcon(R.mipmap.ic_launcher)
            .build();
    startForeground(1001, notification);

    // 第二步:提前申请WakeLock,不要等定时器触发再申请
    PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "FlexRat::Tag");
    wakeLock.setReferenceCounted(false);
    wakeLock.acquire();

    // 原有定时器逻辑
    final long RECORDING_INTERVAL = 30000;
    TimerTask recordingTask = new TimerTask() {
        public void run() {
            Log.i("Debug", "Recording Task");
            stopRecording();
            startRecording();
        }
    };
    Timer recordingTimer = new Timer();
    recordingTimer.scheduleAtFixedRate(recordingTask, 0, RECORDING_INTERVAL);
}

2. 优化MediaRecorder的调用逻辑

你当前每次切分文件都会销毁重建MediaRecorder,熄屏状态下频繁申请麦克风资源很容易被系统拦截,导致setAudioSource失败。

推荐优化方案(无需重建实例)

Android 10及以上可以直接用系统自带的切分逻辑,不需要每次重建MediaRecorder:

private MediaRecorder recorder;

private void startRecording() {
    Log.i("Info", "NEW RECORDING");
    try {
        if (recorder == null) {
            recorder = new MediaRecorder();
            recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
            // 直接设置30秒自动切分
            recorder.setMaxDuration(30000);
            recorder.setOnInfoListener((mr, what, extra) -> {
                if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
                    // 切分文件,重新设置输出路径
                    recorder.stop();
                    recorder.reset();
                    // 复用原有配置
                    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                    recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
                    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
                    recorder.setOutputFile(getNewFilePath());
                    recorder.prepare();
                    recorder.start();
                }
            });
        }
        recorder.setOutputFile(getNewFilePath());
        recorder.prepare();
        recorder.start();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private String getNewFilePath() {
    Date today = Calendar.getInstance().getTime();
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.ENGLISH);
    String reportDate = formatter.format(today);
    File instanceRecordDirectory = new File(getStoragePath());
    if (!instanceRecordDirectory.exists()) {
        instanceRecordDirectory.mkdirs();
    }
    return instanceRecordDirectory.getAbsolutePath() + File.separator + reportDate + ".mp4";
}

3. 适配定制ROM权限限制

小米、华为、OPPO等国产定制系统有额外的后台限制规则,需要引导用户手动开启以下权限:

  • 录音权限设置为「始终允许」,不要选「使用时允许」
  • 开启「允许后台活动」「后台弹出界面」权限
  • 关闭应用的电池优化,加入耗电保护白名单

4. Android 14+适配

Android 14新增了后台麦克风权限自动回收机制,应用退到后台超过30秒没有用户交互就会收回麦克风权限,需要在申请录音权限时明确引导用户开启「始终允许录音」的权限。


内容的提问来源于stack exchange,提问作者Anwar El Bo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 00:27:00