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 '@ohos.resourceschedule.usageStatistics'; 12``` 13 14开发步骤中使用的接口具体请参考[设备使用信息统计API](../reference/apis/js-apis-resourceschedule-deviceUsageStatistics.md)文档。 15 16## 开发步骤 17 181. 获取设备使用信息之前,需要检查是否已经配置请求相应的权限。系统提供的设备使用信息统计的权限是ohos.permission.BUNDLE_ACTIVE_INFO,具体配置方式请参考[权限申请声明](../security/accesstoken-guidelines.md)。 19 202. 通过指定起始和结束时间查询所有应用的事件集合,需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。 21 22 ```ts 23 import { BusinessError } from '@ohos.base'; 24 25 // 异步方法promise方式 26 usageStatistics.queryBundleEvents(0, 20000000000000).then( (res : Array<usageStatistics.BundleEvents>) => { 27 console.log('BUNDLE_ACTIVE queryBundleEvents promise success.'); 28 for (let i = 0; i < res.length; i++) { 29 console.log('BUNDLE_ACTIVE queryBundleEvents promise number : ' + (i + 1)); 30 console.log('BUNDLE_ACTIVE queryBundleEvents promise result ' + JSON.stringify(res[i])); 31 } 32 }).catch((err : BusinessError)=> { 33 console.error('BUNDLE_ACTIVE queryBundleEvents promise failed. code is: ' + err.code + ',message is: ' + err.message); 34 }); 35 36 // 异步方法callback方式 37 usageStatistics.queryBundleEvents(0, 20000000000000, (err : BusinessError, res : Array<usageStatistics.BundleEvents>) => { 38 if (err) { 39 console.log('BUNDLE_ACTIVE queryBundleEvents callback failed. code is: ' + err.code + ',message is: ' + err.message); 40 } else { 41 console.log('BUNDLE_ACTIVE queryBundleEvents callback success.'); 42 for (let i = 0; i < res.length; i++) { 43 console.log('BUNDLE_ACTIVE queryBundleEvents callback number : ' + (i + 1)); 44 console.log('BUNDLE_ACTIVE queryBundleEvents callback result ' + JSON.stringify(res[i])); 45 } 46 } 47 }); 48 ``` 49 503. 通过指定起始和结束时间查询应用使用时长统计信息,需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。 51 52 ```ts 53 import { BusinessError } from '@ohos.base'; 54 55 // 异步方法promise方式 56 usageStatistics.queryBundleStatsInfos(0, 20000000000000).then( (res : usageStatistics.BundleStatsMap) => { 57 console.log('BUNDLE_ACTIVE queryBundleStatsInfos promise success.'); 58 console.log('BUNDLE_ACTIVE queryBundleStatsInfos callback result ' + JSON.stringify(res)); 59 }).catch( (err : BusinessError) => { 60 console.error('BUNDLE_ACTIVE queryBundleStatsInfos promise failed. code is: ' + err.code + ',message is: ' + err.message); 61 }); 62 63 // 异步方法callback方式 64 usageStatistics.queryBundleStatsInfos(0, 20000000000000, (err : BusinessError, res : usageStatistics.BundleStatsMap) => { 65 if (err) { 66 console.log('BUNDLE_ACTIVE queryBundleStatsInfos callback failed. code is: ' + err.code + ',message is: ' + err.message); 67 } else { 68 console.log('BUNDLE_ACTIVE queryBundleStatsInfos callback success.'); 69 console.log('BUNDLE_ACTIVE queryBundleStatsInfos callback result ' + JSON.stringify(res)); 70 } 71 }); 72 ``` 73 744. 通过指定起始和结束时间查询当前应用的事件集合,不需要配置权限。 75 76 ```ts 77 import { BusinessError } from '@ohos.base'; 78 79 // 异步方法promise方式 80 usageStatistics.queryCurrentBundleEvents(0, 20000000000000).then( (res : Array<usageStatistics.BundleEvents>) => { 81 console.log('BUNDLE_ACTIVE queryCurrentBundleEvents promise success.'); 82 for (let i = 0; i < res.length; i++) { 83 console.log('BUNDLE_ACTIVE queryCurrentBundleEvents promise number : ' + (i + 1)); 84 console.log('BUNDLE_ACTIVE queryCurrentBundleEvents promise result ' + JSON.stringify(res[i])); 85 } 86 }).catch( (err : BusinessError) => { 87 console.error('BUNDLE_ACTIVE queryCurrentBundleEvents promise failed. code is: ' + err.code + ',message is: ' + err.message); 88 }); 89 90 // 异步方法callback方式 91 usageStatistics.queryCurrentBundleEvents(0, 20000000000000, (err : BusinessError, res : Array<usageStatistics.BundleEvents>) => { 92 if (err) { 93 console.log('BUNDLE_ACTIVE queryCurrentBundleEvents callback failed. code is: ' + err.code + ',message is: ' + err.message); 94 } else { 95 console.log('BUNDLE_ACTIVE queryCurrentBundleEvents callback success.'); 96 for (let i = 0; i < res.length; i++) { 97 console.log('BUNDLE_ACTIVE queryCurrentBundleEvents callback number : ' + (i + 1)); 98 console.log('BUNDLE_ACTIVE queryCurrentBundleEvents callback result ' + JSON.stringify(res[i])); 99 } 100 } 101 }); 102 ``` 103 1045. 通过指定时间段间隔(天、周、月、年)查询应用使用时长统计信息,需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。 105 106 ```ts 107 import { BusinessError } from '@ohos.base'; 108 109 // 异步方法promise方式 110 usageStatistics.queryBundleStatsInfoByInterval(0, 0, 20000000000000).then( (res : Array<usageStatistics.BundleStatsInfo>) => { 111 console.log('BUNDLE_ACTIVE queryBundleStatsInfoByInterval promise success.'); 112 for (let i = 0; i < res.length; i++) { 113 console.log('BUNDLE_ACTIVE queryBundleStatsInfoByInterval promise number : ' + (i + 1)); 114 console.log('BUNDLE_ACTIVE queryBundleStatsInfoByInterval promise result ' + JSON.stringify(res[i])); 115 } 116 }).catch( (err : BusinessError) => { 117 console.error('BUNDLE_ACTIVE queryBundleStatsInfoByInterval promise failed. code is: ' + err.code + ',message is: ' + err.message); 118 }); 119 120 // 异步方法callback方式 121 122 usageStatistics.queryBundleStatsInfoByInterval(0, 0, 20000000000000, (err : BusinessError, res : Array<usageStatistics.BundleStatsInfo>) => { 123 if (err) { 124 console.log('BUNDLE_ACTIVE queryBundleStatsInfoByInterval callback failed. code is: ' + err.code + ',message is: ' + err.message); 125 } else { 126 console.log('BUNDLE_ACTIVE queryBundleStatsInfoByInterval callback success.'); 127 for (let i = 0; i < res.length; i++) { 128 console.log('BUNDLE_ACTIVE queryBundleStatsInfoByInterval callback number : ' + (i + 1)); 129 console.log('BUNDLE_ACTIVE queryBundleStatsInfoByInterval callback result ' + JSON.stringify(res[i])); 130 } 131 } 132 }); 133 ``` 134 1356. 查询当前应用的使用优先级群组,不需要配置权限。 136 137 ```ts 138 import { BusinessError } from '@ohos.base'; 139 140 // promise方式 141 usageStatistics.queryAppGroup().then( (res : number) => { 142 console.log('BUNDLE_ACTIVE queryAppGroup promise succeeded. result: ' + JSON.stringify(res)); 143 }).catch( (err : BusinessError) => { 144 console.error('BUNDLE_ACTIVE queryAppGroup promise failed. code is: ' + err.code + ',message is: ' + err.message); 145 }); 146 147 // callback方式 148 usageStatistics.queryAppGroup((err : BusinessError, res : number) => { 149 if(err) { 150 console.log('BUNDLE_ACTIVE queryAppGroup callback failed. code is: ' + err.code + ',message is: ' + err.message); 151 } else { 152 console.log('BUNDLE_ACTIVE queryAppGroup callback succeeded. result: ' + JSON.stringify(res)); 153 } 154 }); 155 156 //同步方式 157 let priorityGroup = usageStatistics.queryAppGroupSync(); 158 159 ``` 160 1617. 判断指定Bundle Name的应用当前是否是空闲状态,需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。 162 163 ```ts 164 import { BusinessError } from '@ohos.base'; 165 166 // 异步方法promise方式 167 usageStatistics.isIdleState("com.ohos.camera").then( (res : boolean) => { 168 console.log('BUNDLE_ACTIVE isIdleState promise succeeded, result: ' + JSON.stringify(res)); 169 }).catch( (err : BusinessError) => { 170 console.error('BUNDLE_ACTIVE isIdleState promise failed. code is: ' + err.code + ',message is: ' + err.message); 171 }); 172 173 // 异步方法callback方式 174 usageStatistics.isIdleState("com.ohos.camera", (err : BusinessError, res : boolean) => { 175 if (err) { 176 console.log('BUNDLE_ACTIVE isIdleState callback failed. code is: ' + err.code + ',message is: ' + err.message); 177 } else { 178 console.log('BUNDLE_ACTIVE isIdleState callback succeeded, result: ' + JSON.stringify(res)); 179 } 180 }); 181 182 //同步方式 183 let isIdleState = usageStatistics.isIdleStateSync("com.ohos.camera"); 184 ``` 185 1868. 查询FA使用记录。返回数量最大不超过maxNum设置的值,若不传入maxNum参数,则默认maxNum为1000, 需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。 187 188 ```ts 189 import { BusinessError } from '@ohos.base'; 190 191 // 异步方法promise方式 192 usageStatistics.queryModuleUsageRecords(1000).then( (res : Array<usageStatistics.HapModuleInfo>) => { 193 console.log('BUNDLE_ACTIVE queryModuleUsageRecords promise succeeded'); 194 for (let i = 0; i < res.length; i++) { 195 console.log('BUNDLE_ACTIVE queryModuleUsageRecords promise number : ' + (i + 1)); 196 console.log('BUNDLE_ACTIVE queryModuleUsageRecords promise result ' + JSON.stringify(res[i])); 197 } 198 }).catch( (err : BusinessError)=> { 199 console.error('BUNDLE_ACTIVE queryModuleUsageRecords promise failed. code is: ' + err.code + ',message is: ' + err.message); 200 }); 201 202 // 无maxNum参数异步方法promise方式 203 usageStatistics.queryModuleUsageRecords().then( (res : Array<usageStatistics.HapModuleInfo>) => { 204 console.log('BUNDLE_ACTIVE queryModuleUsageRecords promise succeeded'); 205 for (let i = 0; i < res.length; i++) { 206 console.log('BUNDLE_ACTIVE queryModuleUsageRecords promise number : ' + (i + 1)); 207 console.log('BUNDLE_ACTIVE queryModuleUsageRecords promise result ' + JSON.stringify(res[i])); 208 } 209 }).catch( (err : BusinessError)=> { 210 console.error('BUNDLE_ACTIVE queryModuleUsageRecords promise failed. code is: ' + err.code + ',message is: ' + err.message); 211 }); 212 213 // 异步方法callback方式 214 usageStatistics.queryModuleUsageRecords(1000, (err : BusinessError, res : Array<usageStatistics.HapModuleInfo>) => { 215 if(err) { 216 console.log('BUNDLE_ACTIVE queryModuleUsageRecords callback failed. code is: ' + err.code + ',message is: ' + err.message); 217 } else { 218 console.log('BUNDLE_ACTIVE queryModuleUsageRecords callback succeeded.'); 219 for (let i = 0; i < res.length; i++) { 220 console.log('BUNDLE_ACTIVE queryModuleUsageRecords callback number : ' + (i + 1)); 221 console.log('BUNDLE_ACTIVE queryModuleUsageRecords callback result ' + JSON.stringify(res[i])); 222 } 223 } 224 }); 225 226 // 无maxNum参数异步方法callback方式 227 usageStatistics.queryModuleUsageRecords((err : BusinessError, res : Array<usageStatistics.HapModuleInfo>) => { 228 if(err) { 229 console.log('BUNDLE_ACTIVE queryModuleUsageRecords callback failed. code is: ' + err.code + ',message is: ' + err.message); 230 } else { 231 console.log('BUNDLE_ACTIVE queryModuleUsageRecords callback succeeded.'); 232 for (let i = 0; i < res.length; i++) { 233 console.log('BUNDLE_ACTIVE queryModuleUsageRecords callback number : ' + (i + 1)); 234 console.log('BUNDLE_ACTIVE queryModuleUsageRecords callback result ' + JSON.stringify(res[i])); 235 } 236 } 237 }); 238 ``` 239 2409. 通过指定起始和结束时间查询所有应用的通知次数,需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。 241 242 ```ts 243 import { BusinessError } from '@ohos.base'; 244 245 // 异步方法promise方式 246 usageStatistics.queryNotificationEventStats(0, 20000000000000).then( (res : Array<usageStatistics.DeviceEventStats>) => { 247 console.log('BUNDLE_ACTIVE queryNotificationEventStats promise success.'); 248 console.log('BUNDLE_ACTIVE queryNotificationEventStats promise result ' + JSON.stringify(res)); 249 }).catch( (err : BusinessError) => { 250 console.error('BUNDLE_ACTIVE queryNotificationEventStats promise failed. code is: ' + err.code + ',message is: ' + err.message); 251 }); 252 253 // 异步方法callback方式 254 usageStatistics.queryNotificationEventStats(0, 20000000000000, (err : BusinessError, res : Array<usageStatistics.DeviceEventStats>) => { 255 if(err) { 256 console.log('BUNDLE_ACTIVE queryNotificationEventStats callback failed. code is: ' + err.code + ',message is: ' + err.message); 257 } else { 258 console.log('BUNDLE_ACTIVE queryNotificationEventStats callback success.'); 259 console.log('BUNDLE_ACTIVE queryNotificationEventStats callback result ' + JSON.stringify(res)); 260 } 261 }); 262 ``` 263 26410. 通过指定起始和结束时间查询系统事件(休眠、唤醒、解锁、锁屏)统计信息,需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。 265 266 ```ts 267 import { BusinessError } from '@ohos.base'; 268 269 // 异步方法promise方式 270 usageStatistics.queryDeviceEventStats(0, 20000000000000).then( (res : Array<usageStatistics.DeviceEventStats>) => { 271 console.log('BUNDLE_ACTIVE queryDeviceEventStates promise success.'); 272 console.log('BUNDLE_ACTIVE queryDeviceEventStates promise result ' + JSON.stringify(res)); 273 }).catch( (err : BusinessError) => { 274 console.error('BUNDLE_ACTIVE queryDeviceEventStats promise failed. code is: ' + err.code + ',message is: ' + err.message); 275 }); 276 277 // 异步方法callback方式 278 usageStatistics.queryDeviceEventStats(0, 20000000000000, (err : BusinessError, res : Array<usageStatistics.DeviceEventStats>) => { 279 if(err) { 280 console.log('BUNDLE_ACTIVE queryDeviceEventStats callback failed. code is: ' + err.code + ',message is: ' + err.message); 281 } else { 282 console.log('BUNDLE_ACTIVE queryDeviceEventStats callback success.'); 283 console.log('BUNDLE_ACTIVE queryDeviceEventStats callback result ' + JSON.stringify(res)); 284 } 285 }); 286 ``` 287 28811. 查询指定bundleName的应用的使用优先级群组,返回查询的优先级分组结果,需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。 289 290 ```ts 291 import { BusinessError } from '@ohos.base'; 292 293 // 有bundleName异步promise方式 294 let bundleName = "com.ohos.camera"; 295 usageStatistics.queryAppGroup(bundleName).then( (res : number) => { 296 console.log('BUNDLE_ACTIVE queryAppGroup promise succeeded. result: ' + JSON.stringify(res)); 297 }).catch( (err : BusinessError) => { 298 console.error('BUNDLE_ACTIVE queryAppGroup promise failed. code is: ' + err.code + ',message is: ' + err.message); 299 }); 300 301 // 有bundleName异步方法callback方式 302 let bundleName = "com.ohos.camera"; 303 usageStatistics.queryAppGroup(bundleName, (err : BusinessError, res : number) => { 304 if(err) { 305 console.log('BUNDLE_ACTIVE queryAppGroup callback failed. code is: ' + err.code + ',message is: ' + err.message); 306 } else { 307 console.log('BUNDLE_ACTIVE queryAppGroup callback succeeded. result: ' + JSON.stringify(res)); 308 } 309 }); 310 ``` 311 31212. 给指定bundleName的应用的优先级分组设置成newGroup。 需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。 313 314 ```ts 315 import { BusinessError } from '@ohos.base'; 316 317 // 异步方法promise 318 let bundleName = "com.example.deviceUsageStatistics"; 319 let newGroup = usageStatistics.GroupType.DAILY_GROUP; 320 321 usageStatistics.setAppGroup(bundleName, newGroup).then( () => { 322 console.log('BUNDLE_ACTIVE setAppGroup promise succeeded.'); 323 }).catch( (err : BusinessError) => { 324 console.error('BUNDLE_ACTIVE setAppGroup promise failed. code is: ' + err.code + ',message is: ' + err.message); 325 }); 326 327 // 异步方法callback 328 let bundleName = "com.example.deviceUsageStatistics"; 329 let newGroup = usageStatistics.GroupType.DAILY_GROUP; 330 usageStatistics.setAppGroup(bundleName, newGroup, (err : BusinessError) => { 331 if(err) { 332 console.log('BUNDLE_ACTIVE setAppGroup callback failed. code is: ' + err.code + ',message is: ' + err.message); 333 } else { 334 console.log('BUNDLE_ACTIVE setAppGroup callback succeeded.'); 335 } 336 }); 337 ``` 338 33913. 注册应用分组变化监听回调,返回注册是否成功,当应用分组发生变化时,会给所有已注册的监听者返回回调信息, 需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限 340 341 ```ts 342 import { BusinessError } from '@ohos.base'; 343 344 // 异步方法promise形式 345 function onBundleGroupChanged (res : usageStatistics.AppGroupCallbackInfo) { 346 console.log('BUNDLE_ACTIVE registerAppGroupCallBack RegisterGroupCallBack callback success.'); 347 console.log('BUNDLE_ACTIVE registerAppGroupCallBack result appOldGroup is : ' + res.appOldGroup); 348 console.log('BUNDLE_ACTIVE registerAppGroupCallBack result appNewGroup is : ' + res.appNewGroup); 349 console.log('BUNDLE_ACTIVE registerAppGroupCallBack result changeReason is : ' + res.changeReason); 350 console.log('BUNDLE_ACTIVE registerAppGroupCallBack result userId is : ' + res.userId); 351 console.log('BUNDLE_ACTIVE registerAppGroupCallBack result bundleName is : ' + res.bundleName); 352 }; 353 usageStatistics.registerAppGroupCallBack(onBundleGroupChanged).then( () => { 354 console.log('BUNDLE_ACTIVE registerAppGroupCallBack promise succeeded.'); 355 }).catch( (err : BusinessError) => { 356 console.error('BUNDLE_ACTIVE registerAppGroupCallBack promise failed. code is: ' + err.code + ',message is: ' + err.message); 357 }); 358 359 // 异步方法callback形式 360 function onBundleGroupChanged (res : usageStatistics.AppGroupCallbackInfo) { 361 console.log('BUNDLE_ACTIVE onBundleGroupChanged RegisterGroupCallBack callback success.'); 362 console.log('BUNDLE_ACTIVE registerAppGroupCallBack result appOldGroup is : ' + res.appOldGroup); 363 console.log('BUNDLE_ACTIVE registerAppGroupCallBack result appNewGroup is : ' + res.appNewGroup); 364 console.log('BUNDLE_ACTIVE registerAppGroupCallBack result changeReason is : ' + res.changeReason); 365 console.log('BUNDLE_ACTIVE registerAppGroupCallBack result userId is : ' + res.userId); 366 console.log('BUNDLE_ACTIVE registerAppGroupCallBack result bundleName is : ' + res.bundleName); 367 }; 368 usageStatistics.registerAppGroupCallBack(onBundleGroupChanged, (err : BusinessError) => { 369 if(err) { 370 console.log('BUNDLE_ACTIVE registerAppGroupCallBack callback failed. code is: ' + err.code + ',message is: ' + err.message); 371 } else { 372 console.log('BUNDLE_ACTIVE registerAppGroupCallBack callback success.'); 373 } 374 }); 375 ``` 376 37714. 解除应用分组监听回调, 需要配置ohos.permission.BUNDLE_ACTIVE_INFO权限。 378 379 ```ts 380 import { BusinessError } from '@ohos.base'; 381 382 // promise 383 usageStatistics.unregisterAppGroupCallBack().then( () => { 384 console.log('BUNDLE_ACTIVE unregisterAppGroupCallBack promise succeeded.'); 385 }).catch( (err : BusinessError) => { 386 console.error('BUNDLE_ACTIVE unregisterAppGroupCallBack promise failed. code is: ' + err.code + ',message is: ' + err.message); 387 }); 388 389 // callback 390 usageStatistics.unregisterAppGroupCallBack((err : BusinessError) => { 391 if(err) { 392 console.log('BUNDLE_ACTIVE unregisterAppGroupCallBack callback failed. code is: ' + err.code + ',message is: ' + err.message); 393 } else { 394 console.log('BUNDLE_ACTIVE unregisterAppGroupCallBack callback success.'); 395 } 396 }); 397 ``` 398## 相关实例 399 400针对设备使用信息统计,有以下相关实例可供参考: 401 402- [存储空间统计(ArkTS)(Full SDK)(API10)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-4.0-Release/code/SystemFeature/DeviceManagement/StorageStatistic) 403 404- [设备使用信息统计(ArkTS)(Full SDK)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-4.0-Release/code/BasicFeature/DeviceUsageStatistics/DeviceUsageStatistics)