在HarmonyOS 6应用开发中,自定义相机页面“一片漆黑”是最令人头疼的高频问题。你明明按照文档调用了 createPreviewOutputsession.start(),但预览界面就是没有任何画面,Hilog日志里却只有一句模糊的 failed to get surfaceOperation not allowed

这通常不是硬件故障,而是开发者在权限、时序、生命周期这三个关键环节踩了坑。本文将结合HarmonyOS 6的最新Camera Kit API,为你梳理一套从“日志关键词”到“代码修复”的完整排雷流程。

一、现场:黑屏背后的“七宗罪”与日志指纹

当相机页面黑屏时,第一步是查看Hilog日志。不同的错误日志对应着完全不同的代码缺陷。

黑屏场景(罪因)

典型日志关键词

代码缺陷本质

1. 权限未授权

Permission denied/ errorReason: 2

未声明或未申请 ohos.permission.CAMERA

2. 设备被占用

Can not use camera cause of preempted

相机被其他应用(如系统相机)独占

3. Surface未就绪

failed to get surface/ Cannot find surface

XComponent未加载就提前初始化相机

4. 配置时序错乱

Operation not allowed/ Session not config

beginConfig/commitConfig/start顺序错误

5. 流不可用

canAddInput/CanAddOutput check failed

添加了不支持的 Profile或无效流

6. 折叠屏未切换

(无特定日志)

折叠状态变化后未重新绑定摄像头

7. 后台未释放

Camera restart camera session failed

页面返回后未在 onPageHide释放资源

日志示例(Surface缺失)

// ❌ 典型错误:XComponent未创建就初始化相机
{CreatePreviewOutput():357} failed to get surface
<surface_utils.cpp:48-GetSurface>: Cannot find surface, uniqueId: 0

二、诊断:根据日志关键词锁定“病灶”

1. 如果是“Permission denied”或“errorReason: 2”

排查重点:权限声明与动态申请。

  • 检查 module.json5:确认已声明 ohos.permission.CAMERA权限。

  • 检查动态申请逻辑:在 onPageShow中调用 requestPermissionsFromUser,并处理用户拒绝后的引导逻辑。

  • 日志线索:若日志出现 state: 2, errorReason: 2,通常意味着权限根本未声明。

2. 如果是“failed to get surface”

排查重点XComponent 生命周期与相机初始化的时序

这是HarmonyOS 6开发中最常见的坑。绝对不能onPageShow中直接初始化相机,因为此时 XComponent可能还未创建完成,导致 getXComponentSurfaceId()返回空值。

错误代码示例

// ❌ 错误示例:onPageShow中直接初始化(XComponent可能未加载)
onPageShow() {
  let surfaceId = this.mXComponentController.getXComponentSurfaceId(); // 可能为undefined
  this.initCamera(surfaceId); // 导致createPreviewOutput失败
}

修复方案:必须在 XComponentonLoad回调中初始化相机。

// ✅ 正确示例:等待XComponent加载完成
@State surfaceId: string = '';

XComponent({ id: 'cameraPreview', type: 'surface', controller: this.mXComponentController })
  .onLoad(() => {
    // 此时Surface已创建,获取ID并初始化
    this.surfaceId = this.mXComponentController.getXComponentSurfaceId();
    this.initCamera(this.surfaceId);
  })

3. 如果是“Operation not allowed”或“Session not config”

排查重点相机操作必须包裹在配置会话中

HarmonyOS 6的相机操作是严格的“事务性”流程,添加/移除输入输出流必须在 beginConfig()commitConfig()之间进行,且必须在 commitConfig()之后才能调用 start()

正确时序代码

// ✅ 必须遵循的时序
async initCamera() {
  // ... 创建cameraInput, previewOutput ...
  
  // 1. 开始配置
  this.session.beginConfig();
  
  // 2. 添加流(必须在配置区间内)
  this.session.addInput(this.cameraInput);
  this.session.addOutput(this.previewOutput);
  
  // 3. 提交配置
  await this.session.commitConfig();
  
  // 4. 提交后才能启动
  await this.session.start();
}

注意:任何在 beginConfig之外直接调用 addInputcommitConfig之前调用 start的行为都会触发 74001027400103错误码。

三、修复:高频黑屏场景的“代码手术”

场景1:权限导致的“静默黑屏”

现象:无崩溃日志,但页面黑屏,拍照按钮点击闪退。

修复:在初始化前增加权限校验。

import { abilityAccessCtrl } from '@kit.AbilityAccessCtrlKit';

async checkCameraPermission(): Promise<boolean> {
  let atManager = abilityAccessCtrl.createAtManager();
  let permissions: Array<string> = ['ohos.permission.CAMERA'];
  let grantStatus = await atManager.checkAccessToken(permissions);
  return grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
}

async initCamera() {
  if (!await this.checkCameraPermission()) {
    // 跳转设置或弹窗提示
    return;
  }
  // ... 继续初始化
}

场景2:折叠屏切换后的“黑屏”

现象:折叠屏设备展开/折叠后,相机预览黑屏。

修复:监听 display变化,重新初始化相机。

import { display } from '@kit.ArkUI';

// 监听屏幕变化
display.on('change', () => {
  this.releaseCamera(); // 先释放旧资源
  setTimeout(() => {
    this.initCamera(); // 重新初始化(需等待布局稳定)
  }, 300);
});

场景3:页面返回后“黑屏”

现象:从B页面返回A页面,A页面的相机无法恢复。

修复:在 onPageHide中释放,在 onPageShow中重建。

onPageShow() {
  if (this.surfaceId) {
    this.initCamera(this.surfaceId);
  }
}

onPageHide() {
  this.releaseCamera(); // 必须释放,否则返回时可能报“设备被占用”
}

四、总结:相机黑屏排查 SOP

  1. 查日志:搜索 Permission deniedfailed to get surfaceOperation not allowed关键词。

  2. 验权限:确认 module.json5已声明且用户已授权。

  3. 看时序:确认相机初始化在 XComponent.onLoad中,且操作流严格遵循 beginConfig-> addInput/Output-> commitConfig-> start

  4. 保释放:在 onPageHideaboutToDisappear中调用 release(),防止资源泄漏。

核心法则:在HarmonyOS 6中,相机是稀缺资源,“谁申请,谁释放”是铁律。任何对时序和生命周期的忽视,都会直接导致预览黑屏。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐