HarmonyOS 鸿蒙Next中通过navigation跳转到到二级页面怎么监听前后台事件

HarmonyOS 鸿蒙Next中通过navigation跳转到到二级页面怎么监听前后台事件 【问题描述】:通过navigation跳转到到二级页面怎么监听前后台事件

【问题现象】:有个二级页面在播放视频时,切换到后台,能暂停播放,但是切换回前台不能恢复播放

13 回复

【修改建议】 为了实现前后台切换能够继续播放的效果,结合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)
}
}

(2)在当前组件用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%')

  }
}

【背景知识】

  • 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();

更多关于HarmonyOS 鸿蒙Next中通过navigation跳转到到二级页面怎么监听前后台事件的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


好的,感谢,

方案一:使用 WindowStage 监听窗口生命周期事件

如何判断应用当前在前台/后台-程序框架(Ability)-程序框架-应用框架开发-开发 - 华为HarmonyOS开发者

[Interface (WindowStage)-@ohos.window (窗口)-窗口管理-ArkTS API-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-window-windowstage#onwindowstageevent9)

import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';

export default class EntryAbility extends UIAbility {
  onWindowStageCreate(windowStage: window.WindowStage) {
    try {
      windowStage.on('windowStageEvent', (data) => {
        console.info('Window stage event: ' + JSON.stringify(data));

        if (data === window.WindowStageEventType.SHOWN) {
          console.info('应用进入前台');
          // 在这里恢复视频播放
          this.resumeVideoPlayback();
        } else if (data === window.WindowStageEventType.HIDDEN) {
          console.info('应用进入后台');
          // 在这里暂停视频播放
          this.pauseVideoPlayback();
        } else if (data === window.WindowStageEventType.ACTIVE) {
          console.info('窗口获焦');
        } else if (data === window.WindowStageEventType.INACTIVE) {
          console.info('窗口失焦');
        }
      });
    } catch (exception) {
      console.error('Failed to enable window stage event listener: ' + JSON.stringify(exception));
    }
  }

  private pauseVideoPlayback() {
    // 实现暂停视频播放的逻辑
  }

  private resumeVideoPlayback() {
    // 实现恢复视频播放的逻辑
  }
}

方案二:使用 ApplicationStateChangeCallback 监听应用前后台状态

[@ohos.app.ability.ApplicationStateChangeCallback (应用进程状态变化监听器)-Stage模型能力的接口-ArkTS API-Ability Kit(程序框架服务)-应用框架 - 华为HarmonyOS开发者](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-app-ability-applicationstatechangecallback)

import { UIAbility, ApplicationStateChangeCallback } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

export default class MyAbility extends UIAbility {
  onCreate() {
    console.log('MyAbility onCreate');
    
    let applicationStateChangeCallback: ApplicationStateChangeCallback = {
      onApplicationForeground() {
        console.info('applicationStateChangeCallback onApplicationForeground');
        // 应用切换到前台,恢复视频播放
        this.resumeVideoPlayback();
      },
      onApplicationBackground() {
        console.info('applicationStateChangeCallback onApplicationBackground');
        // 应用切换到后台,暂停视频播放
        this.pauseVideoPlayback();
      }
    }

    // 1.获取applicationContext
    let applicationContext = this.context.getApplicationContext();
    try {
      // 2.通过applicationContext注册应用前后台状态监听
      applicationContext.on('applicationStateChange', applicationStateChangeCallback);
    } catch (paramError) {
      console.error(`error: ${(paramError as BusinessError).code}, ${(paramError as BusinessError).message}`);
    }
    console.log('Register applicationStateChangeCallback');
  }

  onDestroy() {
    // 在销毁时取消监听
    let applicationContext = this.context.getApplicationContext();
    try {
      applicationContext.off('applicationStateChange');
    } catch (paramError) {
      console.error(`error: ${(paramError as BusinessError).code}, ${(paramError as BusinessError).message}`);
    }
  }

  private pauseVideoPlayback() {
    // 实现视频暂停逻辑
    console.info('Video playback paused due to background state');
  }

  private resumeVideoPlayback() {
    // 实现视频恢复播放逻辑
    console.info('Video playback resumed due to foreground state');
  }
}

在鸿蒙 ArkUI 中,通过Navigation跳转的二级页面监听前后台事件(如应用切后台 / 前台),需结合应用生命周期页面生命周期、组件级生命周期实现。针对 “切换后台能暂停、切换前台不能恢复” 的问题,核心是要在正确的时机触发 “恢复播放” 逻辑,以下是具体解决方案:

一、核心思路

二级页面的前后台状态变化,可通过两种生命周期机制监听:

  1. 应用级生命周期:通过AbilityonForeground(切前台)和onBackground(切后台)感知整个应用的前后台切换。
  2. 页面级生命周期:通过页面组件的onPageShow(页面显示)和onPageHide(页面隐藏)感知当前页面的显示 / 隐藏状态(包括应用前后台切换导致的显示变化)。
  3. 组件级生命周期:通过页面组件的onShown(组件显示)和onHidden(组件隐藏)感知当前组件的显示 / 隐藏状态(包括应用前后台切换导致的显示变化)。
// 页面显示时触发(包括从后台切回前台)
onShown() {
  console.log("二级页面显示/切回前台");
  // 恢复播放
  this.videoController.start();
}

// 页面隐藏时触发(包括切到后台或跳走)
onHidden() {
  console.log("二级页面隐藏/切到后台");
  // 暂停播放
  this.videoController.pause();
}

希望HarmonyOS能继续加强在安全性方面的研发,保护用户的隐私和数据安全。

也可以使用onNewWant去获取前后台状态切换,设置一个动态参数,在前后台切换时改变该参数,onNewWant监听到回到前台时继续播放

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, _launchParam: AbilityConstant.LaunchParam): void {
    ......
  }

  onNewWant(want: Want, _launchParam: AbilityConstant.LaunchParam): void {
    // 可以监听到返回前台事件

    改变参数,同时改变播放状态
    ....
  }
 }

找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17

【解决方案】

监听Navigation首页和子页面互相跳转的过程中两个页面的显示和隐藏(前台与后台),Navigation组件通常被用作Page页面的根容器,它内部默认包含标题栏、内容区域和工具栏。
在内容区域中,默认情况下,首页会展示导航内容(即Navigation的子组件),而子页面则展示NavDestination的子组件。当从首页跳转至子页面时,实际打开的是NavDestination组件,而不是一个完整的应用页面,因此不会触发应用页面特有的onPageShow和onPageHide生命周期方法。

有两种途径可以监听页面的显示和隐藏:

  • 途径1:监听NavDestination组件的显示和隐藏。
    可以使用onShown事件onHidden事件来监听NavDestination组件的显示和隐藏。示例代码如下:
NavDestination() {
  }
  .onShown(()=>{
    console.info('MyPageTwo onShown')
    //log('播放')
  })
  .onHidden(()=>{
    console.info('MyPageTwo onHidden')
    //log('暂停')
  })
  • 途径2:监听Navigation首页的显示和隐藏。
    在Navigation不使用hideNavBar隐藏导航栏的场景下,有以下三个方案来监听Navigation主页面的显示和隐藏。
    方案一:在首页的aboutToAppear函数中使用无感监听uiObserver.on(‘navDestinationSwitch’)监听页面切换。在回调函数中,如果切换的目的页面是navBar,表明切换到Navigation首页。示例代码如下:
aboutToAppear(): void {
  uiObserver.on('navDestinationSwitch', this.getUIContext(), (switchInfo) => {
    // 判断切换的目的页面是否为Navigation首页
    if (switchInfo.to === 'navBar') {
      console.info('----NavigationPage again show')
    }
  })
}

方案二:监听Navigation的onNavBarStateChange事件。在回调函数中,如果变量isVisible为true,表明首页正在显示。示例代码如下:

build() {
  Navigation(this.pageInfos) {
  }
  .title('NavigationPage')
  .onNavBarStateChange((isVisible: boolean) => {
    console.info('----isVisible:' + isVisible)
  })
}

方案三:使用@Watch装饰器监听NavPathStack路由栈对象。如果路由栈为空,则表明Navigation首页正在显示。示例代码如下:

@Provide('pageInfos') [@Watch](/user/Watch)('pathInfoChange')  pageInfos: NavPathStack = new NavPathStack()

pathInfoChange() {
  console.info('----pageInfosChange:' + this.pageInfos.size())
}

【背景知识】

您在页面播放视频时使用的是video组件还是avplayer呢?

用的video,

好的,另外提供了关于video组件切换前后台播放中断的解决方案,您看看是否能解决问题,

在鸿蒙Next中监听页面前后台事件,可在二级页面使用onPageShowonPageHide生命周期回调。示例代码:

@Entry
@Component
struct SecondPage {
  onPageShow() {
    // 处理前台事件
  }

  onPageHide() {
    // 处理后台事件
  }
}

通过navigation跳转时,这些生命周期方法会自动触发。页面进入前台执行onPageShow,进入后台执行onPageHide

在HarmonyOS Next中,可通过onPageShowonPageHide生命周期方法监听页面前后台切换。在二级页面的UI组件中实现:

onPageShow() {
  // 切回前台时恢复视频播放
  this.videoController.start();
}

onPageHide() {
  // 切换到后台时暂停播放
  this.videoController.pause();
}

确保在aboutToAppear中初始化视频控制器,在aboutToDisappear中释放资源。这种方法适用于通过navigation跳转的页面栈管理。

回到顶部