App usage
The APP_USAGE measure, which records the foreground time of each app over a time window from Android usage statistics.
dk.cachet.carp.appusage is a one-time measure that runs on the phone, on Android only, through the app_usage plugin. Add it as Measure(type: AppsSamplingPackage.APP_USAGE). Each time its trigger fires, it collects the usage of a time window that ends at that moment.
Add the measure to a protocol
Give the measure its own HistoricSamplingConfiguration, so that each window starts where the previous one ended, also after an app restart. Add it with a trigger that repeats:
A PeriodicTrigger collects when sampling starts and then once per period:
An AppLifecycleTrigger collects each time the app returns to the foreground. AppLifecycleState comes from package:flutter/widgets.dart:
Collect app usage with one measure and one trigger. Two app usage measures keep separate windows, which overlap.
Configuration
HistoricSamplingConfiguration has these properties:
| Property | Type | Default | Description |
|---|---|---|---|
past | Duration | 1 day | How far back the window reaches when the measure has not collected before. |
future | Duration | 1 day | Not used by this measure. |
lastTime | DateTime? | null | When the measure last collected. CARP Mobile Sensing (CAMS) sets it after each collection. |
Without a configuration on the measure, the package default applies, with a past of 1 day.
Time window
Each collection covers a window from start to end:
startislastTimeif the measure collected before, otherwise the current time minuspast.endis the current time.- After the collection, CAMS sets
lastTimeto the current time, so the next window starts where this one ended.
Known issue
Without its own configuration, the measure keeps lastTime in memory only. After an app restart, the first window therefore starts past before the current time again and overlaps data that was already collected. Give the measure its own HistoricSamplingConfiguration, as in the examples above, so that CAMS saves lastTime with the deployment.
Precision
The app_usage plugin states that Android's usage statistics are precise to a day only. The usage of a window therefore comes from Android's statistics for the periods that overlap the window, which can be longer than the window. Each app's startDate and endDate show the period that its statistics cover.
Use windows of a day or longer. Do not add up the usage of consecutive windows: a period that overlaps two windows counts in both.
Usage access
The measure needs the participant to turn on Usage access for the app, which CAMS does not ask for. When access is missing, the app_usage plugin opens the Usage access settings screen each time the measure collects. The measurement then has an empty usage map.
For how to prepare participants for this setting, see Installation.
Limitations
- In
usage,nameis the last part of the package name, not the app name. To get app names, join with the installed apps onpackageName. lastForegroundis not the last time the app was in the foreground. See Data.startandendare in UTC, while the dates inusageare in local time without an offset.- Usage is counted in whole seconds, and apps without foreground time are left out.
- If the phone's clock is set back to before
lastTime, each collection fails until the clock passeslastTimeagain. The data manager then stores an error measurement instead of usage data. - The package has no privacy transformer, so package names and usage times are stored as collected.
- The measure does not run on iOS.
Data
Each measurement holds an AppUsage object with the __type dk.cachet.carp.appusage:
| Field | Type | Description |
|---|---|---|
start | DateTime | Start of the window, in UTC. |
end | DateTime | End of the window, in UTC. |
usage | Map<String, AppUsageInfo> | The usage of each app with foreground time, keyed by package name. Empty when usage access is missing. |
Each value in usage is an AppUsageInfo:
| Field | Type | Description |
|---|---|---|
name | String | The last part of the package name, such as music for com.spotify.music. Not the app name. |
packageName | String | The full package name. |
usage | Duration | Total time in the foreground, in whole seconds. In JSON, an integer number of microseconds. |
startDate | DateTime | Start of the period that Android's statistics for the app cover, in local time without an offset. |
endDate | DateTime | End of that period, in local time without an offset. |
lastForeground | DateTime | On Android 10 or later, the last time that one of the app's foreground services was used. On Android 9 and lower, the epoch (1970-01-01) in local time, which may also appear for apps without foreground services. |
The measurement's sensorStartTime and sensorEndTime hold the window in microseconds since the epoch. The data looks like this:
For the measurement envelope around the data, see Measurements and data.