• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 事件订阅(ArkTS)
2
3<!--Kit: Performance Analysis Kit-->
4<!--Subsystem: HiviewDFX-->
5<!--Owner: @liujiaxing2024-->
6<!--Designer: @junjie_shi-->
7<!--Tester: @gcw_KuLfPSbe-->
8<!--Adviser: @foryourself-->
9
10HiAppEvent提供了事件订阅接口,用于获取应用的事件。
11
12## 接口说明
13
14API接口使用说明,包括参数使用限制和具体取值范围。请参考[@ohos.hiviewdfx.hiAppEvent (应用事件打点)ArkTS API文档](../reference/apis-performance-analysis-kit/js-apis-hiviewdfx-hiappevent.md)。
15
16**订阅接口功能介绍**:
17
18| 接口名 | 描述 |
19| -------- | -------- |
20| addWatcher(watcher: Watcher): AppEventPackageHolder | 添加应用的事件观察者。 |
21| removeWatcher(watcher: Watcher): void | 移除应用的事件观察者。 |
22
23> **说明**
24>
25> addWatcher接口涉及I/O操作。在对性能敏感的业务场景中,开发者应根据实际需要确定该接口是在主线程还是在子线程中调用。
26>
27> 如果选择在子线程中调用addWatcher,需要确保该子线程在整个接口使用周期内不会被销毁,以免影响接口的正常工作。
28>
29> 可参考[多线程并发概述](../arkts-utils/multi-thread-concurrency-overview.md),以实现在子线程中调用接口。
30
31**打点接口功能介绍**:
32
33| 接口名 | 描述 |
34| -------- | -------- |
35| write(info: AppEventInfo, callback: AsyncCallback&lt;void>): void | 应用事件异步打点方法,使用callback方式作为异步回调。 |
36| write(info: AppEventInfo): Promise&lt;void> | 应用事件异步打点方法,使用Promise方式作为异步回调。 |
37
38> **说明**
39>
40> write接口涉及I/O操作,执行时间通常在毫秒级别。因此,开发者应根据实际业务需求,确定该接口是在主线程还是在子线程中调用。
41>
42> 可参考[多线程并发概述](../arkts-utils/multi-thread-concurrency-overview.md),以实现在子线程中调用接口。
43
44## 事件订阅开发指导
45
46以订阅崩溃事件(系统事件)和按钮点击事件(应用事件)为例,说明开发步骤。
47
481. 新建一个ArkTS应用工程,编辑工程中的“entry > src > main > ets  > entryability > EntryAbility.ets”文件,导入所需的依赖模块:
49
50   ```ts
51   import { hiAppEvent, hilog } from '@kit.PerformanceAnalysisKit';
52   ```
53
542. 编辑工程中的“entry > src > main > ets  > entryability > EntryAbility.ets” 文件,在onCreate函数中添加对崩溃事件、按钮点击事件的订阅。
55
56   订阅崩溃事件,采用OnReceive类型观察者的订阅方式,观察者接收到事件后会立即触发OnReceive()回调。编辑“EntryAbility.ets”文件,定义OnReceive类型观察者相关方法:
57
58   ```ts
59   hiAppEvent.addWatcher({
60     // 开发者可以自定义观察者名称,系统会使用名称来标识不同的观察者
61     name: "AppCrashWatcher",
62     // 订阅过滤条件,这里是订阅了系统事件中的崩溃事件
63     appEventFilters: [
64       {
65         domain: hiAppEvent.domain.OS,
66         names: [hiAppEvent.event.APP_CRASH]
67       }
68     ],
69     // 实现onReceive回调,监听到事件后实时回调
70     onReceive: (domain: string, appEventGroups: Array<hiAppEvent.AppEventGroup>) => {
71       hilog.info(0x0000, 'testTag', `domain=${domain}`);
72       for (const eventGroup of appEventGroups) {
73         hilog.info(0x0000, 'testTag', `HiAppEvent eventName=${eventGroup.name}`);
74         for (const eventInfo of eventGroup.appEventInfos) {
75           // 开发者可以获取到崩溃事件发生的时间戳
76           hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.time=${JSON.stringify(eventInfo.params['time'])}`);
77           // 开发者可以获取到崩溃应用的包名
78           hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.bundle_name=${JSON.stringify(eventInfo.params['bundle_name'])}`);
79           // 开发者可以获取到崩溃事件发生时的故障日志文件
80           hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.external_log=${JSON.stringify(eventInfo.params['external_log'])}`);
81         }
82       }
83     }
84   });
85   ```
86
87   订阅按钮点击事件,采用OnTrigger类型观察者的订阅方式。需满足triggerCondition设置的条件,才能触发OnTrigger()回调。编辑“EntryAbility.ets”文件,定义OnTrigger类型观察者相关方法:
88
89   ```ts
90   hiAppEvent.addWatcher({
91     // 开发者可以自定义观察者名称,系统会使用名称来标识不同的观察者
92     name: "ButtonClickWatcher",
93     // 开发者可以订阅感兴趣的应用事件,此处是订阅了按钮事件
94     appEventFilters: [{ domain: "button" }],
95     // 开发者可以设置订阅回调触发的条件,此处是设置为事件打点数量满足1个
96     triggerCondition: { row: 1 },
97     // 开发者可以自行实现订阅回调函数,以便对订阅获取到的事件打点数据进行自定义处理
98     onTrigger: (curRow: number, curSize: number, holder: hiAppEvent.AppEventPackageHolder) => {
99       // 如果返回的holder对象为null,表示订阅过程发生异常。因此,在记录错误日志后直接返回
100       if (holder == null) {
101         hilog.error(0x0000, 'testTag', "HiAppEvent holder is null");
102         return;
103       }
104       hilog.info(0x0000, 'testTag', `HiAppEvent onTrigger: curRow=%{public}d, curSize=%{public}d`, curRow, curSize);
105       let eventPkg: hiAppEvent.AppEventPackage | null = null;
106       // 根据设置阈值大小(默认为1条事件)去获取订阅事件包,直到将订阅数据全部取出
107       // 返回的事件包对象为null,表示当前订阅数据已被全部取出,此次订阅回调触发结束
108       while ((eventPkg = holder.takeNext()) != null) {
109         // 开发者可以对事件包中的事件打点数据进行自定义处理,此处是将事件打点数据打印在日志中
110         hilog.info(0x0000, 'testTag', `HiAppEvent eventPkg.packageId=%{public}d`, eventPkg.packageId);
111         hilog.info(0x0000, 'testTag', `HiAppEvent eventPkg.row=%{public}d`, eventPkg.row);
112         hilog.info(0x0000, 'testTag', `HiAppEvent eventPkg.size=%{public}d`, eventPkg.size);
113         for (const eventInfo of eventPkg.data) {
114           hilog.info(0x0000, 'testTag', `HiAppEvent eventPkg.info=%{public}s`, eventInfo);
115         }
116       }
117     }
118   });
119   ```
120
1213. 编辑工程中的“entry > src > main > ets  > pages > Index.ets” 文件,导入依赖模块:
122
123   ```ts
124   import { BusinessError } from '@kit.BasicServicesKit';
125   import { hiAppEvent, hilog } from '@kit.PerformanceAnalysisKit';
126   ```
127
1284. 编辑工程中的“entry > src > main > ets  > pages > Index.ets” 文件,新增“appCrash”按钮触发崩溃事件;新增“buttonClick”按钮,在按钮点击的函数中进行事件打点。示例代码如下:
129
130   触发崩溃事件。
131
132   ```ts
133     Button("appCrash")
134       .onClick(()=>{
135         // 在按钮点击函数中构造一个crash场景,触发崩溃事件
136         let result: object = JSON.parse("");
137       })
138       .position({ x: 50, y: 100 }) // 设置按钮位置
139   ```
140
141   在按钮点击的函数中进行事件打点。
142
143   ```ts
144     Button("buttonClick")
145       .onClick(()=>{
146         // 在按钮点击函数中进行事件打点,以记录按钮点击事件
147         let eventParams: Record<string, number> = { "click_time": 100 };
148         let eventInfo: hiAppEvent.AppEventInfo = {
149           // 事件领域定义
150           domain: "button",
151           // 事件名称定义
152           name: "click",
153           // 事件类型定义
154           eventType: hiAppEvent.EventType.BEHAVIOR,
155           // 事件参数定义
156           params: eventParams
157         };
158         hiAppEvent.write(eventInfo).then(() => {
159           hilog.info(0x0000, 'testTag', `HiAppEvent success to write event`);
160         }).catch((err: BusinessError) => {
161           hilog.error(0x0000, 'testTag', `HiAppEvent err.code: ${err.code}, err.message: ${err.message}`);
162         });
163         hilog.info(0x0000, 'testTag', `HiAppEvent write event`);
164       })
165       .position({ x: 50, y: 200 }) // 设置按钮的位置
166   ```
167
168## 调测验证
169
1701. 点击DevEco Studio界面中的运行按钮,运行应用工程。在应用界面中点击“appCrash”按钮,触发崩溃事件。应用退出后,重新打开应用。
171
1722. 在HiLog窗口搜索“HiAppEvent”关键字,查看应用处理崩溃事件数据的日志:
173
174   ```text
175   HiAppEvent eventName=APP_CRASH
176   HiAppEvent eventInfo.params.time=1750747995874
177   HiAppEvent eventInfo.params.bundle_name="com.example.txxxxx"
178   HiAppEvent eventInfo.params.external_log=
179   ["/data/storage/el2/log/hiappevent/APP_CRASH_1750747996042_28962.log"]
180   ```
181
1823. 点击DevEco Studio界面中的运行按钮,运行应用工程。在应用界面中点击“buttonClick”按钮,触发按钮点击事件并打点。
183
1844. 在HiLog窗口搜索“HiAppEvent”关键字,查看应用处理按钮点击事件数据的日志:
185
186   ```text
187   HiAppEvent write event
188   HiAppEvent onTrigger: curRow=1, curSize=121
189   HiAppEvent eventPkg.packageId=0
190   HiAppEvent eventPkg.row=1
191   HiAppEvent eventPkg.size=121
192   HiAppEvent eventPkg.info={"domain_":"button","name_":"click","type_":4,"time_":1750754529033,"tz_":"","pid_":40664,"tid_":40664,"click_time":100}
193   HiAppEvent success to write event
194   ```
195