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 "napi/native_api.h"
61   #include "json/json.h"
62   #include "hilog/log.h"
63   #include "hiappevent/hiappevent.h"
64
65   #undef LOG_TAG
66   #define LOG_TAG "testTag"
67   ```
68
694. Subscribe to application events.
70
71   - Watcher of the onReceive type:
72
73     In the **napi_init.cpp** file, define the methods related to the watcher of the onReceive type.
74
75     ```c++
76     static HiAppEvent_Watcher *appEventWatcher;
77
78     static void OnReceive(const char *domain, const struct HiAppEvent_AppEventGroup *appEventGroups, uint32_t groupLen) {
79         for (int i = 0; i < groupLen; ++i) {
80             for (int j = 0; j < appEventGroups[i].infoLen; ++j) {
81                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.domain=%{public}s", appEventGroups[i].appEventInfos[j].domain);
82                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.name=%{public}s", appEventGroups[i].appEventInfos[j].name);
83                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.eventType=%{public}d", appEventGroups[i].appEventInfos[j].type);
84                 if (strcmp(appEventGroups[i].appEventInfos[j].domain, "button") == 0 &&
85                     strcmp(appEventGroups[i].appEventInfos[j].name, "click") == 0) {
86                     Json::Value params;
87                     Json::Reader reader(Json::Features::strictMode());
88                     if (reader.parse(appEventGroups[i].appEventInfos[j].params, params)) {
89                         auto time = params["click_time"].asInt64();
90                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.click_time=%{public}lld", time);
91                     }
92                 }
93             }
94         }
95     }
96
97     static napi_value RegisterWatcher(napi_env env, napi_callback_info info) {
98         // Set the watcher name. The system identifies different watchers based on their names.
99         appEventWatcher = OH_HiAppEvent_CreateWatcher("onReceiverWatcher");
100         // Set the name of the subscribed event to click.
101         const char *names[] = {"click"};
102         // Add the system events to watch, for example, events related to button.
103         OH_HiAppEvent_SetAppEventFilter(appEventWatcher, "button", 0, names, 1);
104         // Set the implemented callback. After receiving the event, the watcher immediately triggers the OnReceive callback.
105         OH_HiAppEvent_SetWatcherOnReceive(appEventWatcher, OnReceive);
106         // Add a watcher to listen for the specified event.
107         OH_HiAppEvent_AddWatcher(appEventWatcher);
108         return {};
109     }
110     ```
111
112   - Watcher of the onTrigger type:
113
114     In the **napi_init.cpp** file, define the methods related to the watcher of the OnTrigger type.
115
116     ```c++
117     // Define a variable to cache the pointer to the created watcher.
118     static HiAppEvent_Watcher *appEventWatcher;
119
120     // Implement the callback function used to return the listened events. The content pointed to by the events pointer is valid only in this function.
121     static void OnTake(const char *const *events, uint32_t eventLen) {
122         Json::Reader reader(Json::Features::strictMode());
123         for (int i = 0; i < eventLen; ++i) {
124             OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo=%{public}s", events[i]);
125             Json::Value eventInfo;
126             if (reader.parse(events[i], eventInfo)) {
127                 auto domain = eventInfo["domain_"].asString();
128                 auto name = eventInfo["name_"].asString();
129                 auto type = eventInfo["type_"].asInt();
130                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.domain=%{public}s", domain.c_str());
131                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.name=%{public}s", name.c_str());
132                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.eventType=%{public}d", type);
133                 if (domain == "button" && name == "click") {
134                     auto clickTime = eventInfo["click_time"].asInt64();
135                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.click_time=%{public}lld", clickTime);
136                 }
137             }
138         }
139     }
140
141     // Implement the subscription callback function to apply custom processing to the obtained event logging data.
142     static void OnTrigger(int row, int size) {
143         // After the callback is received, obtain the specified number of received events.
144         OH_HiAppEvent_TakeWatcherData(appEventWatcher, row, OnTake);
145     }
146
147     static napi_value RegisterWatcher(napi_env env, napi_callback_info info) {
148         // Set the watcher name. The system identifies different watchers based on their names.
149         appEventWatcher = OH_HiAppEvent_CreateWatcher("onTriggerWatcher");
150         // Set the name of the subscribed event to click.
151         const char *names[] = {"click"};
152         // Add the system events to watch, for example, events related to button.
153         OH_HiAppEvent_SetAppEventFilter(appEventWatcher, "button", 0, names, 1);
154         // Set the implemented callback function. The callback function will be triggered when the conditions set by OH_HiAppEvent_SetTriggerCondition are met.
155         OH_HiAppEvent_SetWatcherOnTrigger(appEventWatcher, OnTrigger);
156         // Set the conditions for triggering the subscription callback. For example, trigger this onTrigger callback when the number of new event logs is 1.
157         OH_HiAppEvent_SetTriggerCondition(appEventWatcher, 1, 0, 0);
158         // Add a watcher to listen for the specified event.
159         OH_HiAppEvent_AddWatcher(appEventWatcher);
160         return {};
161     }
162     ```
163
1645. In the **napi_init.cpp** file, add an API for logging button onclick events.
165
166   ```c++
167   static napi_value WriteAppEvent(napi_env env, napi_callback_info info) {
168       auto params = OH_HiAppEvent_CreateParamList();
169       OH_HiAppEvent_AddInt64Param(params, "click_time", time(nullptr));
170       OH_HiAppEvent_Write("button", "click", EventType::BEHAVIOR, params);
171       OH_HiAppEvent_DestroyParamList(params);
172       return {};
173   }
174   ```
175
1766. In the **napi_init.cpp** file, register **RegisterWatcher** and **WriteAppEvent** as ArkTS APIs.
177
178   ```c++
179   static napi_value Init(napi_env env, napi_value exports)
180   {
181       napi_property_descriptor desc[] = {
182           {"registerWatcher", nullptr, RegisterWatcher, nullptr, nullptr, nullptr, napi_default, nullptr},
183           {"writeAppEvent", nullptr, WriteAppEvent, nullptr, nullptr, nullptr, napi_default, nullptr}
184       };
185       napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
186       return exports;
187   }
188   ```
189
190   In the **index.d.ts** file, define ArkTS APIs.
191
192   ```typescript
193   export const registerWatcher: () => void;
194   export const writeAppEvent: () => void;
195   ```
196
1977. In the **EntryAbility.ets** file, add the following interface invocation to **onCreate()**.
198
199   ```typescript
200   // Import the dependent module.
201   import testNapi from 'libentry.so'
202
203   // Add the interface invocation to onCreate().
204   // Register the application event watcher at startup.
205   testNapi.registerWatcher();
206   ```
207
2088. In the **Index.ets** file, add a button to trigger the button onclick event.
209
210   ```typescript
211   import testNapi from 'libentry.so'
212
213   Button("button_click").onClick(() => {
214     testNapi.writeAppEvent();
215   })
216   ```
217
2189. You can view the processing logs of application event data in the **Log** window.
219
220   ```text
221   HiAppEvent eventInfo.domain=button
222   HiAppEvent eventInfo.name=click
223   HiAppEvent eventInfo.eventType=4
224   HiAppEvent eventInfo.params.click_time=1502031843
225   ```
226
22710. Remove the application event watcher.
228
229    ```c++
230    static napi_value RemoveWatcher(napi_env env, napi_callback_info info) {
231        // Remove the watcher.
232        OH_HiAppEvent_RemoveWatcher(appEventWatcher);
233        return {};
234    }
235    ```
236
23711. Destroy the application event watcher.
238
239    ```c++
240    static napi_value DestroyWatcher(napi_env env, napi_callback_info info) {
241        // Destroy the created watcher and set appEventWatcher to nullptr.
242        OH_HiAppEvent_DestroyWatcher(appEventWatcher);
243        appEventWatcher = nullptr;
244        return {};
245    }
246    ```
247