Skip to content
CARP Docs
Ask AISystemLightDark
On this page

Installed apps

The APPS measure, which lists the apps installed on an Android phone with their package name, version and update time.

Copy MarkdownOpen inOpen in GitHubView as MarkdownOpen in Scira AIOpen in ChatGPTOpen in ClaudeOpen in Cursor

dk.cachet.carp.apps is a one-time measure that runs on the phone, on Android only, through the installed_apps plugin. Add it as Measure(type: AppsSamplingPackage.APPS). It collects the full app list each time its trigger fires.

Add the measure to a protocol

A one-time measure collects only when its trigger fires, so choose a trigger that matches how often the app list matters to the study:

PeriodicTriggerOneTimeTrigger

A PeriodicTrigger collects the list when sampling starts, typically at every app start, and then once per period:

protocol.addTaskControl(
  PeriodicTrigger(period: const Duration(days: 7)),
  BackgroundTask(measures: [Measure(type: AppsSamplingPackage.APPS)]),
  phone,
);

A OneTimeTrigger collects the list once per deployment, also across app restarts:

protocol.addTaskControl(
  OneTimeTrigger(),
  BackgroundTask(measures: [Measure(type: AppsSamplingPackage.APPS)]),
  phone,
);

An ImmediateTrigger collects the list only when sampling starts, typically at every app start.

The measure has no sampling configuration.

Included apps

The measure lists the apps that installed_apps returns with its default filters:

  • System apps are left out, also when the participant can open them.
  • Apps without a launcher entry are left out.
  • The list is sorted by app name.

The package has no option to change these filters.

On Android 11 or later, the app sees all other apps only with the QUERY_ALL_PACKAGES permission, which installed_apps adds to the manifest. Without it, the list holds only the apps that Android makes visible by default.

For the Google Play restrictions on this permission, see Google Play policy.

Limitations

  • If reading the list fails, installed_apps returns an empty list instead of an error, so the measurement has an empty installedApps.
  • framework comes from a heuristic in installed_apps, which can misclassify apps.
  • The package has no privacy transformer, so app names and package names are stored as collected, also with the default privacy schema. The list of apps can reveal sensitive information about a participant, so cover it in the study's consent.
  • The measure does not run on iOS.

Data

Each measurement holds an Apps object with the __type dk.cachet.carp.apps:

FieldTypeDescription
installedAppsList<App>The installed apps, sorted by name.

Each entry is an App. Fields that are null are left out of the JSON:

FieldTypeDescription
nameString?App name as shown to the participant.
packageNameString?The application ID, such as com.spotify.music.
versionNameString?Version string, such as 9.0.88.
versionCodeint?Internal version number.
installTimeMillisint?Despite its name, the time the app was last installed or updated, in milliseconds since the epoch, not the time of the first install.
frameworkString?The framework the app is built with: Flutter, React Native, Xamarin, Ionic or Native or Others.

The measurement's sensorStartTime is the time of collection. The data looks like this:

{
  "__type": "dk.cachet.carp.apps",
  "installedApps": [
    {
      "name": "My Study",
      "packageName": "dk.carp.myapp",
      "versionName": "1.4.0",
      "versionCode": 42,
      "installTimeMillis": 1792489267000,
      "framework": "Flutter"
    },
    {
      "name": "Spotify",
      "packageName": "com.spotify.music",
      "versionName": "9.0.88",
      "versionCode": 129088,
      "installTimeMillis": 1788372235000,
      "framework": "Native or Others"
    }
  ]
}

For the measurement envelope around the data, see Measurements and data.

Quick links

Page · DocumentationCARP DocumentationPage · DocumentationIntroductionPage · DocumentationQuickstartPage · DocumentationTerminologyPage · DocumentationArchitecture