HarmonyOS 鸿蒙Next中断

HarmonyOS 鸿蒙Next中断

应用前后台切换时,如何解决Video组件播放发生中断的问题

4 回复

【背景知识】

  • UIAbility组件生命周期:当用户打开、切换和返回到对应应用时,应用中的UIAbility实例会在其生命周期的不同状态之间转换。
  • Foreground和Background状态:Foreground和Background状态分别在UIAbility实例切换至前台和切换至后台时触发,对应于onForeground()回调和onBackground()回调。
  • Watch和自定义组件更新@Watch用于监听状态变量的变化,当状态变量变化时,@Watch的回调方法将被调用。

【问题定位】

视频播放功能需要通过VideoController的start()方法启动。因此可以排查应用在前后台切换时,aboutToAppear和onPageShow方法是否会被触发,从而确定controller.start()方法是否被调用。

【分析结论】

播放视频必须调用controller.start(),如下代码。虽然首次进入页面时,可以通过aboutToAppear或者onPageShow调用controller.start(),但是前后台切换的时候,这两个方法不会被触发,因此controller.start()不会被调用,所以会出现视频无法继续播放的情况。

controller: VideoController = new VideoController()
this.controller.start();

【修改建议】

为了实现前后台切换能够继续播放的效果,结合UIAbility组件生命周期和@Watch和自定义组件更新,考虑在前后台切换时,对APP全局变量的值进行修改,然后通过监听APP全局变量值,以及对其进行判断,来控制视频的停止和播放。

(1)在前后台切换时,对APP里的全局变量isForeGround进行赋值或者修改。

代码示例如下:

import { ConfigurationConstant, UIAbility } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';

const DOMAIN = 0x0000;

export default class EntryAbility extends UIAbility {
  onCreate(): void {
    try {
      this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
    } catch (err) {
      hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
    }
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
  }

  onDestroy(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    // Main window is created, set main page for this ability
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

    windowStage.loadContent('pages/Q-20250401000213', (err) => {
      if (err.code) {
        hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
        return;
      }
      hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
    });
  }

  onWindowStageDestroy(): void {
    // Main window is destroyed, release UI related resources
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }

  onForeground():void {
    // 切到前台,设置isForeGround值为true
    console.info('onForeground-切换到前台了');
    AppStorage.setOrCreate('isForeGround', true);
  }

  onBackground():void {
    // 切到后台,设置isForeGround值为false
    console.info('onBackground-切换到后台了');
    AppStorage.setOrCreate('isForeGround', false);
  }
}

(2)在当前组件用watch来监听APP全局变量。

代码示例如下:

@Entry
@Component
struct videoDemo {
  private controller: VideoController = new VideoController();
  [@Watch](/user/Watch)('network') @StorageLink('isForeGround') isForeGround: boolean = false;
  network() {
    if (this.isForeGround) {
      // 切换到前台了,视频继续播放
      this.controller.start();
    } else {
      // 切换到后台了,视频暂停播放
      this.controller.pause();
    }
  }
  build() {
    Column(){
      Video({
        src: $rawfile('videoTest.mp4'), // 示例视频
        controller:this.controller
      }).height('40%')
        .loop(true)  // 开启循环播放

    }.margin({top:100})
    .width('100%')
    .height('100%')

  }
}

更多关于HarmonyOS 鸿蒙Next中断的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


可以参考 应用前后台切换时,如何解决Video组件播放发生中断的问题

为了实现前后台切换能够继续播放的效果,结合UIAbility组件生命周期和@Watch和自定义组件更新,考虑在前后台切换时,对APP全局变量的值进行修改,然后通过监听APP全局变量值,以及对其进行判断,来控制视频的停止和播放。

  1. 在前后台切换时,对APP里的全局变量isForeGround进行赋值或者修改。
// EntryAbility.ets
export default class EntryAbility extends UIAbility {
  // ...
  onForeground():void {
    // 切到前台,设置isForeGround值为true
    console.info('onForeground-切换到前台了');
    AppStorage.setOrCreate('isForeGround', true);
  }

  onBackground():void {
    // 切到后台,设置isForeGround值为false
    console.info('onBackground-切换到后台了');
    AppStorage.setOrCreate('isForeGround', false)
  }
}
  1. 在当前组件用watch来监听APP全局变量。
// video.ets
@Entry
@Component
struct videoDemo {
  private controller: VideoController = new VideoController();
  [@Watch](/user/Watch)('network') @StorageLink('isForeGround') isForeGround: boolean = false;

  network() {
    if (this.isForeGround) {
      // 切换到前台了,视频继续播放
      this.controller.start();
    } else {
      // 切换到后台了,视频暂停播放
      this.controller.pause();
    }
  }

  build() {
    Column() {
      Video({
        src: $rawfile('video.mp4'), // 示例视频
        controller: this.controller
      }).height('40%')
        .loop(true) // 开启循环播放

    }.margin({ top: 100 })
    .width('100%')
    .height('100%')

  }
}

HarmonyOS Next中断机制基于事件驱动架构实现。系统通过异步通信处理中断事件,采用微内核设计确保实时响应。中断服务例程在用户态执行,通过权限分离保障系统安全。鸿蒙Next支持软中断和硬中断两种模式,中断优先级由任务调度器动态管理。中断处理过程包含事件注册、消息派发和异步回调三个阶段,所有中断事件均通过事件总线进行统一分发。

在HarmonyOS Next中,Video组件在应用前后台切换时中断播放是常见问题,可通过以下方式解决:

  1. 生命周期管理:在onPageHide中保存播放状态和进度,在onPageShow中恢复播放
  2. 使用ServiceAbility:通过后台服务维持播放状态,避免被系统回收
  3. 音频焦点管理:监听音频焦点变化,在焦点丢失时暂停,重新获取时续播
  4. 后台播放权限:确保在config.json中声明ohos.permission.KEEP_BACKGROUND_RUNNING权限

示例代码片段:

// 页面隐藏时保存状态
onPageHide() {
  this.videoState = {
    currentTime: this.video.currentTime,
    isPlaying: !this.video.paused
  };
}

// 页面显示时恢复播放
onPageShow() {
  if (this.videoState.isPlaying) {
    this.video.currentTime = this.videoState.currentTime;
    this.video.play();
  }
}

建议结合具体业务场景选择合适的解决方案,确保视频播放体验的连贯性。

回到顶部