HarmonyOS鸿蒙Next中camera.PhotoSession.release()报错,无法释放

HarmonyOS鸿蒙Next中camera.PhotoSession.release()报错,无法释放

camera.PhotoSession.release()释放报错,
7400201 - Camera service fatal error.

完全按照官方建议的关闭相机操作,也关闭不了,造成第二次进来无法拍照,有没有大佬知道到底为啥啊!? 如何实现相机关闭-相机开发(Camera)-拍照和图片-媒体开发-开发 - 华为HarmonyOS开发者


更多关于HarmonyOS鸿蒙Next中camera.PhotoSession.release()报错,无法释放的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

可以参考 拉起相机预览图像失败,报错7400201

问题定位

  1. 搜索createPreviewOutput或者CameraOutputCapability,查看是否获取previewProfiles属性。
  2. 搜索日志中错误码7400201,查看是否存在分辨率不支持相关日志。
07-01 22:31:45.915   11445-11445   C02B01/com....hm/CAMERA   com....hm       E     {IsPreconfigProfilesLegal():237} VideoSession::IsPreconfigProfilesLegal check video profile fail, no matched video profiles:1003 3840x2160
07-01 22:31:45.915   11445-11445   C02B01/com....hm/CAMERA   com....hm       E     {Preconfig():295} VideoSession::Preconfig preconfigProfile is illegal.
07-01 22:31:45.915   11445-11445   A03D00/com....hm/JSAPP    com....hm       E     initCamera fail: {"code":"7400201"}

更多关于HarmonyOS鸿蒙Next中camera.PhotoSession.release()报错,无法释放的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


✅ 正确的释放顺序(文档推荐)

async function releaseResources(): Promise<void> {
  // 1. 停止当前会话(必须第一步)
  await photoSession?.stop().catch((e: BusinessError) => {
    console.error('停止会话失败:', e);
  });

// 2. 释放相机输入流

  await cameraInput?.close().catch((e: BusinessError) => {
    console.error('关闭相机失败:', e);
  });

// 3. 释放预览输出流

await previewOutput?.release().catch((e: BusinessError) => {
    console.error('停止预览流失败:', e);
  });

// 4. 释放拍照输出流

  await photoOutput?.release().catch((e: BusinessError) => {
    console.error('停止拍照流失败:', e);
  });

// 5. 释放会话(必须最后一步)

  await photoSession?.release().catch((e: BusinessError) => {
    console.error('释放会话失败:', e);
  });
}

🔴 常见错误做法

// 错误1:未先 stop() 就直接 release()

 await photoSession.release(); // 会报 7400201

// 错误2:顺序错误,先释放 session 再释放 output

 await photoSession.release();
  await photoOutput.release(); // session 已释放,output 无法释放

// 错误3:未等待异步完成就执行下一步

  photoSession.stop(); // 未 await
  photoSession.release(); // stop 未完成就执行 release

完整解决方案

方案一:标准释放流程(推荐)

import { camera } from '[@kit](/user/kit).CameraKit';
import { BusinessError } from '[@kit](/user/kit).BasicServicesKit';
class CameraManager {
  private photoSession: camera.PhotoSession | undefined;
  private cameraInput: camera.CameraInput | undefined;
  private previewOutput: camera.PreviewOutput | undefined;
  private photoOutput: camera.PhotoOutput | undefined;
  private isReleasing: boolean = false; // 防止重复释放
  /**
   * 安全释放相机资源
   */
  async releaseCamera(): Promise<void> {
    // 防止重复释放
    if (this.isReleasing) {
      console.warn('Camera is already releasing, skip this call');
      return;
    }
    this.isReleasing = true;
    try {
      // 步骤 1: 停止会话(必须第一步)
      if (this.photoSession) {
        try {
          console.info('Step 1: Stopping photo session...');
          await this.photoSession.stop();
          console.info('Photo session stopped successfully');
        } catch (error) {
          let err = error as BusinessError;
          console.error(`Failed to stop session: ${err.code}, ${err.message}`);
          // 即使 stop 失败也继续执行后续释放
        }
      }
      // 步骤 2: 关闭相机输入
      if (this.cameraInput) {
        try {
          console.info('Step 2: Closing camera input...');
          await this.cameraInput.close();
          console.info('Camera input closed successfully');
        } catch (error) {
          let err = error as BusinessError;
          console.error(`Failed to close camera input: ${err.code}, ${err.message}`);
        }
      }
      // 步骤 3: 释放预览输出
      if (this.previewOutput) {
        try {
          console.info('Step 3: Releasing preview output...');
          await this.previewOutput.release();
          console.info('Preview output released successfully');
        } catch (error) {
          let err = error as BusinessError;
          console.error(`Failed to release preview output: ${err.code}, ${err.message}`);
        }
      }
      // 步骤 4: 释放拍照输出
      if (this.photoOutput) {
        try {
          console.info('Step 4: Releasing photo output...');
          await this.photoOutput.release();
          console.info('Photo output released successfully');
        } catch (error) {
          let err = error as BusinessError;
          console.error(`Failed to release photo output: ${err.code}, ${err.message}`);
        }
      }
      // 步骤 5: 释放会话(必须最后)
      if (this.photoSession) {
        try {
          console.info('Step 5: Releasing photo session...');
          await this.photoSession.release();
          console.info('Photo session released successfully');
        } catch (error) {
          let err = error as BusinessError;
          console.error(`Failed to release session: ${err.code}, ${err.message}`);
          // 如果仍然报 7400201,重置所有引用
          if (err.code === 7400201) {
            console.warn('Camera service error, force reset all references');
          }
        }
      }
      // 步骤 6: 清空所有引用
      this.photoSession = undefined;
      this.cameraInput = undefined;
      this.previewOutput = undefined;
      this.photoOutput = undefined;
      console.info('All camera resources released successfully');
    } finally {
      this.isReleasing = false;
    }
  }
}

方案二:增加释放前检查(推荐)

/**
  * 带状态检查的安全释放
  */
 async function releaseSessionSafely(session: camera.PhotoSession | undefined): Promise<void> {
   if (!session) {
     console.warn('Session is undefined, skip release');
     return;
   }
   try {
     // 1. 先调用 stop()
     console.info('Stopping session...');
     await session.stop();
     // 2. 等待一小段时间确保 stop 完成
     await new Promise(resolve => setTimeout(resolve, 100));
     // 3. 再调用 release()
     console.info('Releasing session...');
     await session.release();
     console.info('Session released successfully');
   } catch (error) {
     let err = error as BusinessError;
     if (err.code === 7400201) {
       console.error('Camera service fatal error when releasing session');
       console.error('This usually means:');
       console.error('1. Session was not stopped before release');
       console.error('2. Camera service crashed');
       console.error('3. Resources were already released');
       // 强制清理引用,下次重新创建
       session = undefined;
     } else {
       console.error(`Release failed with error: ${err.code}, ${err.message}`);
     }
     throw error;
   }
 }

方案三:页面生命周期集成

 import { camera } from '[@kit](/user/kit).CameraKit';
 import { BusinessError } from '[@kit](/user/kit).BasicServicesKit';
 @Entry
 @Component
 struct CameraPage {
   private photoSession: camera.PhotoSession | undefined;
   private cameraInput: camera.CameraInput | undefined;
   private previewOutput: camera.PreviewOutput | undefined;
   private photoOutput: camera.PhotoOutput | undefined;
   // 页面即将销毁时释放资源
   aboutToDisappear(): void {
     console.info('Page is about to disappear, releasing camera resources');
     this.releaseAllResources();
   }
   // 页面返回前台时重新初始化
   onPageShow(): void {
     console.info('Page showed, check if need to reinitialize camera');
     if (!this.photoSession) {
       this.initializeCamera();
     }
   }
   /**
     * 初始化相机
     */
   async initializeCamera(): Promise<void> {
     try {
       // 先释放可能存在的旧资源
       await this.releaseAllResources();
       // 重新创建相机资源
       // ... 创建逻辑
       console.info('Camera initialized successfully');
     } catch (error) {
       console.error('Failed to initialize camera:', error);
     }
   }
   /**
     * 释放所有资源
     */
   async releaseAllResources(): Promise<void> {
     try {
       // 按照正确顺序释放
       if (this.photoSession) {
         await this.photoSession.stop();
       }
       if (this.cameraInput) {
         await this.cameraInput.close();
       }
       if (this.previewOutput) {
         await this.previewOutput.release();
       }
       if (this.photoOutput) {
         await this.photoOutput.release();
       }
       if (this.photoSession) {
         await this.photoSession.release();
       }
       // 清空引用
       this.photoSession = undefined;
       this.cameraInput = undefined;
       this.previewOutput = undefined;
       this.photoOutput = undefined;
     } catch (error) {
       let err = error as BusinessError;
       console.error(`Release error: ${err.code}, ${err.message}`);
       // 即使释放失败也要清空引用
       this.photoSession = undefined;
       this.cameraInput = undefined;
       this.previewOutput = undefined;
       this.photoOutput = undefined;
     }
   }
   build() {
     Column() {
       // UI 组件
     }
   }
 }

关键要点总结

✅ 必须遵守的规则

  1. 释放顺序不能错

stop() → cameraInput.close() → previewOutput.release() → photoOutput.release() → session.release()

  1. 必须使用 await 等待异步完成

await session.stop(); // ✅ 正确 session.stop(); // ❌ 错误:未等待完成

  1. stop() 和 release() 必须都调用

await session.stop(); // 先停止 await session.release(); // 再释放

  1. 使用 try-catch 捕获每一步的错误

try { await session.release(); } catch (error) { console.error(‘Release failed:’, error); // 即使失败也要清空引用 session = undefined; }

  1. 防止重复释放

if (this.isReleasing) return; this.isReleasing = true;

调试建议

  1. 添加详细日志

async function releaseWithLog(session: camera.PhotoSession): Promise<void> { console.info(’=== Start releasing camera ===’); console.info(Session state: ${session ? 'exists' : 'undefined'}); try { console.info(’[1/5] Calling session.stop()…’); await session.stop(); console.info(’[1/5] ✓ session.stop() completed’); console.info(’[2/5] Calling session.release()…’); await session.release(); console.info(’[2/5] ✓ session.release() completed’); console.info(’=== Camera released successfully ===’); } catch (error) { let err = error as BusinessError; console.error(=== Release failed at some step ===); console.error(Error code: ${err.code}); console.error(Error message: ${err.message}); throw error; } }

  1. 检查相机服务状态

import { camera } from ‘@kit.CameraKit’; // 监听相机状态变化 function monitorCameraStatus(cameraManager: camera.CameraManager): void { cameraManager.on(‘cameraStatus’, (err: BusinessError, status: camera.CameraStatusInfo) => { console.info(Camera status changed: ${JSON.stringify(status)}); if (status.status === camera.CameraStatus.UNAVAILABLE) { console.warn(‘Camera became unavailable, may need to release and reinitialize’); } }); }

  1. 如果问题依然存在

/**

  • 终极方案:强制重启相机服务 */ async function forceResetCamera(): Promise<void> { try { // 1. 释放所有相机资源(忽略错误) await photoSession?.stop().catch(() => {}); await cameraInput?.close().catch(() => {}); await previewOutput?.release().catch(() => {}); await photoOutput?.release().catch(() => {}); await photoSession?.release().catch(() => {}); // 2. 清空所有引用 photoSession = undefined; cameraInput = undefined; previewOutput = undefined; photoOutput = undefined; // 3. 等待一段时间让系统清理资源 await new Promise(resolve => setTimeout(resolve, 500)); // 4. 重新初始化相机 await initializeCamera(); console.info(‘Camera force reset completed’); } catch (error) { console.error(‘Force reset failed:’, error); } }

在HarmonyOS Next中,camera.PhotoSession.release()报错通常是由于资源未正确初始化或已被释放导致的。请检查PhotoSession是否已成功创建且未被重复释放。确保在调用release()前,所有相关操作已完成。

在HarmonyOS Next中,camera.PhotoSession.release() 报错 7400201 通常表示相机资源释放时发生了服务端致命错误。这往往不是调用顺序的问题,而是与相机会话的状态管理或底层资源竞争有关。

根据官方文档,释放的正确顺序通常是:先停止捕获会话,再释放PhotoSession。但错误7400201提示问题可能发生在更底层。

建议排查以下几点:

  1. 检查异步操作:确保所有与相机相关的异步操作(如拍照、对焦)都已完全完成或取消,再调用release()。未完成的异步任务会持有相机资源。
  2. 检查生命周期绑定:确认PhotoSession的释放时机。最佳实践是在页面或组件的aboutToDisappearonDestroy生命周期回调中释放,并确保释放前UI已完全与相机解耦。
  3. 检查权限与状态:虽然少见,但请确认相机权限在释放时依然有效。另外,确保没有其他后台进程或模块(如预览的XComponent)在异常状态下仍持有对相机会话的引用。
  4. 查看完整日志:错误码7400201是一个服务端错误。查看设备Logcat的完整错误日志,搜索CameraService7400201相关的更详细堆栈信息,这能帮助定位是哪个具体操作触发了服务端异常。

一个更稳健的释放模式参考:

// 1. 停止当前捕获会话
try {
    await this.photoSession.stop();
} catch (err) {
    console.error('Stop photo session failed: ' + err);
}

// 2. 可选:确保所有资源置空
// this.previewOutput = undefined;
// this.photoOutput = undefined;

// 3. 释放PhotoSession
try {
    this.photoSession.release();
    this.photoSession = undefined; // 释放后置空引用
    console.info('PhotoSession released successfully.');
} catch (err) {
    console.error('Release photo session failed, error code: ' + err.code);
}

如果上述步骤仍无法解决,问题可能涉及特定设备或场景下的底层兼容性。可以尝试在官方开发者社区搜索错误码7400201,查看是否有已知问题或临时解决方案。

回到顶部