Work profile detection

  • This guide explains how to detect a work profile on a device, specifically those managed by the Android Device Policy app.

  • You can detect if your app is currently running inside a work profile by checking if it's the profile owner app for "com.google.android.apps.work.clouddpc".

  • You can determine if a device has a work profile from the personal profile by querying for the intent "com.google.android.apps.work.clouddpc.ACTION_DETECT_WORK_PROFILE".

  • The method for detecting if a device has a work profile differs slightly depending on whether the device is running Android 11 or later, or a prior version.

This guide illustrates how to detect a work profile on a device. It applies only to work profiles managed by the Android Device policy app.

Detect if the app is running inside a work profile

The following method checks if the calling app is running within a work profile managed by the Android Device Policy app.

Kotlin

fun isInsideWorkProfile(): Boolean {
  val devicePolicyManager = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager

  return devicePolicyManager.isProfileOwnerApp("com.google.android.apps.work.clouddpc")
}

Java

boolean isInsideWorkProfile() {
  DevicePolicyManager devicePolicyManager = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);

  return devicePolicyManager.isProfileOwnerApp("com.google.android.apps.work.clouddpc");
}

Detect if the device has a work profile

To determine if a device has a work profile managed by the Android Device Policy app, use the following method. This can be called from any management mode. From an app in the personal profile, querying for the intent com.google.android.apps.work.clouddpc.ACTION_DETECT_WORK_PROFILE should resolve as a cross-profile intent if a work profile managed by the Android Device Policy app exists. This method will only return true when called from the personal profile of a device that has such a work profile.

Android 11 and later:

Kotlin

fun hasWorkProfile(): Boolean {
  val intent = Intent("com.google.android.apps.work.clouddpc.ACTION_DETECT_WORK_PROFILE")
  val activities = context.packageManager.queryIntentActivities(intent, 0)
  return activities.any { it.isCrossProfileIntentForwarderActivity }
}

Java

boolean hasWorkProfile() {
  Intent intent = new Intent("com.google.android.apps.work.clouddpc.ACTION_DETECT_WORK_PROFILE");
  List<ResolveInfo> activities = context.getPackageManager().queryIntentActivities(intent, 0);
  return activities.stream()
        .anyMatch(
            (ResolveInfo resolveInfo) -> {
              return resolveInfo.isCrossProfileIntentForwarderActivity();
            });
}

Prior to Android 11:

Kotlin

fun hasWorkProfile(): Boolean {
  val intent = Intent("com.google.android.apps.work.clouddpc.ACTION_DETECT_WORK_PROFILE")
  val activities = context.packageManager.queryIntentActivities(intent, 0)
  return activities.any { it.activityInfo.name == "com.android.internal.app.ForwardIntentToManagedProfile" }
}

Java

boolean hasWorkProfile() {
  Intent intent = new Intent("com.google.android.apps.work.clouddpc.ACTION_DETECT_WORK_PROFILE");
  List<ResolveInfo> activities = context.getPackageManager().queryIntentActivities(intent, 0);
  return activities.stream()
        .anyMatch(
            (ResolveInfo resolveInfo) -> {
              return resolveInfo.activityInfo.name.equals("com.android.internal.app.ForwardIntentToManagedProfile");
            });
}