1# Subscribing to Application Events (C/C++)
2
3HiAppEvent provides APIs for subscribing to application events.
4
5## Available APIs
6For details about how to use the APIs (such as parameter usage restrictions and value ranges), see [HiAppEvent](../reference/apis-performance-analysis-kit/_hi_app_event.md#hiappevent).
7
8**Event Logging APIs**
9
10| API                                                      | Description                                |
11| ------------------------------------------------------------ | ------------------------------------ |
12| int OH_HiAppEvent_Write(const char \*domain, const char \*name, enum EventType type, const ParamList list) | Logs application events whose parameters are of the list type.|
13
14**Subscription APIs**
15
16| API                                                      | Description                                        |
17| ------------------------------------------------------------ | -------------------------------------------- |
18| int OH_HiAppEvent_AddWatcher (HiAppEvent_Watcher \*watcher)  | Adds a watcher to listen for application events.|
19| int OH_HiAppEvent_RemoveWatcher (HiAppEvent_Watcher \*watcher) | Removes a watcher to unsubscribe from application events.|
20
21## How to Develop
22
23The following describes how to log and subscribe to button onclick events.
24
251. Create a native C++ project and import the **jsoncpp** file to the project. The directory structure is as follows:
26
27   ```yml
28   entry:
29     src:
30       main:
31         cpp:
32           - json:
33               - json.h
34               - json-forwards.h
35           - types:
36               libentry:
37                 - index.d.ts
38           - CMakeLists.txt
39           - napi_init.cpp
40           - jsoncpp.cpp
41         ets:
42           - entryability:
43               - EntryAbility.ets
44           - pages:
45               - Index.ets
46   ```
47
482. In the **CMakeLists.txt** file, add the source file and dynamic libraries.
49
50   ```cmake
51   # Add the jsoncpp.cpp file, which is used to parse the JSON strings in the subscription events.
52   add_library(entry SHARED napi_init.cpp jsoncpp.cpp)
53   # Add libhiappevent_ndk.z.so and libhilog_ndk.z.so (log output). 
54   target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so libhiappevent_ndk.z.so)
55   ```
56
573. Import the dependencies to the **napi_init.cpp** file, and define **LOG_TAG**.
58
59   ```c++
60   # include "json/json.h"
61   # include "hilog/log.h"
62   # include "hiappevent/hiappevent.h"
63   
64   # undef LOG_TAG
65   # define LOG_TAG "testTag"
66   ```
67
684. Subscribe to application events.
69
70   - Watcher of the onReceive type:
71
72     In the **napi_init.cpp** file, define the methods related to the watcher of the onReceive type.
73
74     ```c++
75     static HiAppEvent_Watcher *appEventWatcher;
76     
77     static void OnReceive(const char *domain, const struct HiAppEvent_AppEventGroup *appEventGroups, uint32_t groupLen) {
78         for (int i = 0; i < groupLen; ++i) {
79             for (int j = 0; j < appEventGroups[i].infoLen; ++j) {
80                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.domain=%{public}s", appEventGroups[i].appEventInfos[j].domain);
81                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.name=%{public}s", appEventGroups[i].appEventInfos[j].name);
82                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.eventType=%{public}d", appEventGroups[i].appEventInfos[j].type);
83                 if (strcmp(appEventGroups[i].appEventInfos[j].domain, "button") == 0 &&
84                     strcmp(appEventGroups[i].appEventInfos[j].name, "click") == 0) {
85                     Json::Value params;
86                     Json::Reader reader(Json::Features::strictMode());
87                     if (reader.parse(appEventGroups[i].appEventInfos[j].params, params)) {
88                         auto time = params["click_time"].asInt64();
89                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.click_time=%{public}lld", time);
90                     }
91                 }
92             }
93         }
94     }
95     
96     static napi_value RegisterWatcher(napi_env env, napi_callback_info info) {
97         // Set the watcher name. The system identifies different watchers based on their names.
98         appEventWatcher = OH_HiAppEvent_CreateWatcher("onReceiverWatcher");
99         // Set the name of the subscribed event to click.
100         const char *names[] = {"click"};
101         // Add the system events to watch, for example, events related to button.
102         OH_HiAppEvent_SetAppEventFilter(appEventWatcher, "button", 0, names, 1);
103         // Set the implemented callback. After receiving the event, the watcher immediately triggers the OnReceive callback.
104         OH_HiAppEvent_SetWatcherOnReceive(appEventWatcher, OnReceive);
105         // Add a watcher to listen for the specified event.
106         OH_HiAppEvent_AddWatcher(appEventWatcher);
107         return {};
108     }
109     ```
110
111   - Watcher of the onTrigger type:
112
113     In the **napi_init.cpp** file, define the methods related to the watcher of the OnTrigger type.
114
115     ```c++
116     // Define a variable to cache the pointer to the created watcher.
117     static HiAppEvent_Watcher *appEventWatcher;
118     
119     // Implement the callback function used to return the listened events. The content pointed to by the events pointer is valid only in this function.
120     static void OnTake(const char *const *events, uint32_t eventLen) {
121         Json::Reader reader(Json::Features::strictMode());
122         for (int i = 0; i < eventLen; ++i) {
123             OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo=%{public}s", events[i]);
124             Json::Value eventInfo;
125             if (reader.parse(events[i], eventInfo)) {
126                 auto domain = eventInfo["domain_"].asString();
127                 auto name = eventInfo["name_"].asString();
128                 auto type = eventInfo["type_"].asInt();
129                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.domain=%{public}s", domain.c_str());
130                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.name=%{public}s", name.c_str());
131                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.eventType=%{public}d", type);
132                 if (domain == "button" && name == "click") {
133                     auto clickTime = eventInfo["click_time"].asInt64();
134                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.click_time=%{public}lld", clickTime);
135                 }
136             }
137         }
138     }
139     
140     // Implement the subscription callback function to apply custom processing to the obtained event logging data.
141     static void OnTrigger(int row, int size) {
142         // After the callback is received, obtain the specified number of received events.
143         OH_HiAppEvent_TakeWatcherData(appEventWatcher, row, OnTake);
144     }
145     
146     static napi_value RegisterWatcher(napi_env env, napi_callback_info info) {
147         // Set the watcher name. The system identifies different watchers based on their names.
148         appEventWatcher = OH_HiAppEvent_CreateWatcher("onTriggerWatcher");
149         // Set the name of the subscribed event to click.
150         const char *names[] = {"click"};
151         // Add the system events to watch, for example, events related to button.
152         OH_HiAppEvent_SetAppEventFilter(appEventWatcher, "button", 0, names, 1);
153         // Set the implemented callback function. The callback function will be triggered when the conditions set by OH_HiAppEvent_SetTriggerCondition are met.
154         OH_HiAppEvent_SetWatcherOnTrigger(appEventWatcher, OnTrigger);
155         // Set the conditions for triggering the subscription callback. For example, trigger this onTrigger callback when the number of new event logs is 1.
156         OH_HiAppEvent_SetTriggerCondition(appEventWatcher, 1, 0, 0);
157         // Add a watcher to listen for the specified event.
158         OH_HiAppEvent_AddWatcher(appEventWatcher);
159         return {};
160     }
161     ```
162
1635. In the **napi_init.cpp** file, add an API for logging button onclick events.
164
165   ```c++
166   static napi_value WriteAppEvent(napi_env env, napi_callback_info info) {
167       auto params = OH_HiAppEvent_CreateParamList();
168       OH_HiAppEvent_AddInt64Param(params, "click_time", time(nullptr));
169       OH_HiAppEvent_Write("button", "click", EventType::BEHAVIOR, params);
170       OH_HiAppEvent_DestroyParamList(params);
171       return {};
172   }
173   ```
174
1756. In the **napi_init.cpp** file, register **RegisterWatcher** and **WriteAppEvent** as ArkTS APIs.
176
177   ```c++
178   static napi_value Init(napi_env env, napi_value exports)
179   {
180       napi_property_descriptor desc[] = {
181           {"registerWatcher", nullptr, RegisterWatcher, nullptr, nullptr, nullptr, napi_default, nullptr},
182           {"writeAppEvent", nullptr, WriteAppEvent, nullptr, nullptr, nullptr, napi_default, nullptr}
183       };
184       napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
185       return exports;
186   }
187   ```
188
189   In the **index.d.ts** file, define ArkTS APIs.
190
191   ```typescript
192   export const registerWatcher: () => void;
193   export const writeAppEvent: () => void;
194   ```
195
1967. In the **EntryAbility.ets** file, add the following interface invocation to **onCreate()**.
197
198   ```typescript
199   // Import the dependent module.
200   import testNapi from 'libentry.so'
201
202   // Add the interface invocation to onCreate().
203   // Register the application event watcher at startup.
204   testNapi.registerWatcher();
205   ```
206
2078. In the **Index.ets** file, add a button to trigger the button onclick event.
208
209   ```typescript
210   import testNapi from 'libentry.so'
211
212   Button("button_click").onClick(() => {
213     testNapi.writeAppEvent();
214   })
215   ```
216
2179. You can view the processing logs of application event data in the **Log** window.
218
219   ```text
220   HiAppEvent eventInfo.domain=button
221   HiAppEvent eventInfo.name=click
222   HiAppEvent eventInfo.eventType=4
223   HiAppEvent eventInfo.params.click_time=1502031843
224   ```
225
22610. Remove the application event watcher.
227
228    ```c++
229    static napi_value RemoveWatcher(napi_env env, napi_callback_info info) {
230        // Remove the watcher.
231        OH_HiAppEvent_RemoveWatcher(appEventWatcher);
232        return {};
233    }
234    ```
235
23611. Destroy the application event watcher.
237
238    ```c++
239    static napi_value DestroyWatcher(napi_env env, napi_callback_info info) {
240        // Destroy the created watcher and set appEventWatcher to nullptr.
241        OH_HiAppEvent_DestroyWatcher(appEventWatcher);
242        appEventWatcher = nullptr;
243        return {};
244    }
245    ```
246
247<!--no_check-->