常见HarmonyOS开发中CommonEvent订阅:系统事件监听

举报
Jack20 发表于 2026/06/19 18:23:03 2026/06/19
【摘要】 常见HarmonyOS开发中CommonEvent订阅:系统事件监听监听系统脉搏,让应用随系统状态而动 一、背景与动机:为什么需要监听系统事件? 1.1 响应式应用设计现代应用不能"闭门造车",需要感知系统状态:电量低时:暂停后台下载,节省电量网络断开时:提示用户,暂停网络请求屏幕关闭时:停止动画,降低刷新频率来电时:暂停音乐播放这些都是系统事件,通过CommonEvent订阅,应用可以实...

常见HarmonyOS开发中CommonEvent订阅:系统事件监听

监听系统脉搏,让应用随系统状态而动

一、背景与动机:为什么需要监听系统事件?

1.1 响应式应用设计

现代应用不能"闭门造车",需要感知系统状态:

  • 电量低时:暂停后台下载,节省电量
  • 网络断开时:提示用户,暂停网络请求
  • 屏幕关闭时:停止动画,降低刷新频率
  • 来电时:暂停音乐播放

这些都是系统事件,通过CommonEvent订阅,应用可以实时感知系统状态变化。

1.2 鸿蒙系统事件分类

1.3 系统事件 vs 自定义事件

对比项 系统事件 自定义事件
发布者 系统 应用自己
事件名 预定义常量 自定义字符串
权限 部分需要权限 无需权限
数据格式 系统定义 自定义
典型用途 响应系统状态 应用间通信

二、核心原理:系统事件订阅机制

2.1 系统事件发布流程

图片.png

2.2 事件数据结构

系统事件的数据结构是统一的:

interface CommonEventData {
    // 事件名称
    event: string
    
    // 事件数据(字符串形式)
    data: string
    
    // 事件代码(整数)
    code: number
    
    // 附加参数(键值对)
    parameters: {
        [key: string]: unknown
    }
}

不同系统事件的parameters内容不同,需要查阅文档了解具体字段。

2.3 常用系统事件列表

事件名 说明 触发时机
android.intent.action.BATTERY_CHANGED 电量变化 电量改变时
android.intent.action.BATTERY_LOW 电量低 电量低于15%时
android.intent.action.BATTERY_OKAY 电量恢复 电量恢复到正常时
android.intent.action.POWER_CONNECTED 连接电源 插入充电器时
android.intent.action.POWER_DISCONNECTED 断开电源 拔出充电器时
android.net.conn.CONNECTIVITY_CHANGE 网络变化 网络状态改变时
android.net.wifi.WIFI_STATE_CHANGED WiFi状态变化 WiFi开关状态改变时
android.intent.action.SCREEN_ON 屏幕亮起 屏幕点亮时
android.intent.action.SCREEN_OFF 屏幕关闭 屏幕熄灭时
android.intent.action.TIME_TICK 时间流逝 每分钟触发一次
android.intent.action.BOOT_COMPLETED 启动完成 系统启动完成时

三、代码实战:监听各类系统事件

3.1 电量事件监听

// BatteryEventListener.ets
import { commonEventManager, CommonEventSubscribeInfo, CommonEventData } from '@kit.BasicServicesKit'
import hilog from '@ohos.hilog'

const TAG = 'BatteryEvent'
const DOMAIN = 0xFF00

/**
 * 电量事件监听器
 */
export class BatteryEventListener {
    private subscriber: commonEventManager.CommonEventSubscriber = null
    
    // 电量状态
    private batteryLevel: number = 100
    private isCharging: boolean = false
    
    /**
     * 开始监听电量事件
     */
    async startListening(): Promise<void> {
        // 订阅多个电量相关事件
        const subscribeInfo: CommonEventSubscribeInfo = {
            events: [
                'android.intent.action.BATTERY_CHANGED',  // 电量变化
                'android.intent.action.BATTERY_LOW',     // 电量低
                'android.intent.action.BATTERY_OKAY',    // 电量恢复
                'android.intent.action.POWER_CONNECTED', // 连接电源
                'android.intent.action.POWER_DISCONNECTED' // 断开电源
            ]
        }
        
        try {
            this.subscriber = await commonEventManager.createSubscriber(subscribeInfo)
            
            this.subscriber.subscribe((err, data: CommonEventData) => {
                if (err) {
                    hilog.error(DOMAIN, TAG, `Subscribe error: ${err.message}`)
                    return
                }
                
                this.handleBatteryEvent(data)
            })
            
            hilog.info(DOMAIN, TAG, 'Battery event listener started')
        } catch (err) {
            hilog.error(DOMAIN, TAG, `Start listening failed: ${err.message}`)
        }
    }
    
    /**
     * 处理电量事件
     */
    private handleBatteryEvent(data: CommonEventData): void {
        hilog.info(DOMAIN, TAG, `Event: ${data.event}`)
        
        switch (data.event) {
            case 'android.intent.action.BATTERY_CHANGED':
                this.onBatteryChanged(data)
                break
                
            case 'android.intent.action.BATTERY_LOW':
                this.onBatteryLow(data)
                break
                
            case 'android.intent.action.BATTERY_OKAY':
                this.onBatteryOkay(data)
                break
                
            case 'android.intent.action.POWER_CONNECTED':
                this.onPowerConnected()
                break
                
            case 'android.intent.action.POWER_DISCONNECTED':
                this.onPowerDisconnected()
                break
        }
    }
    
    /**
     * 电量变化
     */
    private onBatteryChanged(data: CommonEventData): void {
        // 从parameters中提取电量信息
        const params = data.parameters
        
        // 电量百分比
        this.batteryLevel = params?.level ?? 0
        
        // 充电状态
        // status: 1=未知, 2=充电中, 3=放电中, 4=未充电, 5=充满
        const status = params?.status ?? 0
        this.isCharging = (status === 2 || status === 5)
        
        hilog.info(DOMAIN, TAG, `Battery: ${this.batteryLevel}%, Charging: ${this.isCharging}`)
        
        // 根据电量调整应用行为
        this.adjustAppBehavior()
    }
    
    /**
     * 电量低警告
     */
    private onBatteryLow(data: CommonEventData): void {
        hilog.warn(DOMAIN, TAG, 'Battery is low!')
        
        // 暂停非必要操作
        this.pauseNonEssentialTasks()
        
        // 通知用户
        this.notifyUser('电量低,已暂停后台下载')
    }
    
    /**
     * 电量恢复正常
     */
    private onBatteryOkay(data: CommonEventData): void {
        hilog.info(DOMAIN, TAG, 'Battery is okay')
        
        // 恢复操作
        this.resumeTasks()
    }
    
    /**
     * 连接电源
     */
    private onPowerConnected(): void {
        hilog.info(DOMAIN, TAG, 'Power connected')
        this.isCharging = true
        
        // 充电时可以执行更多操作
        this.enablePowerIntensiveTasks()
    }
    
    /**
     * 断开电源
     */
    private onPowerDisconnected(): void {
        hilog.info(DOMAIN, TAG, 'Power disconnected')
        this.isCharging = false
        
        // 使用电池时限制耗电操作
        this.limitPowerConsumption()
    }
    
    /**
     * 根据电量调整应用行为
     */
    private adjustAppBehavior(): void {
        if (this.batteryLevel < 20 && !this.isCharging) {
            // 低电量且未充电,进入省电模式
            this.enablePowerSavingMode()
        } else if (this.batteryLevel > 50 || this.isCharging) {
            // 电量充足或充电中,正常模式
            this.disablePowerSavingMode()
        }
    }
    
    private pauseNonEssentialTasks(): void {
        hilog.info(DOMAIN, TAG, 'Pausing non-essential tasks')
        // 实现暂停逻辑
    }
    
    private resumeTasks(): void {
        hilog.info(DOMAIN, TAG, 'Resuming tasks')
    }
    
    private enablePowerIntensiveTasks(): void {
        hilog.info(DOMAIN, TAG, 'Enabling power intensive tasks')
    }
    
    private limitPowerConsumption(): void {
        hilog.info(DOMAIN, TAG, 'Limiting power consumption')
    }
    
    private enablePowerSavingMode(): void {
        hilog.info(DOMAIN, TAG, 'Power saving mode enabled')
    }
    
    private disablePowerSavingMode(): void {
        hilog.info(DOMAIN, TAG, 'Power saving mode disabled')
    }
    
    private notifyUser(message: string): void {
        hilog.info(DOMAIN, TAG, `Notify: ${message}`)
        // 实现通知逻辑
    }
    
    /**
     * 停止监听
     */
    async stopListening(): Promise<void> {
        if (this.subscriber) {
            try {
                await this.subscriber.unsubscribe()
                hilog.info(DOMAIN, TAG, 'Battery event listener stopped')
            } catch (err) {
                hilog.error(DOMAIN, TAG, `Stop listening failed: ${err.message}`)
            }
        }
    }
    
    /**
     * 获取当前电量状态
     */
    getBatteryStatus(): { level: number, isCharging: boolean } {
        return {
            level: this.batteryLevel,
            isCharging: this.isCharging
        }
    }
}

3.2 网络事件监听

// NetworkEventListener.ets
import { commonEventManager, CommonEventSubscribeInfo, CommonEventData } from '@kit.BasicServicesKit'
import connection from '@ohos.net.connection'
import hilog from '@ohos.hilog'

const TAG = 'NetworkEvent'
const DOMAIN = 0xFF00

/**
 * 网络类型
 */
export enum NetworkType {
    NONE = 'none',
    WIFI = 'wifi',
    CELLULAR = 'cellular',
    ETHERNET = 'ethernet',
    UNKNOWN = 'unknown'
}

/**
 * 网络状态
 */
export interface NetworkStatus {
    isConnected: boolean
    type: NetworkType
    wifiName?: string
    signalStrength?: number
}

/**
 * 网络事件监听器
 */
export class NetworkEventListener {
    private subscriber: commonEventManager.CommonEventSubscriber = null
    private netConnection: connection.NetConnection = null
    
    // 当前网络状态
    private currentStatus: NetworkStatus = {
        isConnected: false,
        type: NetworkType.NONE
    }
    
    // 状态变化回调
    private onStatusChange: ((status: NetworkStatus) => void) | null = null
    
    /**
     * 设置状态变化回调
     */
    setOnStatusChange(callback: (status: NetworkStatus) => void): void {
        this.onStatusChange = callback
    }
    
    /**
     * 开始监听网络事件
     */
    async startListening(): Promise<void> {
        // 订阅网络相关事件
        const subscribeInfo: CommonEventSubscribeInfo = {
            events: [
                'android.net.conn.CONNECTIVITY_CHANGE',      // 网络连接变化
                'android.net.wifi.WIFI_STATE_CHANGED',       // WiFi状态变化
                'android.net.wifi.STATE_CHANGE',            // WiFi连接状态变化
                'android.net.wifi.SCAN_RESULTS'             // WiFi扫描结果
            ]
        }
        
        try {
            this.subscriber = await commonEventManager.createSubscriber(subscribeInfo)
            
            this.subscriber.subscribe((err, data: CommonEventData) => {
                if (err) {
                    hilog.error(DOMAIN, TAG, `Error: ${err.message}`)
                    return
                }
                
                this.handleNetworkEvent(data)
            })
            
            // 同时使用connection API获取详细状态
            await this.setupNetConnection()
            
            hilog.info(DOMAIN, TAG, 'Network event listener started')
        } catch (err) {
            hilog.error(DOMAIN, TAG, `Start failed: ${err.message}`)
        }
    }
    
    /**
     * 使用connection API监听网络
     */
    private async setupNetConnection(): Promise<void> {
        this.netConnection = connection.createNetConnection()
        
        // 注册网络可用回调
        this.netConnection.on('netAvailable', (data: connection.NetHandle) => {
            hilog.info(DOMAIN, TAG, `Network available: ${data.netId}`)
            this.updateNetworkStatus(data)
        })
        
        // 注册网络丢失回调
        this.netConnection.on('netLost', (data: connection.NetHandle) => {
            hilog.info(DOMAIN, TAG, `Network lost: ${data.netId}`)
            this.currentStatus.isConnected = false
            this.currentStatus.type = NetworkType.NONE
            this.notifyStatusChange()
        })
        
        // 注册网络不可用回调
        this.netConnection.on('netUnavailable', () => {
            hilog.info(DOMAIN, TAG, 'Network unavailable')
            this.currentStatus.isConnected = false
            this.currentStatus.type = NetworkType.NONE
            this.notifyStatusChange()
        })
    }
    
    /**
     * 处理网络事件
     */
    private handleNetworkEvent(data: CommonEventData): void {
        hilog.info(DOMAIN, TAG, `Event: ${data.event}`)
        
        switch (data.event) {
            case 'android.net.conn.CONNECTIVITY_CHANGE':
                this.onConnectivityChange(data)
                break
                
            case 'android.net.wifi.WIFI_STATE_CHANGED':
                this.onWifiStateChanged(data)
                break
                
            case 'android.net.wifi.STATE_CHANGE':
                this.onWifiConnectionChanged(data)
                break
        }
    }
    
    /**
     * 网络连接变化
     */
    private onConnectivityChange(data: CommonEventData): void {
        const params = data.parameters
        
        // networkInfo包含网络详细信息
        const isConnected = params?.networkInfo?.isConnected ?? false
        
        hilog.info(DOMAIN, TAG, `Connectivity changed, connected: ${isConnected}`)
        
        if (!isConnected) {
            // 网络断开
            this.currentStatus.isConnected = false
            this.notifyStatusChange()
        }
    }
    
    /**
     * WiFi状态变化(开关)
     */
    private onWifiStateChanged(data: CommonEventData): void {
        const params = data.parameters
        
        // wifiState: 0=正在关闭, 1=已关闭, 2=正在打开, 3=已打开
        const wifiState = params?.wifiState ?? 0
        
        hilog.info(DOMAIN, TAG, `WiFi state: ${wifiState}`)
        
        if (wifiState === 1) {
            // WiFi已关闭
            if (this.currentStatus.type === NetworkType.WIFI) {
                this.currentStatus.type = NetworkType.NONE
                this.currentStatus.isConnected = false
                this.notifyStatusChange()
            }
        }
    }
    
    /**
     * WiFi连接状态变化
     */
    private onWifiConnectionChanged(data: CommonEventData): void {
        const params = data.parameters
        
        // networkInfo包含WiFi连接信息
        const networkInfo = params?.networkInfo
        
        if (networkInfo?.isConnected) {
            this.currentStatus.type = NetworkType.WIFI
            this.currentStatus.isConnected = true
            this.currentStatus.wifiName = networkInfo?.ssid ?? ''
            this.currentStatus.signalStrength = networkInfo?.rssi ?? 0
            
            hilog.info(DOMAIN, TAG, `Connected to WiFi: ${this.currentStatus.wifiName}`)
            this.notifyStatusChange()
        }
    }
    
    /**
     * 更新网络状态
     */
    private async updateNetworkStatus(netHandle: connection.NetHandle): Promise<void> {
        try {
            // 获取网络能力
            const capabilities = await connection.getNetCapabilities(netHandle)
            
            // 判断网络类型
            if (capabilities.bearerTypes.includes(connection.BearerType.WIFI)) {
                this.currentStatus.type = NetworkType.WIFI
            } else if (capabilities.bearerTypes.includes(connection.BearerType.CELLULAR)) {
                this.currentStatus.type = NetworkType.CELLULAR
            } else if (capabilities.bearerTypes.includes(connection.BearerType.ETHERNET)) {
                this.currentStatus.type = NetworkType.ETHERNET
            } else {
                this.currentStatus.type = NetworkType.UNKNOWN
            }
            
            this.currentStatus.isConnected = true
            
            hilog.info(DOMAIN, TAG, `Network type: ${this.currentStatus.type}`)
            this.notifyStatusChange()
            
        } catch (err) {
            hilog.error(DOMAIN, TAG, `Get capabilities failed: ${err.message}`)
        }
    }
    
    /**
     * 通知状态变化
     */
    private notifyStatusChange(): void {
        hilog.info(DOMAIN, TAG, `Status changed: ${JSON.stringify(this.currentStatus)}`)
        
        if (this.onStatusChange) {
            this.onStatusChange(this.currentStatus)
        }
    }
    
    /**
     * 获取当前网络状态
     */
    getCurrentStatus(): NetworkStatus {
        return { ...this.currentStatus }
    }
    
    /**
     * 检查是否有网络
     */
    hasNetwork(): boolean {
        return this.currentStatus.isConnected
    }
    
    /**
     * 检查是否是WiFi
     */
    isWifi(): boolean {
        return this.currentStatus.type === NetworkType.WIFI
    }
    
    /**
     * 停止监听
     */
    async stopListening(): Promise<void> {
        if (this.subscriber) {
            try {
                await this.subscriber.unsubscribe()
            } catch (err) {
                hilog.error(DOMAIN, TAG, `Unsubscribe failed: ${err.message}`)
            }
        }
        
        if (this.netConnection) {
            this.netConnection.off('netAvailable')
            this.netConnection.off('netLost')
            this.netConnection.off('netUnavailable')
        }
        
        hilog.info(DOMAIN, TAG, 'Network event listener stopped')
    }
}

3.3 屏幕事件监听

// ScreenEventListener.ets
import { commonEventManager, CommonEventSubscribeInfo, CommonEventData } from '@kit.BasicServicesKit'
import hilog from '@ohos.hilog'

const TAG = 'ScreenEvent'
const DOMAIN = 0xFF00

/**
 * 屏幕状态
 */
export enum ScreenState {
    ON = 'on',
    OFF = 'off',
    UNKNOWN = 'unknown'
}

/**
 * 屏幕事件监听器
 */
export class ScreenEventListener {
    private subscriber: commonEventManager.CommonEventSubscriber = null
    private screenState: ScreenState = ScreenState.UNKNOWN
    
    // 状态变化回调
    private onScreenStateChange: ((state: ScreenState) => void) | null = null
    
    /**
     * 设置状态变化回调
     */
    setOnScreenStateChange(callback: (state: ScreenState) => void): void {
        this.onScreenStateChange = callback
    }
    
    /**
     * 开始监听屏幕事件
     */
    async startListening(): Promise<void> {
        const subscribeInfo: CommonEventSubscribeInfo = {
            events: [
                'android.intent.action.SCREEN_ON',   // 屏幕亮起
                'android.intent.action.SCREEN_OFF',  // 屏幕关闭
                'android.intent.action.USER_PRESENT' // 用户解锁
            ]
        }
        
        try {
            this.subscriber = await commonEventManager.createSubscriber(subscribeInfo)
            
            this.subscriber.subscribe((err, data: CommonEventData) => {
                if (err) {
                    hilog.error(DOMAIN, TAG, `Error: ${err.message}`)
                    return
                }
                
                this.handleScreenEvent(data)
            })
            
            hilog.info(DOMAIN, TAG, 'Screen event listener started')
        } catch (err) {
            hilog.error(DOMAIN, TAG, `Start failed: ${err.message}`)
        }
    }
    
    /**
     * 处理屏幕事件
     */
    private handleScreenEvent(data: CommonEventData): void {
        hilog.info(DOMAIN, TAG, `Event: ${data.event}`)
        
        switch (data.event) {
            case 'android.intent.action.SCREEN_ON':
                this.onScreenOn()
                break
                
            case 'android.intent.action.SCREEN_OFF':
                this.onScreenOff()
                break
                
            case 'android.intent.action.USER_PRESENT':
                this.onUserPresent()
                break
        }
    }
    
    /**
     * 屏幕亮起
     */
    private onScreenOn(): void {
        this.screenState = ScreenState.ON
        hilog.info(DOMAIN, TAG, 'Screen ON')
        
        // 恢复暂停的操作
        this.resumeOperations()
        
        this.notifyStateChange()
    }
    
    /**
     * 屏幕关闭
     */
    private onScreenOff(): void {
        this.screenState = ScreenState.OFF
        hilog.info(DOMAIN, TAG, 'Screen OFF')
        
        // 暂停不必要的操作
        this.pauseOperations()
        
        this.notifyStateChange()
    }
    
    /**
     * 用户解锁
     */
    private onUserPresent(): void {
        hilog.info(DOMAIN, TAG, 'User present (unlocked)')
        
        // 用户解锁后的操作
        this.onUserUnlocked()
    }
    
    /**
     * 恢复操作
     */
    private resumeOperations(): void {
        hilog.info(DOMAIN, TAG, 'Resuming operations')
        
        // 恢复动画
        // 恢复定时刷新
        // 恢复实时数据更新
    }
    
    /**
     * 暂停操作
     */
    private pauseOperations(): void {
        hilog.info(DOMAIN, TAG, 'Pausing operations')
        
        // 暂停动画(屏幕关闭时动画无意义)
        // 降低刷新频率
        // 暂停实时数据更新
    }
    
    /**
     * 用户解锁后
     */
    private onUserUnlocked(): void {
        // 刷新数据
        // 检查通知
        // 更新时间显示
    }
    
    /**
     * 通知状态变化
     */
    private notifyStateChange(): void {
        if (this.onScreenStateChange) {
            this.onScreenStateChange(this.screenState)
        }
    }
    
    /**
     * 获取当前屏幕状态
     */
    getScreenState(): ScreenState {
        return this.screenState
    }
    
    /**
     * 屏幕是否亮起
     */
    isScreenOn(): boolean {
        return this.screenState === ScreenState.ON
    }
    
    /**
     * 停止监听
     */
    async stopListening(): Promise<void> {
        if (this.subscriber) {
            try {
                await this.subscriber.unsubscribe()
                hilog.info(DOMAIN, TAG, 'Screen event listener stopped')
            } catch (err) {
                hilog.error(DOMAIN, TAG, `Stop failed: ${err.message}`)
            }
        }
    }
}

3.4 综合系统事件管理器

// SystemEventManager.ets
import { BatteryEventListener, NetworkEventListener, ScreenEventListener } from './EventListeners'
import hilog from '@ohos.hilog'

const TAG = 'SystemEventManager'
const DOMAIN = 0xFF00

/**
 * 系统状态
 */
export interface SystemStatus {
    battery: {
        level: number
        isCharging: boolean
    }
    network: {
        isConnected: boolean
        type: string
    }
    screen: {
        isOn: boolean
    }
}

/**
 * 系统事件管理器
 * 统一管理所有系统事件监听
 */
export class SystemEventManager {
    private batteryListener: BatteryEventListener
    private networkListener: NetworkEventListener
    private screenListener: ScreenEventListener
    
    // 当前系统状态
    private status: SystemStatus = {
        battery: { level: 100, isCharging: false },
        network: { isConnected: false, type: 'none' },
        screen: { isOn: true }
    }
    
    // 状态变化回调
    private onStatusChange: ((status: SystemStatus) => void) | null = null
    
    constructor() {
        this.batteryListener = new BatteryEventListener()
        this.networkListener = new NetworkEventListener()
        this.screenListener = new ScreenEventListener()
    }
    
    /**
     * 设置状态变化回调
     */
    setOnStatusChange(callback: (status: SystemStatus) => void): void {
        this.onStatusChange = callback
    }
    
    /**
     * 启动所有监听
     */
    async startAll(): Promise<void> {
        hilog.info(DOMAIN, TAG, 'Starting all system event listeners')
        
        // 并行启动所有监听
        await Promise.all([
            this.startBatteryListener(),
            this.startNetworkListener(),
            this.startScreenListener()
        ])
        
        hilog.info(DOMAIN, TAG, 'All listeners started')
    }
    
    /**
     * 启动电量监听
     */
    private async startBatteryListener(): Promise<void> {
        await this.batteryListener.startListening()
        
        // 定期获取状态
        setInterval(() => {
            const batteryStatus = this.batteryListener.getBatteryStatus()
            this.status.battery = batteryStatus
            this.notifyStatusChange()
        }, 60000)  // 每分钟更新一次
    }
    
    /**
     * 启动网络监听
     */
    private async startNetworkListener(): Promise<void> {
        this.networkListener.setOnStatusChange((networkStatus) => {
            this.status.network = {
                isConnected: networkStatus.isConnected,
                type: networkStatus.type
            }
            this.notifyStatusChange()
        })
        
        await this.networkListener.startListening()
    }
    
    /**
     * 启动屏幕监听
     */
    private async startScreenListener(): Promise<void> {
        this.screenListener.setOnScreenStateChange((screenState) => {
            this.status.screen.isOn = (screenState === 'on')
            this.notifyStatusChange()
        })
        
        await this.screenListener.startListening()
    }
    
    /**
     * 通知状态变化
     */
    private notifyStatusChange(): void {
        hilog.info(DOMAIN, TAG, `System status: ${JSON.stringify(this.status)}`)
        
        if (this.onStatusChange) {
            this.onStatusChange(this.status)
        }
    }
    
    /**
     * 获取当前系统状态
     */
    getStatus(): SystemStatus {
        return { ...this.status }
    }
    
    /**
     * 检查是否应该执行耗电操作
     */
    shouldRunPowerIntensiveTask(): boolean {
        const { battery, network, screen } = this.status
        
        // 充电中或电量充足
        const hasPower = battery.isCharging || battery.level > 30
        
        // 有网络连接
        const hasNetwork = network.isConnected
        
        // 屏幕亮起
        const screenActive = screen.isOn
        
        return hasPower && hasNetwork && screenActive
    }
    
    /**
     * 检查是否应该执行后台任务
     */
    shouldRunBackgroundTask(): boolean {
        const { battery, network } = this.status
        
        // 电量充足或充电中
        const hasPower = battery.isCharging || battery.level > 20
        
        // 有网络连接
        const hasNetwork = network.isConnected
        
        return hasPower && hasNetwork
    }
    
    /**
     * 停止所有监听
     */
    async stopAll(): Promise<void> {
        hilog.info(DOMAIN, TAG, 'Stopping all listeners')
        
        await Promise.all([
            this.batteryListener.stopListening(),
            this.networkListener.stopListening(),
            this.screenListener.stopListening()
        ])
        
        hilog.info(DOMAIN, TAG, 'All listeners stopped')
    }
}

/**
 * 在UI组件中使用
 */
@Entry
@Component
struct SystemStatusPage {
    @State systemStatus: SystemStatus = {
        battery: { level: 100, isCharging: false },
        network: { isConnected: false, type: 'none' },
        screen: { isOn: true }
    }
    
    private eventManager: SystemEventManager = new SystemEventManager()
    
    async aboutToAppear() {
        // 设置状态变化回调
        this.eventManager.setOnStatusChange((status) => {
            this.systemStatus = status
        })
        
        // 启动监听
        await this.eventManager.startAll()
    }
    
    async aboutToDisappear() {
        await this.eventManager.stopAll()
    }
    
    build() {
        Column() {
            Text('系统状态监控')
                .fontSize(24)
                .fontWeight(FontWeight.Bold)
                .margin({ bottom: 20 })
            
            // 电量状态
            Row() {
                Text('电量:')
                    .width(80)
                Text(`${this.systemStatus.battery.level}%`)
                if (this.systemStatus.battery.isCharging) {
                    Text(' (充电中)')
                        .fontColor(Color.Green)
                }
            }
            .width('100%')
            .margin({ bottom: 10 })
            
            // 网络状态
            Row() {
                Text('网络:')
                    .width(80)
                if (this.systemStatus.network.isConnected) {
                    Text(`${this.systemStatus.network.type}`)
                        .fontColor(Color.Green)
                } else {
                    Text('无网络')
                        .fontColor(Color.Red)
                }
            }
            .width('100%')
            .margin({ bottom: 10 })
            
            // 屏幕状态
            Row() {
                Text('屏幕:')
                    .width(80)
                Text(this.systemStatus.screen.isOn ? '亮起' : '关闭')
            }
            .width('100%')
        }
        .width('100%')
        .height('100%')
        .padding(20)
    }
}

四、踩坑与注意事项

4.1 坑一:权限不足

问题:部分系统事件需要系统签名或特殊权限。

// ❌ 普通应用无法订阅某些系统事件
await commonEventManager.createSubscriber({
    events: ['android.intent.action.BOOT_COMPLETED']  // 需要系统权限
})

// ✅ 检查权限并优雅降级
async function safeSubscribe() {
    try {
        const subscriber = await commonEventManager.createSubscriber({
            events: ['android.intent.action.BOOT_COMPLETED']
        })
        
        subscriber.subscribe((err, data) => {
            if (err) {
                if (err.code === 201 || err.code === 202) {
                    // 权限不足,使用替代方案
                    hilog.warn(DOMAIN, TAG, 'Permission denied, using alternative')
                    useAlternativeApproach()
                }
                return
            }
            
            // 处理事件
        })
    } catch (err) {
        hilog.error(DOMAIN, TAG, `Subscribe failed: ${err.message}`)
    }
}

4.2 坑二:事件数据格式变化

问题:不同系统版本,事件数据格式可能不同。

// ❌ 假设数据格式固定
const level = data.parameters.level  // 可能不存在

// ✅ 安全访问数据
function safeGetBatteryLevel(data: CommonEventData): number {
    const params = data.parameters
    
    // 多种方式获取
    if (params?.level !== undefined) {
        return params.level
    }
    
    // 从data字符串解析
    if (data.data) {
        try {
            const parsed = JSON.parse(data.data)
            return parsed.level ?? 0
        } catch (e) {
            // 解析失败
        }
    }
    
    // 默认值
    return 0
}

4.3 坑三:回调在非主线程

问题:CommonEvent回调可能在Binder线程,不能直接更新UI。

// ❌ 在回调中直接更新UI
this.subscriber.subscribe((err, data) => {
    this.batteryLevel = data.parameters.level  // 可能不在主线程
})

// ✅ 使用EventHandler转发到主线程
import { EventHandler, EventRunner } from '@kit.BasicServicesKit'

class SafeSubscriber {
    private mainHandler: EventHandler
    
    constructor() {
        const mainRunner = EventRunner.getMainEventRunner()
        this.mainHandler = new EventHandler(mainRunner)
    }
    
    async subscribe() {
        this.subscriber.subscribe((err, data) => {
            // 转发到主线程
            this.mainHandler.sendEvent({
                eventId: 1,
                param: data
            })
        })
    }
}

4.4 坑四:重复订阅

问题:多次调用订阅会收到多次回调。

// ❌ 多次订阅
async subscribeMultiple() {
    await this.subscriber.subscribe(callback)
    await this.subscriber.subscribe(callback)  // 会收到两次回调
}

// ✅ 使用标志位防止重复
class SingleSubscriber {
    private isSubscribed: boolean = false
    
    async subscribe() {
        if (this.isSubscribed) {
            hilog.warn(DOMAIN, TAG, 'Already subscribed')
            return
        }
        
        await this.subscriber.subscribe(callback)
        this.isSubscribed = true
    }
    
    async unsubscribe() {
        if (!this.isSubscribed) {
            return
        }
        
        await this.subscriber.unsubscribe()
        this.isSubscribed = false
    }
}

五、HarmonyOS 6适配指南

5.1 API变更

变更项 HarmonyOS 5 HarmonyOS 6
导入方式 @ohos.commonEvent @kit.BasicServicesKit
订阅返回 同步返回 Promise异步
错误处理 回调参数 独立error事件

5.2 新增功能

// HarmonyOS 6新增:事件过滤
const subscribeInfo: CommonEventSubscribeInfo = {
    events: ['android.intent.action.BATTERY_CHANGED'],
    
    // 过滤特定设备
    publisherDeviceId: 'local',
    
    // 过滤特定UID
    publisherUid: 1001,
    
    // 设置优先级
    priority: 100
}

// HarmonyOS 6新增:获取粘性事件
const subscribeInfo: CommonEventSubscribeInfo = {
    events: ['android.intent.action.BATTERY_CHANGED'],
    
    // 订阅时立即获取粘性事件
    getStickEvent: true
}

六、总结

6.1 核心要点回顾

图片.png

6.2 最佳实践清单

  • [ ] 处理权限不足的情况
  • [ ] 安全访问事件数据
  • [ ] 使用EventHandler转发到主线程
  • [ ] 防止重复订阅
  • [ ] 组件销毁时取消订阅
  • [ ] 使用统一管理器管理所有监听
  • [ ] 根据系统状态调整应用行为

下一篇预告:《粘性事件:延迟事件处理》——深入粘性事件机制,实现延迟订阅场景。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。