鸿蒙开发实战:【手机应用使用信息统计】 - HarmonyOS技术社区 - 电子技术论坛 - 广受欢迎的专业电子论坛
分享 收藏 返回

[文章]

鸿蒙开发实战:【手机应用使用信息统计】

概述

本示例主要展示了设备使用信息情况。

样例展示

image.png

基础信息

image.png

设备使用信息统计

介绍

本示例使用[bundleState]相关接口完成设备中应用时长的统计功能。

效果预览

主页

使用说明:

1.顶部的数据面板展示了最常用的五个应用的使用时间占比情况。

2.中部的竖向滑动栏展示了每个应用的使用总时长和最后一次使用的时间。

3.底部的横向滑动栏展示了不常用应用列表。

具体实现

  • 该示例使用bundleState接口中isIdleState方法判断指定bundleName的应用当前是否是空闲状态来分类不常用应用列表,queryBundleStateInfos方法通过指定起始和结束时间查询应用使用时长统计信息来获得每个应用的使用总时长。
  • 源码链接:[BundleStateUtil.ets]
/*

 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *     http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */



import usageStatistics from '@ohos.resourceschedule.usageStatistics'

import AppTime from '../model/AppTime'

import Logger from './Logger'

import { AppInfo, appInit } from '../model/AppInfo'

import { getAppName, getAppIcon, getTimStr } from './Util'



const TAG: string = 'BundleStateUtil'

const BEGIN_HOURS: number = 0

const BEGIN_MINUTES: number = 0

const BEGIN_SECONDS: number = 0

const END_HOURS: number = 23

const END_MINUTES: number = 59

const END_SECONDS: number = 59



export class BundleStateUtil {

  private apps: Array<AppInfo> = appInit()

  private freeApps: Array<AppInfo> = []



  /**

   * 获取不常用应用列表

   */

  async getFreeAppList(): Promise<Array<AppInfo>> {

    for (let appsKey in this.apps) {

      let bundleName = this.apps[appsKey].bundleName

      let isIdleState = await usageStatistics.isIdleState(bundleName)

      if (isIdleState) {

        this.freeApps.push({ bundleName: bundleName, name: getAppName(bundleName), icon: getAppIcon(bundleName) })

      }

      Logger.info(TAG, `freeApps=${JSON.stringify(this.freeApps)}`)

    }

    return this.freeApps

  }



  /**

   * 获取所有应用使用时间列表

   */

  async getTotalAppList(): Promise<Array<AppTime>> {

    let dateBegin = new Date()

    // 设置开始时间为00:00:00

    dateBegin.setHours(BEGIN_HOURS)

    dateBegin.setMinutes(BEGIN_MINUTES)

    dateBegin.setSeconds(BEGIN_SECONDS)

    Logger.info(TAG, `dateBegin= ${getTimStr(dateBegin)} ${dateBegin.toString()}`)

    let dateEnd = new Date()

    // 设置结束时间为23:59:59

    dateEnd.setHours(END_HOURS)

    dateEnd.setMinutes(END_MINUTES)

    dateEnd.setSeconds(END_SECONDS)

    Logger.info(TAG, `dateEnd= ${getTimStr(dateEnd)} ${dateEnd.toString()}`)

    let res = await usageStatistics.queryBundleStatsInfos(Date.parse(dateBegin.toString()), Date.parse(dateEnd.toString()))

    Logger.info(TAG, `queryBundleStateInfos promise success`)

    let list: Array<AppTime> = []

    for (let key in res) {

      if (res.hasOwnProperty(key)) {

        Logger.info(TAG, `queryBundleStateInfos promise result ${JSON.stringify(res[key])}`)

        let appTime = new AppTime(res[key].bundleName, res[key].abilityPrevAccessTime, res[key].abilityInFgTotalTime)

        list.push(appTime)

      }

    }

    return list

  }

}

[FreeApps.ets]

/*

 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *     http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */



import { AppInfo, appInit, BundleStateUtil } from 'feature-util'



const TAG = 'FreeApps'



@Component

export struct FreeApps {

  @State apps: Array<AppInfo> = appInit()

  @State freeApps: Array<AppInfo> = []



  aboutToAppear() {

    this.getFreeApps()

  }



  async getFreeApps() {

    let bundleStateUtil = new BundleStateUtil()

    this.freeApps = await bundleStateUtil.getFreeAppList()

  }



  build() {

    Column() {

      Text($r('app.string.free_apps'))

        .width('80%')

        .fontSize(20)

        .fontWeight(FontWeight.Bold)

        .direction(Direction.Ltr)

        .margin({ bottom: 10 })

      Column() {

        Scroll() {

          Row() {

            ForEach(this.freeApps, (item) => {

              Column() {

                Image(item.icon)

                  .margin({ top: 10 })

                  .width(70)

                  .height(70)

                  .objectFit(ImageFit.Fill)

                Text(item.name)

                  .fontSize(10)

                  .margin({ top: 5 })

              }

              .width(70)

              .height(120)

              .margin(10)

            }, item => item.name)

          }

          .borderRadius(10)

          .backgroundColor(Color.White)

        }

        .margin(5)

        .width('90%')

        .scrollable(ScrollDirection.Horizontal)

      }

      .width('95%')

      .padding(10)

    }.margin({ top: 20 })

  }

}

[PanelView.ets]

/*

 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *     http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */



import { AppTime, BundleStateUtil, getAppName, getTotalTime } from 'feature-util'



const TAG = 'PanelView'

const oftenUsed = 5



@Component

export struct PanelView {

  @State statisticals: Array<AppTime> = []

  @State panelName: string[] = []

  @State panelValue: number[] = []

  @State totalTime: number = 0

  @State panelViewHeight: number = 0



  aboutToAppear() {

    this.getTime()

  }



  async getTime() {

    let bundleStateUtil = new BundleStateUtil()

    let list = await bundleStateUtil.getTotalAppList()



    this.totalTime = getTotalTime(list)

    list.sort((a, b) => b.totalTime - a.totalTime)

    this.statisticals = list

    let topFiveTotalTime = 0

    for (let i = 0;i < oftenUsed; i++) {

      this.panelName.push(getAppName(this.statisticals[i].bundleName))

      this.panelValue.push(this.statisticals[i].totalTime)

      topFiveTotalTime += this.statisticals[i].totalTime

    }

    this.panelName.push('others')

    this.panelValue.push(this.totalTime - topFiveTotalTime)

  }



  build() {

    Column() {

      Text($r('app.string.application_duration'))

        .fontSize(20)

        .width('100%')

        .margin({ top: 10 })

        .textAlign(TextAlign.Center)

      Row() {

        DataPanel({ values: this.panelValue, max: this.totalTime, type: DataPanelType.Circle })

          .width(200)

          .height(200)

        Column() {

          ForEach(this.panelName, (item) => {

            Text(item)

              .fontSize(20)

              .margin({ top: 5 })

          }, item => item)

        }

        .margin({ top: 10, left: 35 })

      }

      .height(250)

      .margin({ top: 10 })

      .alignSelf(ItemAlign.Center)



    }

    .width('100%')

    .onAreaChange((oldArea: Area, newArea: Area) => {

      this.panelViewHeight = (newArea.height) as number * 0.3 // percentage

    })

  }

}

[UsageList.ets]

/*

 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *     http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */



import { AppTime, BundleStateUtil, hmsToString, getAppName, getAppIcon, getTotalTime } from 'feature-util'



const TAG = 'UsageList'



@Component

export struct UsageList {

  @State statisticals: Array<AppTime> = []

  @State totalTime: number = 0



  aboutToAppear() {

    this.getTime()

  }



  async getTime() {

    let bundleStateUtil = new BundleStateUtil()

    let list = await bundleStateUtil.getTotalAppList()



    this.totalTime = getTotalTime(list)

    list.sort((a, b) => b.totalTime - a.totalTime)

    this.statisticals = list

  }



  build() {

    Column() {

      Text(hmsToString(this.totalTime / 1000))

        .width('80%')

        .fontSize(30)

        .textAlign(TextAlign.Start)

        .fontWeight(FontWeight.Bold)

        .margin({ top: 15, bottom: 15 })

      Scroll() {

        Column() {

          ForEach(this.statisticals, (item) => {

            Row() {

              Image(getAppIcon(item.bundleName))

                .width(80)

                .height(80)

                .objectFit(ImageFit.Fill)

              Column() {

                Row() {

                  Text(getAppName(item.bundleName))

                    .width('60%')

                    .fontSize(25)

                    .fontWeight(FontWeight.Bold)

                  Text(hmsToString(Math.floor(item.totalTime / 1000)))

                    .width('40%')

                    .fontSize(22)

                    .textAlign(TextAlign.End)

                }

                .width('100%')

                .alignSelf(ItemAlign.Start)



                Progress({ value: item.totalTime, total: this.totalTime, type: ProgressType.Linear })

                  .height(20)

                  .width('100%')

                  .color(Color.Grey)

                  .margin({ top: 12 })

                  .style({ strokeWidth: 10 })

                  .alignSelf(ItemAlign.Start)



                Row() {

                  Text($r('app.string.application_last_used')).fontSize(15)

                  Text(hmsToString(Math.floor(item.prevAccessTime / 1000))).fontSize(15)

                }

              }

              .alignItems(HorizontalAlign.Start)

              .layoutWeight(1)

              .padding({ left: 5, right: 5 })

            }

            .height(95)

            .margin({ bottom: 50 })

          }, item => item.bundleName)

        }

        .justifyContent(FlexAlign.Start)

      }

      .width('90%')

      .height('80%')

      .scrollBar(BarState.Off)

      .backgroundColor(Color.White)

      .scrollable(ScrollDirection.Vertical)

      .borderRadius(10)

      .padding(20)

    }

    .width('100%')

    .height('55%')

    .margin({ top: 40 })

  }

}

鸿蒙OpenHarmony知识待更新

485f48c927688f7ba739dc1871e0214e.jpeg

更多回帖

×
发帖