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

Android 12屏幕录制保存至存储异常:服务启动即停止求助

问题排查与修复方案

1. 先搞定存储权限和路径问题

  • 权限检查:
    • Android 9及更早版本:必须动态申请WRITE_EXTERNAL_STORAGE权限,确保代码中包含权限申请逻辑且用户已授权。
    • Android 10+:虽然DCIM目录无需WRITE权限,但要保证目录能正常创建。在getValues()中添加日志确认创建结果:
      if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) && !saveDir.isDirectory()) {
          boolean dirCreated = saveDir.mkdirs();
          Log.d("StorageDebug", "目录创建结果: " + dirCreated + ", 路径: " + saveLocation);
      }
      
    • 打印SAVEPATH完整值,确认路径无特殊字符、父目录真实存在。

2. 抓准MediaRecorder的异常原因

mMediaRecorder.stop()抛出RuntimeException是触发Service立即停止的核心原因,在catch块中打印完整异常栈,定位具体问题:

catch (RuntimeException e) {
    Log.e("RecorderCrash", "MediaRecorder停止失败: ", e); // 打印完整异常信息
    if (new File(SAVEPATH).delete())
        Toast.makeText(this, "ذخیره ویدیو با مشکل روبرو شد", Toast.LENGTH_SHORT).show();
}

常见触发场景:

  • 未调用mMediaRecorder.start()就执行stop:检查录制启动逻辑,确保start成功后才会进入停止流程。
  • 音频源配置错误:audioRecSource = "1"对应麦克风,若暂时不需要音频,可先关闭音频录制测试是否恢复正常。
  • 分辨率/比特率超出设备支持范围:降低比特率或改用设备原生分辨率。

3. 修复重复停止Service的问题

indexFile()的扫描回调和destroyMediaProjection的finally块都调用了stopSelf(),重复停止会导致异常。删除扫描回调中的stopSelf(),仅保留finally块中的一次调用:

MediaScannerConnection.scanFile(this, toBeScannedStr, null, (path, uri) -> {
    Message message = mHandler.obtainMessage();
    Log.e("ServiceErrors","RecorderService Index : " + message.toString());
    message.sendToTarget();
    // 移除此处的stopSelf()
});

4. 检查MediaProjection的回调逻辑

确认mMediaProjectionCallback是否在录制启动前就触发了onStop(),导致提前执行停止逻辑。添加状态判断:

private MediaProjection.Callback mMediaProjectionCallback = new MediaProjection.Callback() {
    @Override
    public void onStop() {
        Log.d("ProjectionDebug", "MediaProjection被停止");
        // 仅在录制状态下执行停止逻辑
        if (isRecording) {
            destroyMediaProjection();
        }
    }
};

5. 确保Service以前台模式启动

Android 8.0+要求后台Service必须以前台模式启动,否则会被系统立即杀死。启动Service时使用startForegroundService(),并在onStartCommand中尽快显示前台通知:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // 构建前台通知(需先创建通知渠道)
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "RECORDER_CHANNEL")
            .setSmallIcon(R.drawable.ic_recorder)
            .setContentTitle("正在录屏")
            .setContentText("录屏中...")
            .setPriority(NotificationCompat.PRIORITY_LOW);
    
    startForeground(1, builder.build());
    // 执行录制初始化与启动逻辑
    startRecording();
    return START_STICKY;
}

内容的提问来源于stack exchange,提问作者Dr.KeyOk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 01:31:34