HarmonyOS 鸿蒙Next 如何解决从后台回到前台后,相机停止预览的问题

HarmonyOS 鸿蒙Next 如何解决从后台回到前台后,相机停止预览的问题

【问题现象】

自定义相机预览画面,退到后台,再回到前台,相机画面停止,不输出预览画面。

问题代码如下:

build() {
  aboutToAppear() {
    this.initCamera()
  }

  aboutToDisappear(): void {
    this.releaseCamera()
  }

  NavDestination() {
    Column() {
     //页面UI布局逻辑代码
    }
  }
}

【背景知识】

切换后台再切回来,必须要重新初始化相机才可以。因为切后台,相机资源被全部回收,导致再回到相机页面也无法预览画面。

从下图中相机初始化创建拍照流和输出照片的流程可以了解到,当创建的会话session被释放后,相当于输入输出流也被释放,因为没有输入流,再次进入前台后,页面就呈现静止状态。详细可以参考自定义相机拍照

点击放大

【定位思路】

1. 走读问题代码

(1)通过问题代码可以看出,在使用Navigation导航框架管理页面场景时,在aboutToAppear()方法进行了初始化相机操作,如果切换到后台,系统自动释放相机资源。

(2)查看代码中切换前台是否有再次初始化的动作,发现aboutToAppear()方法再次进入前台不会触发,因此得出结论,从后台切换到前台后相机没有再初始化,导致了相机画面停止。

2. 两种解决思路解决

(1)通过生命周期判断当前相机页面是否在前台。

  • 如果页面显示,则初始化相机资源。
  • 如果页面消失,则释放相机资源。

(2)通过生命周期的系统回调触发通知前台。

  • 切回前台触发onForeground()方法后通知相机页面初始化相机资源。
  • 切到后台触发onBackground()方法后通知相机页面释放相机资源。

【解决方案】

1. 通过生命周期判断当前相机页面是否在前台

1.1 页面被**@Entry组件修饰的场景

通过onPageShow和onPageHide进行判断,流程如下:

@Entry装饰的组件可以调用页面的生命周期,切换前后台会触发onPageShow和onPageHide方法,在此方法中实现相机初始化和释放方法。

[@Entry](/user/Entry)
@Component
struct Index {
  onPageShow(): void {
  // 在此处进行初始化,切换前台后调用,即可重新预览
    this.initCamera();
  }
onPageHide(): void {
   // 在此处进行释放,切换后台后调用,预防再次进入前台后有些资源重复创建。
    this.releaseCamera()
  }
}

1.2 使用Navigation导航框架管理页面的场景

通过onShown和onHidden进行判断,流程如下:

Navigation作为路由容器,其生命周期承载在NavDestination组件上。其中onShown和onHidden在前后台切换时会触发,可以在此方法中实现相机初始化和释放方法。

@Component
struct Index {
  build() {
    NavDestination() {
    }.onShown(()=> { 
    //页面显示时触发
      this.initCamera();
    })
    .onHidden(()=> { 
     //页面消失时触发
      this.releaseCamera()
    })
  }
}

2. 通过生命周期的系统回调触发通知前台

Foreground和Background状态分别在UIAbility实例切换至前台和切换至后台时触发,对应于onForeground()回调和onBackground()回调,因此可以在触发回调后使用Emitter进行线程间通信,通知相机初始化资源和释放资源。该方法的时序图如下:

点击放大

关键步骤如下:

(1)在EntryAbility实现Emitter发送事件。

export default class EntryAbility extends UIAbility {
  onForeground(): void {
    let event: emitter.InnerEvent = {
      eventId: 1,
      priority: emitter.EventPriority.LOW
    };
    // 发送eventId为1的事件
    emitter.emit(event);
  }
  onBackground(): void {
    let event: emitter.InnerEvent = {
      eventId: 2,
      priority: emitter.EventPriority.LOW
    };
    // 发送eventId为2的事件
    emitter.emit(event);
  }
}

(2)在相机页面实现Emitter订阅事件。

@Component
struct Index {
  private  event1: emitter.InnerEvent = {
    eventId: 1
  };
  private event2: emitter.InnerEvent = {
    eventId: 2
  };
  aboutToAppear(){
    // 收到eventId为1的事件后执行该回调
    let foregroundCallback = (): void => {
      this.initCamera();
    };
    // 订阅eventId为1的事件,即返回到前台
    emitter.on(this.event1, foregroundCallback);
    let backgroundCallback = (): void => {
      this.releaseCamera()
    };
    // 订阅eventId为2的事件,即切换到后台
    emitter.on(this.event2, backgroundCallback);}

  aboutToDisappear(): void {
    //释放emitter事件
    emitter.off(this.event1.eventId)
    emitter.off(this.event2.eventId)
  }
}

【总结】

  • 相机切到后台,一定先释放全部的相机资源,进入前台后重新初始化。
  • 前后台的切换EntryAbility必然会触发onForeground()和onBackground()回调,但是需要线程间的通信才能在页面实现具体操作。
  • 根据项目的不同架构,主要有@Entry修饰的生命周期和NavDestination承载的生命周期,可以根据实际使用的场景进行解决方案选择。

更多关于HarmonyOS 鸿蒙Next 如何解决从后台回到前台后,相机停止预览的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS 鸿蒙Next 如何解决从后台回到前台后,相机停止预览的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


针对HarmonyOS 鸿蒙Next中从后台回到前台后相机停止预览的问题,可以尝试以下解决步骤:

  1. 确保系统更新:请确保设备已升级至最新版本的HarmonyOS 鸿蒙Next,并查看开发者文档或官方公告,确认是否有关于相机预览的修复或更新。
  2. 检查应用适配:确保应用已完全适配HarmonyOS 鸿蒙Next版本,特别是相机预览功能。有时版本更新会带来兼容性问题,需要开发者进行适配。
  3. 重新初始化相机:从后台回到前台时,应用可能未能正确恢复相机预览。可以尝试在应用恢复前台时重新初始化相机预览功能。
  4. 权限与配置:检查设备设置中的相机权限和相关配置,确保应用具有必要的访问和操作权限。
  5. API调用:检查相机预览相关的API调用是否正确,确保在应用生命周期的不同阶段都能正确管理相机资源。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部