1# 设备使用信息统计开发指导
2
3## 场景介绍
4
5设备使用信息统计,包括app usage/notification usage/system usage等使用统计。例如应用使用信息统计,用于保存和查询应用使用详情(app usage)、事件日志数据(event log)、应用分组(app group)情况。
6部件缓存的应用记录(使用历史统计和使用事件记录)会在事件上报后30分钟内刷新到数据库持久化保存。
7
8## 接口说明
9注册相关接口包导入:
10```ts
11import { usageStatistics } from '@kit.BackgroundTasksKit'
12```
13
14**表1** 设备使用信息统计主要接口
15
16| 接口名 | 描述 |
17| -------- | -------- |
18| function queryBundleEvents(begin: number, end: number, callback: AsyncCallback<Array<BundleEvents>>): void | 通过指定起始和结束时间查询所有应用的事件集合。 |
19| function queryBundleStatsInfos(begin: number, end: number, callback: AsyncCallback<BundleStatsMap>): void | 通过指定起始和结束时间查询应用使用时长统计信息。 |
20| function queryCurrentBundleEvents(begin: number, end: number, callback: AsyncCallback<Array<BundleEvents>>): void | 通过指定起始和结束时间查询当前应用的事件集合。 |
21| function queryBundleStatsInfoByInterval(byInterval: IntervalType, begin: number, end: number, callback: AsyncCallback<Array<BundleStatsInfo>>): void | 通过指定时间段间隔(天、周、月、年)查询应用使用时长统计信息。 |
22| function queryAppGroup(callback: AsyncCallback<number>): void | 查询当前应用的使用优先级群组。callback形式。 |
23| function queryAppGroup(): Promise<number>; | 查询当前应用的使用优先级群组。promise形式。 |
24|function queryAppGroupSync(): number; | 查询当前应用的使用优先级群组。同步接口。|
25| function queryAppGroup(bundleName : string, callback: AsyncCallback<number>): void | 查询指定应用的使用优先级群组。callback形式。 |
26| function queryAppGroup(bundleName : string): Promise<number>; | 查询当前调用者应用或者指定应用的使用优先级群组。promise形式。 |
27|function queryAppGroupSync(bundleName: string): number; |  查询当前调用者应用或者指定应用的使用优先级群组。同步接口。|
28| function isIdleState(bundleName: string, callback: AsyncCallback<boolean>): void | 判断指定Bundle Name的应用当前是否是空闲状态。 |
29|function isIdleStateSync(bundleName: string): boolean; | 判断指定Bundle Name的应用当前是否是空闲状态,同步接口。 |
30| function queryModuleUsageRecords(callback: AsyncCallback<HapModuleInfo>): void | 查询FA使用记录,返回不超过1000条FA使用记录。 |
31| function queryModuleUsageRecords(maxNum: number, callback: AsyncCallback<HapModuleInfo>): void | 根据maxNum,查询FA使用记录,返回不超过maxNum条FA使用记录。 maxNum不超过1000。|
32| function queryNotificationEventStats(begin: number, end: number, callback: AsyncCallback<Array<DeviceEventStats>>): void | 通过指定起始和结束时间查询所有应用的通知次数。 |
33| function queryDeviceEventStats(begin: number, end: number, callback: AsyncCallback<Array<DeviceEventStats>>): void | 通过指定起始和结束时间查询系统事件(休眠、唤醒、解锁、锁屏)统计信息。 |
34| function setAppGroup(bundleName : string, newGroup: GroupType, callback: AsyncCallback<void>): void | 给应用名是bundleName的应用分组设置成newGroup,返回设置结果是否成功,以callback形式返回。 |
35| function setAppGroup(bundleName : string, newGroup : GroupType): Promise<void>; | 给应用名是bundleName的应用分组设置成newGroup,返回设置结果是否成功,以promise形式返回。 |
36| function registerAppGroupCallBack(groupCallback: Callback<AppGroupCallbackInfo>, callback: AsyncCallback<void>): void | 注册应用分组变化监听回调,返回注册是否成功,当应用分组发生变化时,会给所有已注册的监听者返回回调信息,以callback形式返回。 |
37| function registerAppGroupCallBack(groupCallback: Callback<AppGroupCallbackInfo>): Promise<void>; | 注册应用分组变化监听回调,返回注册是否成功,当应用分组发生变化时,会给所有已注册的监听者返回回调信息,以promise形式返回。 |
38| function unregisterAppGroupCallBack(callback: AsyncCallback<void>): void | 解除应用分组监听回调,以callback形式返回。 |
39| function unregisterAppGroupCallBack(): Promise<void>; | 解除应用分组监听回调,以promise形式返回。 |
40
41## 开发步骤
42
431. 获取设备使用信息之前,需要检查是否已经配置请求相应的权限。
44    系统提供的设备使用信息统计的权限是ohos.permission.BUNDLE_ACTIVE_INFO
45    具体配置方式请参考[申请应用权限](../security/AccessToken/determine-application-mode.md#system_basic等级应用申请权限的方式)。
46
472. 通过指定起始和结束时间查询所有应用的事件集合,需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。
48
49    ```ts
50    import { BusinessError } from '@kit.BasicServicesKit';
51
52    // 异步方法promise方式
53    usageStatistics.queryBundleEvents(0, 20000000000000).then( (res : Array<usageStatistics.BundleEvents>) => {
54        console.log('BUNDLE_ACTIVE queryBundleEvents promise success.');
55        for (let i = 0; i < res.length; i++) {
56            console.log('BUNDLE_ACTIVE queryBundleEvents promise number : ' + (i + 1));
57            console.log('BUNDLE_ACTIVE queryBundleEvents promise result ' + JSON.stringify(res[i]));
58        }
59    }).catch((err : BusinessError)=> {
60        console.error('BUNDLE_ACTIVE queryBundleEvents promise failed. code is: ' + err.code + ',message is: ' + err.message);
61    });
62
63    // 异步方法callback方式
64    usageStatistics.queryBundleEvents(0, 20000000000000, (err : BusinessError, res : Array<usageStatistics.BundleEvents>) => {
65        if (err) {
66            console.log('BUNDLE_ACTIVE queryBundleEvents callback failed. code is: ' + err.code + ',message is: ' + err.message);
67        } else {
68            console.log('BUNDLE_ACTIVE queryBundleEvents callback success.');
69            for (let i = 0; i < res.length; i++) {
70                console.log('BUNDLE_ACTIVE queryBundleEvents callback number : ' + (i + 1));
71                console.log('BUNDLE_ACTIVE queryBundleEvents callback result ' + JSON.stringify(res[i]));
72            }
73        }
74    });
75    ```
76
773. 通过指定起始和结束时间查询应用使用时长统计信息,需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。
78
79    ```ts
80    import { BusinessError } from '@kit.BasicServicesKit';
81
82    // 异步方法promise方式
83    usageStatistics.queryBundleStatsInfos(0, 20000000000000).then( (res : usageStatistics.BundleStatsMap) => {
84        console.log('BUNDLE_ACTIVE queryBundleStatsInfos promise success.');
85        console.log('BUNDLE_ACTIVE queryBundleStatsInfos callback result ' + JSON.stringify(res));
86    }).catch( (err : BusinessError) => {
87        console.error('BUNDLE_ACTIVE queryBundleStatsInfos promise failed. code is: ' + err.code + ',message is: ' + err.message);
88    });
89
90    // 异步方法callback方式
91    usageStatistics.queryBundleStatsInfos(0, 20000000000000, (err : BusinessError, res : usageStatistics.BundleStatsMap) => {
92        if (err) {
93        console.log('BUNDLE_ACTIVE queryBundleStatsInfos callback failed. code is: ' + err.code + ',message is: ' + err.message);
94        } else {
95        console.log('BUNDLE_ACTIVE queryBundleStatsInfos callback success.');
96        console.log('BUNDLE_ACTIVE queryBundleStatsInfos callback result ' + JSON.stringify(res));
97        }
98    });
99    ```
100
1014. 通过指定起始和结束时间查询当前应用的事件集合,不需要配置权限。
102
103    ```ts
104    import { BusinessError } from '@kit.BasicServicesKit';
105
106    // 异步方法promise方式
107    usageStatistics.queryCurrentBundleEvents(0, 20000000000000).then( (res : Array<usageStatistics.BundleEvents>) => {
108        console.log('BUNDLE_ACTIVE queryCurrentBundleEvents promise success.');
109        for (let i = 0; i < res.length; i++) {
110        console.log('BUNDLE_ACTIVE queryCurrentBundleEvents promise number : ' + (i + 1));
111        console.log('BUNDLE_ACTIVE queryCurrentBundleEvents promise result ' + JSON.stringify(res[i]));
112        }
113    }).catch( (err : BusinessError) => {
114        console.error('BUNDLE_ACTIVE queryCurrentBundleEvents promise failed. code is: ' + err.code + ',message is: ' + err.message);
115    });
116
117    // 异步方法callback方式
118    usageStatistics.queryCurrentBundleEvents(0, 20000000000000, (err : BusinessError, res : Array<usageStatistics.BundleEvents>) => {
119        if (err) {
120        console.log('BUNDLE_ACTIVE queryCurrentBundleEvents callback failed. code is: ' + err.code + ',message is: ' + err.message);
121        } else {
122        console.log('BUNDLE_ACTIVE queryCurrentBundleEvents callback success.');
123        for (let i = 0; i < res.length; i++) {
124            console.log('BUNDLE_ACTIVE queryCurrentBundleEvents callback number : ' + (i + 1));
125            console.log('BUNDLE_ACTIVE queryCurrentBundleEvents callback result ' + JSON.stringify(res[i]));
126        }
127        }
128    });
129    ```
130
1315. 通过指定时间段间隔(天、周、月、年)查询应用使用时长统计信息,需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。
132
133    ```ts
134    import { BusinessError } from '@kit.BasicServicesKit';
135
136    // 异步方法promise方式
137    usageStatistics.queryBundleStatsInfoByInterval(0, 0, 20000000000000).then( (res : Array<usageStatistics.BundleStatsInfo>) => {
138    console.log('BUNDLE_ACTIVE queryBundleStatsInfoByInterval promise success.');
139        for (let i = 0; i < res.length; i++) {
140        console.log('BUNDLE_ACTIVE queryBundleStatsInfoByInterval promise number : ' + (i + 1));
141        console.log('BUNDLE_ACTIVE queryBundleStatsInfoByInterval promise result ' + JSON.stringify(res[i]));
142        }
143    }).catch( (err : BusinessError) => {
144        console.error('BUNDLE_ACTIVE queryBundleStatsInfoByInterval promise failed. code is: ' + err.code + ',message is: ' + err.message);
145    });
146
147    // 异步方法callback方式
148
149    usageStatistics.queryBundleStatsInfoByInterval(0, 0, 20000000000000, (err : BusinessError, res : Array<usageStatistics.BundleStatsInfo>) => {
150        if (err) {
151        console.log('BUNDLE_ACTIVE queryBundleStatsInfoByInterval callback failed. code is: ' + err.code + ',message is: ' + err.message);
152        } else {
153        console.log('BUNDLE_ACTIVE queryBundleStatsInfoByInterval callback success.');
154        for (let i = 0; i < res.length; i++) {
155            console.log('BUNDLE_ACTIVE queryBundleStatsInfoByInterval callback number : ' + (i + 1));
156            console.log('BUNDLE_ACTIVE queryBundleStatsInfoByInterval callback result ' + JSON.stringify(res[i]));
157        }
158        }
159    });
160    ```
161
1626. 查询当前应用的使用优先级群组,不需要配置权限。
163
164    ```ts
165    import { BusinessError } from '@kit.BasicServicesKit';
166
167    // promise方式
168    usageStatistics.queryAppGroup().then( (res : number) => {
169        console.log('BUNDLE_ACTIVE queryAppGroup promise succeeded. result: ' + JSON.stringify(res));
170    }).catch( (err : BusinessError) => {
171        console.error('BUNDLE_ACTIVE queryAppGroup promise failed. code is: ' + err.code + ',message is: ' + err.message);
172    });
173
174    // callback方式
175    usageStatistics.queryAppGroup((err : BusinessError, res : number) => {
176        if(err) {
177            console.log('BUNDLE_ACTIVE queryAppGroup callback failed. code is: ' + err.code + ',message is: ' + err.message);
178        } else {
179            console.log('BUNDLE_ACTIVE queryAppGroup callback succeeded. result: ' + JSON.stringify(res));
180        }
181    });
182
183    //同步方式
184    let priorityGroup = usageStatistics.queryAppGroupSync();
185
186    ```
187
1887. 判断指定Bundle Name的应用当前是否是空闲状态,需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。
189
190    ```ts
191    import { BusinessError } from '@kit.BasicServicesKit';
192
193    // 异步方法promise方式
194    usageStatistics.isIdleState("com.ohos.camera").then( (res : boolean) => {
195        console.log('BUNDLE_ACTIVE isIdleState promise succeeded, result: ' + JSON.stringify(res));
196    }).catch( (err : BusinessError) => {
197        console.error('BUNDLE_ACTIVE isIdleState promise failed. code is: ' + err.code + ',message is: ' + err.message);
198    });
199
200    // 异步方法callback方式
201    usageStatistics.isIdleState("com.ohos.camera", (err : BusinessError, res : boolean) => {
202        if (err) {
203        console.log('BUNDLE_ACTIVE isIdleState callback failed. code is: ' + err.code + ',message is: ' + err.message);
204        } else {
205        console.log('BUNDLE_ACTIVE isIdleState callback succeeded, result: ' + JSON.stringify(res));
206        }
207    });
208
209    //同步方式
210    let isIdleState = usageStatistics.isIdleStateSync("com.ohos.camera");
211    ```
212
2138. 查询FA使用记录。返回数量最大不超过maxNum设置的值,若不传入maxNum参数,则默认maxNum为1000, 需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。
214
215    ```ts
216    import { BusinessError } from '@kit.BasicServicesKit';
217
218    // 异步方法promise方式
219    usageStatistics.queryModuleUsageRecords(1000).then( (res : Array<usageStatistics.HapModuleInfo>) => {
220        console.log('BUNDLE_ACTIVE queryModuleUsageRecords promise succeeded');
221        for (let i = 0; i < res.length; i++) {
222        console.log('BUNDLE_ACTIVE queryModuleUsageRecords promise number : ' + (i + 1));
223        console.log('BUNDLE_ACTIVE queryModuleUsageRecords promise result ' + JSON.stringify(res[i]));
224        }
225    }).catch( (err : BusinessError)=> {
226        console.error('BUNDLE_ACTIVE queryModuleUsageRecords promise failed. code is: ' + err.code + ',message is: ' + err.message);
227    });
228
229    // 无maxNum参数异步方法promise方式
230    usageStatistics.queryModuleUsageRecords().then( (res : Array<usageStatistics.HapModuleInfo>) => {
231        console.log('BUNDLE_ACTIVE queryModuleUsageRecords promise succeeded');
232        for (let i = 0; i < res.length; i++) {
233        console.log('BUNDLE_ACTIVE queryModuleUsageRecords promise number : ' + (i + 1));
234        console.log('BUNDLE_ACTIVE queryModuleUsageRecords promise result ' + JSON.stringify(res[i]));
235        }
236    }).catch( (err : BusinessError)=> {
237        console.error('BUNDLE_ACTIVE queryModuleUsageRecords promise failed. code is: ' + err.code + ',message is: ' + err.message);
238    });
239
240    // 异步方法callback方式
241    usageStatistics.queryModuleUsageRecords(1000, (err : BusinessError, res : Array<usageStatistics.HapModuleInfo>) => {
242        if(err) {
243        console.log('BUNDLE_ACTIVE queryModuleUsageRecords callback failed. code is: ' + err.code + ',message is: ' + err.message);
244        } else {
245        console.log('BUNDLE_ACTIVE queryModuleUsageRecords callback succeeded.');
246        for (let i = 0; i < res.length; i++) {
247            console.log('BUNDLE_ACTIVE queryModuleUsageRecords callback number : ' + (i + 1));
248            console.log('BUNDLE_ACTIVE queryModuleUsageRecords callback result ' + JSON.stringify(res[i]));
249        }
250        }
251    });
252
253    // 无maxNum参数异步方法callback方式
254    usageStatistics.queryModuleUsageRecords((err : BusinessError, res : Array<usageStatistics.HapModuleInfo>) => {
255        if(err) {
256        console.log('BUNDLE_ACTIVE queryModuleUsageRecords callback failed. code is: ' + err.code + ',message is: ' + err.message);
257        } else {
258        console.log('BUNDLE_ACTIVE queryModuleUsageRecords callback succeeded.');
259        for (let i = 0; i < res.length; i++) {
260            console.log('BUNDLE_ACTIVE queryModuleUsageRecords callback number : ' + (i + 1));
261            console.log('BUNDLE_ACTIVE queryModuleUsageRecords callback result ' + JSON.stringify(res[i]));
262        }
263        }
264    });
265    ```
266
2679. 通过指定起始和结束时间查询所有应用的通知次数,需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。
268
269    ```ts
270    import { BusinessError } from '@kit.BasicServicesKit';
271
272    // 异步方法promise方式
273    usageStatistics.queryNotificationEventStats(0, 20000000000000).then( (res : Array<usageStatistics.DeviceEventStats>) => {
274        console.log('BUNDLE_ACTIVE queryNotificationEventStats promise success.');
275        console.log('BUNDLE_ACTIVE queryNotificationEventStats promise result ' + JSON.stringify(res));
276    }).catch( (err : BusinessError) => {
277        console.error('BUNDLE_ACTIVE queryNotificationEventStats promise failed. code is: ' + err.code + ',message is: ' + err.message);
278    });
279
280    // 异步方法callback方式
281    usageStatistics.queryNotificationEventStats(0, 20000000000000, (err : BusinessError, res : Array<usageStatistics.DeviceEventStats>) => {
282        if(err) {
283        console.log('BUNDLE_ACTIVE queryNotificationEventStats callback failed. code is: ' + err.code + ',message is: ' + err.message);
284        } else {
285        console.log('BUNDLE_ACTIVE queryNotificationEventStats callback success.');
286        console.log('BUNDLE_ACTIVE queryNotificationEventStats callback result ' + JSON.stringify(res));
287        }
288    });
289    ```
290
29110. 通过指定起始和结束时间查询系统事件(休眠、唤醒、解锁、锁屏)统计信息,需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。
292
293    ```ts
294    import { BusinessError } from '@kit.BasicServicesKit';
295
296    // 异步方法promise方式
297    usageStatistics.queryDeviceEventStats(0, 20000000000000).then( (res : Array<usageStatistics.DeviceEventStats>) => {
298        console.log('BUNDLE_ACTIVE queryDeviceEventStates promise success.');
299        console.log('BUNDLE_ACTIVE queryDeviceEventStates promise result ' + JSON.stringify(res));
300    }).catch( (err : BusinessError) => {
301        console.error('BUNDLE_ACTIVE queryDeviceEventStats promise failed. code is: ' + err.code + ',message is: ' + err.message);
302    });
303
304    // 异步方法callback方式
305    usageStatistics.queryDeviceEventStats(0, 20000000000000, (err : BusinessError, res : Array<usageStatistics.DeviceEventStats>) => {
306        if(err) {
307        console.log('BUNDLE_ACTIVE queryDeviceEventStats callback failed. code is: ' + err.code + ',message is: ' + err.message);
308        } else {
309        console.log('BUNDLE_ACTIVE queryDeviceEventStats callback success.');
310        console.log('BUNDLE_ACTIVE queryDeviceEventStats callback result ' + JSON.stringify(res));
311        }
312    });
313    ```
314
31511. 查询指定bundleName的应用的使用优先级群组,返回查询的优先级分组结果,需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。
316
317     ```ts
318    import { BusinessError } from '@kit.BasicServicesKit';
319
320    // 有bundleName异步promise方式
321    let bundleName = "com.ohos.camera";
322    usageStatistics.queryAppGroup(bundleName).then( (res : number) => {
323        console.log('BUNDLE_ACTIVE queryAppGroup promise succeeded. result: ' + JSON.stringify(res));
324    }).catch( (err : BusinessError) => {
325        console.error('BUNDLE_ACTIVE queryAppGroup promise failed. code is: ' + err.code + ',message is: ' + err.message);
326    });
327
328    // 有bundleName异步方法callback方式
329    let bundleName = "com.ohos.camera";
330    usageStatistics.queryAppGroup(bundleName, (err : BusinessError, res : number) => {
331        if(err) {
332        console.log('BUNDLE_ACTIVE queryAppGroup callback failed. code is: ' + err.code + ',message is: ' + err.message);
333        } else {
334        console.log('BUNDLE_ACTIVE queryAppGroup callback succeeded. result: ' + JSON.stringify(res));
335        }
336    });
337     ```
338
33912. 给指定bundleName的应用的优先级分组设置成newGroup。 需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。
340
341    ```ts
342    import { BusinessError } from '@kit.BasicServicesKit';
343
344    // 异步方法promise
345    let bundleName = "com.example.deviceUsageStatistics";
346    let newGroup = usageStatistics.GroupType.DAILY_GROUP;
347
348    usageStatistics.setAppGroup(bundleName, newGroup).then( () => {
349        console.log('BUNDLE_ACTIVE setAppGroup promise succeeded.');
350    }).catch( (err : BusinessError) => {
351        console.error('BUNDLE_ACTIVE setAppGroup promise failed. code is: ' + err.code + ',message is: ' + err.message);
352    });
353
354    // 异步方法callback
355    let bundleName = "com.example.deviceUsageStatistics";
356    let newGroup = usageStatistics.GroupType.DAILY_GROUP;
357    usageStatistics.setAppGroup(bundleName, newGroup, (err : BusinessError) => {
358        if(err) {
359        console.log('BUNDLE_ACTIVE setAppGroup callback failed. code is: ' + err.code + ',message is: ' + err.message);
360        } else {
361        console.log('BUNDLE_ACTIVE setAppGroup callback succeeded.');
362        }
363    });
364    ```
365
36613. 注册应用分组变化监听回调,返回注册是否成功,当应用分组发生变化时,会给所有已注册的监听者返回回调信息, 需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。
367
368    ```ts
369    import { BusinessError } from '@kit.BasicServicesKit';
370
371    // 异步方法promise形式
372    function  onBundleGroupChanged (res : usageStatistics.AppGroupCallbackInfo) {
373        console.log('BUNDLE_ACTIVE registerAppGroupCallBack RegisterGroupCallBack callback success.');
374        console.log('BUNDLE_ACTIVE registerAppGroupCallBack result appOldGroup is : ' + res.appOldGroup);
375        console.log('BUNDLE_ACTIVE registerAppGroupCallBack result appNewGroup is : ' + res.appNewGroup);
376        console.log('BUNDLE_ACTIVE registerAppGroupCallBack result changeReason is : ' + res.changeReason);
377        console.log('BUNDLE_ACTIVE registerAppGroupCallBack result userId is : ' + res.userId);
378        console.log('BUNDLE_ACTIVE registerAppGroupCallBack result bundleName is : ' + res.bundleName);
379    };
380    usageStatistics.registerAppGroupCallBack(onBundleGroupChanged).then( () => {
381        console.log('BUNDLE_ACTIVE registerAppGroupCallBack promise succeeded.');
382    }).catch( (err : BusinessError) => {
383        console.error('BUNDLE_ACTIVE registerAppGroupCallBack promise failed. code is: ' + err.code + ',message is: ' + err.message);
384    });
385
386    // 异步方法callback形式
387    function onBundleGroupChanged (res : usageStatistics.AppGroupCallbackInfo) {
388    console.log('BUNDLE_ACTIVE onBundleGroupChanged RegisterGroupCallBack callback success.');
389    console.log('BUNDLE_ACTIVE registerAppGroupCallBack result appOldGroup is : ' + res.appOldGroup);
390    console.log('BUNDLE_ACTIVE registerAppGroupCallBack result appNewGroup is : ' + res.appNewGroup);
391    console.log('BUNDLE_ACTIVE registerAppGroupCallBack result changeReason is : ' + res.changeReason);
392    console.log('BUNDLE_ACTIVE registerAppGroupCallBack result userId is : ' + res.userId);
393    console.log('BUNDLE_ACTIVE registerAppGroupCallBack result bundleName is : ' + res.bundleName);
394    };
395    usageStatistics.registerAppGroupCallBack(onBundleGroupChanged, (err : BusinessError) => {
396    if(err) {
397        console.log('BUNDLE_ACTIVE registerAppGroupCallBack callback failed. code is: ' + err.code + ',message is: ' + err.message);
398    } else {
399        console.log('BUNDLE_ACTIVE registerAppGroupCallBack callback success.');
400    }
401    });
402    ```
403
40414. 解除应用分组监听回调, 需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。
405
406    ```ts
407    import { BusinessError } from '@kit.BasicServicesKit';
408
409    // promise
410    usageStatistics.unregisterAppGroupCallBack().then( () => {
411        console.log('BUNDLE_ACTIVE unregisterAppGroupCallBack promise succeeded.');
412    }).catch( (err : BusinessError) => {
413        console.error('BUNDLE_ACTIVE unregisterAppGroupCallBack promise failed. code is: ' + err.code + ',message is: ' + err.message);
414    });
415
416    // callback
417    usageStatistics.unregisterAppGroupCallBack((err : BusinessError) => {
418        if(err) {
419        console.log('BUNDLE_ACTIVE unregisterAppGroupCallBack callback failed. code is: ' + err.code + ',message is: ' + err.message);
420        } else {
421        console.log('BUNDLE_ACTIVE unregisterAppGroupCallBack callback success.');
422        }
423    });
424    ```
425## 相关实例
426
427针对设备使用信息统计,有以下相关实例可供参考:
428
429- [存储空间统计(ArkTS)(Full SDK)(API10)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/SystemFeature/DeviceManagement/StorageStatistic)
430
431- [设备使用信息统计(ArkTS)(Full SDK)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/SystemFeature/DeviceUsageStatistics/DeviceUsageStatistics)