Skip to content

广播与事件(CommonEvent)

1. CommonEvent 概述

CommonEvent 是鸿蒙系统的发布-订阅广播机制:

┌──────────────────────────────────────────────────┐
│  CommonEvent 特性                                 │
│  ├── 发布-订阅模式:发布者不感知订阅者               │
│  ├── 系统级广播:系统事件通过 CommonEvent 广播       │
│  ├── 支持跨应用通信:不同应用通过事件名订阅           │
│  ├── 异步通信:发布后立即返回,不等待处理完成          │
│  ├── 有序/无序广播:通过 flags 区分                 │
│  └── 订阅限流:每个应用对同一事件最多订阅 100 次     │
└──────────────────────────────────────────────────┘

2. CommonEvent 发布

2.1 发布 CommonEvent

arkts
import { common } from '@kit.AbilityKit';

// 1. 发布有序事件(有序广播)
async function publishOrderedEvent() {
  const want: common.EventWant = {
    action: 'com.example.action.MY_EVENT',
    parameters: {
      key1: 'value1',
      key2: 100
    }
  };

  const publishInfo: common.PublishOptions = {
    permissions: ['ohos.permission.BROADCAST_COMMON'], // 需要权限
    flags: common.Flags.FLAG_OWNED_SYNC, // 同步等待
  };

  await common.publishEvent('com.example.action.MY_EVENT', want, publishInfo);
}

// 2. 发布无序事件(无序广播)
async function publishUnorderedEvent() {
  const want: common.EventWant = {
    action: 'com.example.action.MY_EVENT_ASYNC',
    parameters: {
      key1: 'value1'
    }
  };

  // 无序:不需要权限
  await common.publishEvent('com.example.action.MY_EVENT_ASYNC', want);
}

// 3. 发布系统事件
async function publishSystemEvent() {
  const want: common.EventWant = {
    action: 'com.huawei.system.bootup', // 系统启动事件
    parameters: {
      bootType: 'cold'
    }
  };
  await common.publishEvent(want.action, want);
}

2.2 系统内置事件

事件名(Action)说明触发时机
com.huawei.system.bootup系统启动完成开机完成后
com.huawei.intent.action.USER_PRESENT用户解锁设备解锁时
com.huawei.intent.action.ACTION_POWER_CONNECTED充电器连接插拔充电器
com.huawei.intent.action.ACTION_POWER_DISCONNECTED充电器断开拔充电器
ohos.action.internetConnectivityChange网络连通性变化网络切换时
ohos.action.timeChange时间变更时间变化
ohos.action.timezoneChange时区变更时区变化
com.huawei.intent.action.PACKAGE_ADDED应用安装安装完成
com.huawei.intent.action.PACKAGE_REMOVED应用卸载卸载完成
ohos.wifi.WIFI_STATE_CHANGEDWiFi 状态变化WiFi 开关

3. CommonEvent 订阅

3.1 订阅 CommonEvent

arkts
import { common } from '@kit.AbilityKit';

// 1. 订阅事件(需要订阅者)
interface MySubscriber extends common.Subscriber {
  onReceiveEvent(want: common.EventWant): void {
    console.log(`Received event: ${want.action}`);
    console.log(`Parameters:`, want.parameters);
  }
}

// 2. 创建订阅者
const mySubscriber: common.Subscriber = {
  wantList: [
    {
      actions: [
        'com.example.action.MY_EVENT',
        'com.example.action.MY_EVENT_ASYNC',
      ]
    }
  ],
  onReceiveEvent(want: common.EventWant) {
    console.log('Received: ' + want.action);
    console.log('Params:', want.parameters);
  }
};

// 3. 注册订阅
const subscriberId = await common.subscribe(mySubscriber);
console.log('Subscriber ID: ' + subscriberId);

// 4. 取消订阅
async function unsubscribeEvent() {
  await common.unsubscribe(subscriberId);
}

3.2 事件过滤器

arkts
// 订阅过滤器:匹配特定事件
import { common } from '@kit.AbilityKit';

const filter: common.SubscriberOptions = {
  wantList: [
    {
      actions: ['com.example.action.MY_EVENT'],
      entities: ['entity.default'],
      URI: 'uri://example.com/event',
      parameters: {
        key1: 'value1'  // 参数过滤
      }
    }
  ]
};

const subscriber = {
  wantList: filter.wantList,
  onReceiveEvent: (want: common.EventWant) => {
    // 处理匹配的事件
  }
};

const id = await common.subscribe(subscriber);

4. 权限与安全

4.1 权限要求

发布权限:
├── 无序 CommonEvent:不需要特殊权限(ohos.permission.BROADCAST_COMMON)
├── 有序 CommonEvent:需要 ohos.permission.BROADCAST_COMMON
└── 系统级事件:需要系统权限(ohos.permission.SYSTEM_BROADCAST)

订阅权限:
├── 无序事件:无需权限
├── 有序事件:需与发布方相同权限
└── 系统事件:需对应系统权限

4.2 安全限制

安全限制:
├── 事件名规范:需以应用 bundleName 为前缀(防止冲突)
├── 消息大小限制:单次事件数据不超过 1MB
├── 订阅次数限制:同一事件最多订阅 100 次/应用
├── 发布频率限制:防止滥用导致系统负载过高
└── 跨应用隔离:不可发布/订阅其他应用的私有事件

5. CommonEvent 与 Android Broadcast 对比

维度Android BroadcastReceiver鸿蒙 CommonEvent
通信模式发布-订阅发布-订阅
有序/无序有序/无序广播通过 flags 区分
权限控制权限声明 + 动态权限发布权限 + 订阅权限
事件类型Intent ActionWant Action + parameters
注册方式Manifest 静态 / 动态动态注册
执行线程主线程(可能导致 ANR)异步(不阻塞主线程)
超时限制有序广播 10s 超时无固定超时(FLAG_OWNED_SYNC)
系统事件AndroidManifest 定义CommonEvent 预定义
性能BroadcastReceiver 开销大CommonEvent 更轻量

6. 使用场景

6.1 跨 Ability 通信

arkts
// Ability A:发布事件
async function notifyAbilityB() {
  const want: common.EventWant = {
    action: 'com.example.app.ACTION_UPDATE',
    parameters: { data: 'new_data', timestamp: Date.now() }
  };
  await common.publishEvent(want.action, want);
}

// Ability B:订阅事件
const subscriber: common.Subscriber = {
  wantList: [{ actions: ['com.example.app.ACTION_UPDATE'] }],
  onReceiveEvent(want: common.EventWant) {
    const { data, timestamp } = want.parameters;
    this.refreshData(data);
    console.log(`Updated at ${timestamp}`);
  }
};
const subId = await common.subscribe(subscriber);

6.2 系统状态监听

arkts
// 监听网络状态变化
import { common } from '@kit.AbilityKit';
import { net } from '@kit.NetworkKit';

// 方式一:通过 CommonEvent 监听
const networkSubscriber: common.Subscriber = {
  wantList: [{ actions: ['ohos.action.internetConnectivityChange'] }],
  onReceiveEvent(want: common.EventWant) {
    const networkInfo = net.getNetworkInfo();
    console.log('Network: ' + networkInfo.connected);
  }
};
await common.subscribe(networkSubscriber);

// 方式二:使用 net 模块(推荐)
import { net } from '@kit.NetworkKit';
net.on('connectivityChange', (info: net.NetChangeInfo) => {
  console.log('Connected: ' + info.connected);
});

7. 🎯 面试高频考点

Q1: CommonEvent 与 Android Broadcast 的区别?

答要点

  • 执行线程:Android Broadcast 在主线程(可能 ANR),CommonEvent 异步
  • 注册方式:Android 支持静态(Manifest)和动态,鸿蒙仅支持动态注册
  • 超时处理:Android 有序广播有 10s 超时,鸿蒙无固定超时
  • 性能:CommonEvent 更轻量,广播更安全
  • 权限:CommonEvent 发布/订阅均需验证权限,更安全

Q2: CommonEvent 的有序和无序有什么区别?

答要点

  • 有序:通过 FLAG_OWNED_SYNC 等 flag 控制,按优先级顺序依次传递
  • 无序:同时传递给所有订阅者,不等待处理
  • 权限:有序需要权限,无序不需要
  • 使用场景:有序用于需要确认的场景(如系统关键事件),无序用于通知场景

Q3: CommonEvent 的订阅限制?

答要点

  • 同一应用对同一事件最多订阅 100 次
  • 事件数据不超过 1MB
  • 事件名需以 bundleName 为前缀
  • 发布无序事件无需权限,有序需要 BROADCAST_COMMON 权限
  • 系统级事件需要 SYSTEM_BROADCAST 权限

💡 面试提示:重点掌握 发布-订阅机制有序/无序区别权限控制。对比 Android Broadcast 时强调 异步执行安全性