监听当前进程的前后台状态变化,便于进程在前后台切换时执行某些操作。例如,统计进程前后台时长、或者当进程退到后台时清理内存缓存。
当应用部分功能退后台时,系统仅挂起无活跃窗口的进程,而保持前台进程(如音乐播放)正常运行,兼顾性能与用户体验。
一、 进程与应用
在鸿蒙系统中,进程的前后台状态与应用的前后台状态是两个相关但不同的概念。
应用是基于鸿蒙分布式架构,以Ability为核心组件,可跨设备部署、调度、运行的软件程序。
应用分为传统应用和元服务两类。
一个应用可以包含一个或多个进程。
进程是系统进行资源分配的基本单位,是操作系统结构的基础。
进程分为基本进程类型和其他进程类型两类。
二、 区分进程的前后台状态与应用的前后台状态
2.1 进程的前后台状态
取决于当前进程中是否存在前台UIAbility/UIExtensionAbility或可见窗口
前台进程:
进程中至少有一个 UIAbility 处于前台(例如用户正在操作的页面)或存在可见窗口。
后台进程:
进程中所有 UIAbility 均退至后台且无可见窗口。
2.2 应用的前后台状态
取决于应用内所有进程的整体状态:
前台应用:应用下至少有一个进程处于前台状态。
后台应用:应用下所有进程均处于后台状态。
2.3 假设一个应用包含两个进程(如主进程和音乐播放进程):
场景 1:用户返回桌面(主进程退后台),但音乐仍在播放(播放进程处前台)
应用状态:前台(因播放进程在前台)
主进程状态:后台
场景 2:用户暂停音乐后返回桌面(所有进程退后台)
应用状态:后台
所有进程状态:后台
三、 监听当前进程的前后状态:ApplicationStateChangeCallback
该模块仅支持监听当前进程的前后台状态变化。
export default class ApplicationStateChangeCallback {// 当前进程从后台切换到前台时触发回调。onApplicationForeground(): void;// 当前进程从前台切换到后台时触发回调。onApplicationBackground(): void;}
调用ApplicationContext.on('applicationStateChange')方法传入自定义ApplicationStateChangeCallback来监听当前进程的前后台状态变化,从而根据进程前后台状态变化来执行某些操作。
3.1 onApplicationForeground(): void
当前进程从后台切换到前台时触发回调。
当该回调触发时,并不表示进程已完全处于前台状态,而是即将进入前台状态,此时无法执行需要依赖前台状态的操作(例如启动其他UIAbility)。
从API version 11开始,该接口支持在元服务中使用。
3.2 onApplicationBackground(): void
当前进程从前台切换到后台时触发回调。
当该回调触发时,表示进程已完全处于后台状态,可以执行适合在后台状态下完成的操作(例如清理内存缓存)。
从API version 11开始,该接口支持在元服务中使用。
3.3 实现 ApplicationStateChangeCallback
import { ApplicationStateChangeCallback, common } from '@kit.AbilityKit';import { hilog } from '@kit.PerformanceAnalysisKit';const DOMAIN = 0x0001;const TAG = "AppStatusCbOnOff";const PREFIX = "AppStsCb";export class ApplicationStatusCallbackImpl extends ApplicationStateChangeCallback {private applicationContext: common.ApplicationContext | null = null;public onApplicationStatus(applicationContext: common.ApplicationContext) {let format = '%{public}s on applicationStateChangeCallback run, appContext:%{public}s';let isNotUndefined = applicationContext != undefined;hilog.info(DOMAIN, TAG, format, PREFIX, isNotUndefined);if (applicationContext != undefined) {this.applicationContext = applicationContext;try {// 1.通过applicationContext注册当前进程状态监听this.applicationContext.on('applicationStateChange', this);let format = '%{public}s on applicationStateChange!';hilog.info(DOMAIN, TAG, format, PREFIX);} catch (paramError) {let error = paramError as BusinessErrorlet format = '%{public}s on applicationStateChange error, code:%{public}d, message:%{public}s'hilog.info(DOMAIN, TAG, format, PREFIX, error.code, error.message);}}}public offApplicationStatus() {let format = '%{public}s off applicationStateChangeCallback run. appContext:%{public}s';hilog.info(DOMAIN, TAG, format, PREFIX, this.applicationContext != undefined);if (this.applicationContext != undefined) {try {// 2.通过applicationContext注册当前进程状态监听this.applicationContext.off('applicationStateChange', this);let format = '%{public}s off applicationStateChange!';hilog.info(DOMAIN, TAG, format, PREFIX);} catch (paramError) {let error = paramError as BusinessErrorlet format = '%{public}s off applicationStateChange error, code:%{public}d, message:%{public}s'hilog.info(DOMAIN, TAG, format, PREFIX, error.code, error.message);}}}override onApplicationForeground(): void {let format = '%{public}s on onApplicationForeground.';hilog.info(DOMAIN, TAG, format, PREFIX);}override onApplicationBackground(): void {let format = '%{public}s on onApplicationBackground.';hilog.info(DOMAIN, TAG, format, PREFIX);}}
3.4 注册/解注册监听ApplicationStateChangeCallback
import { AbilityStage } from '@kit.AbilityKit';import { ApplicationStatusCallbackImpl } from 'commonlib';export default class MyAbilityStage extends AbilityStage {private appStatusCallbackImpl: ApplicationStatusCallbackImpl = new ApplicationStatusCallbackImpl();onCreate(): void {let applicationContext = this.context.getApplicationContext();this.appStatusCallbackImpl.onApplicationStatus(applicationContext);}override onDestroy(): void {super.onDestroy();this.appStatusCallbackImpl.offApplicationStatus();}}
自定义的MyAbilityStage类需要在的module.json5配置文件中,通过配置 srcEntry 参数来指定对应的代码路径,以作为HAP加载的入口。
详情见:AbilityStageContext是模块级别的上下文
B族维生素,公众号:众擎易举独力难支鸿蒙应用获取AbilityStageContext、UIAbilityContext及其他模块的Context
3.5 日志如下
I AppStsCb on applicationStateChangeCallback run, appContext:trueI AppStsCb on applicationStateChange!I AppStsCb on onApplicationForeground.I Ability onCreaterecipes I Ability onWindowStageCreaterecipes I Ability onForegroundrecipes I Succeeded in loading the content.recipes I Ability onBackgroundrecipes I AppStsCb on onApplicationBackground.recipes I Ability onWindowStageDestroyrecipes I Ability onDestroyrecipes I AppStsCb off applicationStateChangeCallback run. appContext:truerecipes I AppStsCb off applicationStateChange!
第3行:进入前台,第9行进入后台
四、 典型场景
5.1 资源释放与状态保存
应用进程退到后台时需释放内存、网络资源或暂停高耗能任务(如动画、数据传输)。
5.2 后台持续任务(如音乐播放)
应用进程需在后台持续运行(如音乐播放),需申请长时任务并监听状态变化。
5.3 网络连接管理
应用进程切后台后网络资源被冻结(约12秒释放),需重新连接或释放 Socket。
5.4 状态同步与 UI 更新
应用进程回到前台需刷新数据(如消息列表、定位信息)。
5.5 播控中心交互(AVSession)
音乐类应用需在后台同步播放状态到系统播控中心。
六、约束限制
ApplicationStateChangeCallback仅支持监听当前进程的前后台状态变化。
如果需要监听整个应用的前后台状态变化,需要使用ApplicationStateObserver,但ApplicationStateObserver不对普通应用授权,下面仅做简单介绍。
ApplicationStateObserver:监听整个应用前后台状态
ApplicationStateObserver作为入参传入appManager.on('applicationState')方法,监听应用的生命周期变化。
导入模块:import { appManager } from '@kit.AbilityKit';
需要权限:ohos.permission.RUNNING_STATE_OBSERVER
ohos.permission.RUNNING_STATE_OBSERVER为系统级别权限,需要系统授权。
从API 14开始,开放范围从系统应用变更为企业普通应用
对于非系统应用和非企业类应用
声明:ohos.permission.RUNNING_STATE_OBSERVER权限时,将导致应用安装失败
Install Failed: error: failed to install bundle.code:9568289error: install failed due to grant request permissions failed.PermissionName: ohos.permission.RUNNING_STATE_OBSERVER
企业类应用的特性:
包括:企业普通应用和MDM(Mobile Device Management)设备管理应用。
仅在企业定制设备上运行,不会在普通消费者设备上运行。
不会上架华为应用市场。
代码示例:
import { appManager } from '@kit.AbilityKit';let applicationStateObserver: appManager.ApplicationStateObserver = {onForegroundApplicationChanged(appStateData) {console.log(`[appManager] onForegroundApplicationChanged: ${JSON.stringify(appStateData)}`);},onAbilityStateChanged(abilityStateData) {console.log(`[appManager] onAbilityStateChanged: ${JSON.stringify(abilityStateData)}`);},onProcessCreated(processData) {console.log(`[appManager] onProcessCreated: ${JSON.stringify(processData)}`);},onProcessDied(processData) {console.log(`[appManager] onProcessDied: ${JSON.stringify(processData)}`);},onProcessStateChanged(processData) {console.log(`[appManager] onProcessStateChanged: ${JSON.stringify(processData)}`);},onAppStarted(appStateData) {console.log(`[appManager] onAppStarted: ${JSON.stringify(appStateData)}`);},onAppStopped(appStateData) {console.log(`[appManager] onAppStopped: ${JSON.stringify(appStateData)}`);}};let observerId: number = -1;try {observerId = appManager.on('applicationState', applicationStateObserver);console.info(`[appManager] observerCode: ${observerId}`);} catch (paramError) {let code = (paramError as BusinessError).code;let message = (paramError as BusinessError).message;console.error(`[appManager] error: ${code}, ${message}`);}function offCallback(err: BusinessError) {if (err) {console.error(`appmanager.off failed, code: ${err.code}, msg: ${err.message}`);} else {console.info(`appmanager.off success.`);}}try {appManager.off('applicationState', observerId, offCallback);console.info(`[appManager] observerCode: ${observerId}`);} catch (paramError) {let code = (paramError as BusinessError).code;let message = (paramError as BusinessError).message;console.error(`[appManager] error: ${code}, ${message}`);}
七、注意事项:资源冻结策略
在鸿蒙系统中,应用或进程切换到后台2秒后,应用的网络资源会被冻结,并且在12秒后进行释放(未申请短时任务或长时任务会导致网络资源被冻结和释放)。此时,再继续使用网络资源,就会出现网络不可用的情况。

欢迎关注公众号
长按上图识别二维码或扫一扫