HarmonyOS Next——鸿蒙监听App前后台切换的3种方式及applicationStateChange监听失效问题

1. 利用 applicationStateChange 监听前后台变化

参考文档:

该 API 目前已知问题:

  1. pad 设备更新到 SP6 新版系统后,对应 API 前后台时不执行回调
  2. 手机设备在最新的 135 SP6 系统,依旧是正常的
  • 示例代码:
ts 复制代码
private _stateCallback?: ApplicationStateCallback
// 利用对象字面量初始化 ApplicationStateChangeCallback class
// 这是官方示例的写法,API 的设计方式比较奇怪
private _applicationStateChangeCallback: ApplicationStateChangeCallback = {
  // 换用箭头函数改变 this 指向
  onApplicationForeground: () => {
    if (this._stateCallback) {
      this._stateCallback('Foreground')
    }
  },
  onApplicationBackground: () => {
    if (this._stateCallback) {
      this._stateCallback('Background')
    }
  }
}

// 启动App前后台监听
startWatchingApplicationStateChange(callback: ApplicationStateCallback) {
  this._stateCallback = callback
  // 间接应用的应用上下文
  let applicationContext = Util.getContext().getApplicationContext()
  try {
    if (applicationContext != undefined) {
      applicationContext.on('applicationStateChange', this._applicationStateChangeCallback)
    }
  } catch (err) {
  }
}

// 停止App前后台监听
stopWatchingApplicationStateChange() {
  let applicationContext = Util.getContext().getApplicationContext()
  try {
    if (applicationContext != undefined) {
      applicationContext.off('applicationStateChange', this._applicationStateChangeCallback)
      this._stateCallback = undefined
    }
  } catch (er) {
  }
}

2. 利用 windowEvent 监听窗口生命周期变化

参考文档:

名称 说明
WINDOW_SHOWN 1 切到前台。系统能力: SystemCapability.WindowManager.WindowManager.Core。
WINDOW_ACTIVE 2 获焦状态。系统能力: SystemCapability.WindowManager.WindowManager.Core。
WINDOW_INACTIVE 3 失焦状态。系统能力: SystemCapability.WindowManager.WindowManager.Core。
WINDOW_HIDDEN 4 切到后台。系统能力: SystemCapability.WindowManager.WindowManager.Core。
WINDOW_DESTROYED11+ 7 窗口销毁。系统能力: SystemCapability.Window.SessionManager。

这里可以根据主窗口的生命周期变化,间接监听 App 的前后台事件:

ts 复制代码
// 获取 App 主窗口
const windowStage = Util.getWindowStage()
windowStage.getMainWindowSync().on('windowEvent', (windowEventType: window.WindowEventType) => {
  console.log('windowEventType: ', windowEventType)
})

pad 设备切换前后台时,窗口生命周期变化的日志对应关系:

makefile 复制代码
// App 切后台
windowEventType: 3
windowEventType: 4
// App 切前台
windowEventType: 1
windowEventType: 2

3. 利用 abilityLifecycle 监听应用生命周期

注册 abilityLifecycle 监听应用内生命周期,可以使用callback做异步回调,该 API 仅支持主线程调用。

该 API 目前已知问题:

  1. pad 设备最新版本系统,前后台对应的生命周期同样无法监听到,但可以监听到窗口失焦和获焦的状态
  2. 手机设备整体 API 表现正常

pad 设备切换前后台时,应用内生命周期变化的调试日志:

arduino 复制代码
// App 切后台
AbilityLifecycleCallback onWindowStageInactive
// App 切前台
AbilityLifecycleCallback onWillNewWant
AbilityLifecycleCallback onNewWant
AbilityLifecycleCallback onWindowStageActive

手机设备切换前后台时,相对完整的生命周期示意日志:

arduino 复制代码
// App 切后台
AbilityLifecycleCallback onWindowStageInactive
AbilityLifecycleCallback onAbilityWillBackground
AbilityLifecycleCallback onAbilityBackground
// App 切前台
AbilityLifecycleCallback onWillNewWant
AbilityLifecycleCallback onNewWant
AbilityLifecycleCallback onAbilityWillForeground
AbilityLifecycleCallback onAbilityForeground
AbilityLifecycleCallback onWindowStageActive

这里对应窗口生命周期的失焦获焦有:

  1. 注册监听应用上下文的生命周期后,在windowStage失焦时触发回调: onWindowStageInactive(ability: UIAbility, windowStage: window.WindowStage): void
  2. 注册监听应用上下文的生命周期后,在windowStage获焦时触发回调: onWindowStageActive(ability: UIAbility, windowStage: window.WindowStage): void
  3. 这两个个生命周期和 iOS 有点类似,可以临时替代前后台监听:
  • 示例代码(参考官方示例):
ts 复制代码
export enum AppState {
  AppWindowStageActive,
  AppWindowStageInactive
}

type AppStateCallback = (state: AppState, ability?: UIAbility, windowStage?: window.WindowStage) => void

// 应用内生命周期监听回调
public startWatchingAbilityLifecycle(callback: AppStateCallback) {
  // 注意 AbilityLifecycleCallback 是 class,其中某些方法是必选实现,无法用 Partial 过滤
  // 官方示例也是用对象字面量初始化的这个类(不规范)
  // 可以考虑用继承的方式过滤不必要的实现
  let callback: AbilityLifecycleCallback = {
    onAbilityCreate(ability: UIAbility) {
    },
    onWindowStageCreate(ability, windowStage) {
    },
    // 在windowStage获焦时触发回调
    onWindowStageActive: (ability, windowStage) => {
      callback?.(AppState.WindowStageActive, ability, windowStage)
    },
    // 在windowStage失焦时触发回调
    onWindowStageInactive: (ability, windowStage) => {
      callback?.(AppState.WindowStageInactive, ability, windowStage)
    },
    onWindowStageDestroy(ability, windowStage) {
    },
    onAbilityDestroy(ability) {
    },
    onAbilityForeground: (ability) => {
    },
    onAbilityBackground: (ability) => {
    },
    onAbilityContinue(ability) {
    }
  }
  let applicationContext = Util.getContext().getApplicationContext();
  try {
    this.lifecycleId = applicationContext.on('abilityLifecycle', callback);
  } catch (err) {
  }
}

// 停止App生命周期监听 
stopWatchingAbilityLifecycle() {
  let applicationContext = Util.getContext().getApplicationContext();
  try {
    applicationContext.off('abilityLifecycle', this.lifecycleId, (error, data) => {
    });
  } catch (err) {
  }
}
  • 优化后,相对符合编码规范的实现:
ts 复制代码
// 通过继承过滤方法回调
class PartialAbilityLifecycleCallback extends AbilityLifecycleCallback {
  constructor(callback: AppStateCallback) {
    super()
    this.callback = callback
  }

  callback?: AppStateCallback

  // 在windowStage获焦时触发回调
  onWindowStageActive(ability: UIAbility, windowStage: window.WindowStage) {
    super.onWindowStageActive(ability, windowStage)
    this.callback?.(AppState.WindowStageActive, ability, windowStage)
  }

  // 在windowStage失焦时触发回调
  onWindowStageInactive(ability: UIAbility, windowStage: window.WindowStage) {
    super.onWindowStageInactive(ability, windowStage)
    this.callback?.(AppState.WindowStageInactive, ability, windowStage)
  }
}

// 实现
let applicationContext = Util.getContext().getApplicationContext();
try {
  this.lifecycleId = applicationContext.on('abilityLifecycle', new PartialAbilityLifecycleCallback(callback));
} catch (err) {
}
相关推荐
Hello__77778 小时前
开源鸿蒙 Flutter 实战|消息通知功能完整实现
flutter·开源·harmonyos
高心星8 小时前
鸿蒙6.0应用开发——页面专场实践案例
华为·页面跳转·鸿蒙6.0·harmonyos6.0·页面专场·专场动画
敲代码的鱼哇10 小时前
发送短信/拨打电话/获取联系人能力 UTS 插件(cz-sms)
android·前端·ios·uni-app·安卓·harmonyos·鸿蒙
Hello__777710 小时前
开源鸿蒙 Flutter 实战|仓库评论与点赞功能完整实现
flutter·开源·harmonyos
代码飞天10 小时前
harmonyOS开发之页面跳转
华为·harmonyos
ancktion10 小时前
鸿蒙开发环境配置搭建
华为·harmonyos
nashane11 小时前
HarmonyOS 6学习:加密一致性与安全存储——AES GCM排查与SaveButton实践
学习·安全·harmonyos·harmony app
liulian091613 小时前
【Flutter for OpenHarmony第三方库】Flutter for OpenHarmony 音频播放功能适配与实现指南
flutter·华为·音视频·学习方法·harmonyos
KIHU快狐13 小时前
快狐KIHU|86寸落地触控一体机G+G电容屏HarmonyOS鸿蒙酒吧查询终端
python·华为·harmonyos
SuperHeroWu713 小时前
【小艺Claw】鸿蒙龙虾是什么?如何接入和使用?
华为·harmonyos·鸿蒙·jiuwenclaw·小艺claw