Configuring Android Enterprise (Work Profile) for Corporate Apps
Common scenario: employee uses personal Android phone for work, IT wants to manage corporate apps without touching personal data. Without Work Profile—either entire device under MDM or no isolation. Both bad.
Android Enterprise Work Profile creates separate profile at OS level—own launcher, own keystore, isolated storage. Corporate apps work inside; personal apps don't even see them exist.
Common Failure Points
Most common issue—improper Device Policy Controller (DPC) initialization. If app registers as Device Owner instead of Profile Owner, gets too wide permissions, breaks UX: blocks Bluetooth, disables wallpaper change, causes complaints.
For BYOD need exactly ProfileOwner. Provisioning via QR (Android 7+) or NFC (Android 6) configured via DevicePolicyManager with EXTRA_PROVISIONING_SKIP_ENCRYPTION flag—without it, old devices hang on disk encryption.
Second failure point—cross-profile intent. If business logic needs to pass data from work profile to personal (e.g., open PDF in system viewer), must explicitly allow via DevicePolicyManager.addCrossProfileIntentFilter(). Without it, intent silently dropped, user sees blank screen, no Logcat logs.
Third issue—managed configurations. Many teams don't use RestrictionsManager, push settings via push notifications or hardcoded URLs. Antipattern: EMM system (Intune, VMware Workspace ONE, SOTI) should deploy config via APP_RESTRICTIONS_CHANGED, app—read from Bundle in onReceive.
How We Implement Work Profile
Process starts with audit: which MDM, which Android versions in fleet, BYOD or COBO (Corporate-Owned, Business-Only). Architecture depends on this.
For BYOD via QR:
// In DPC app becoming Profile Owner
val dpm = getSystemService(DevicePolicyManager::class.java)
val adminComponent = ComponentName(this, DeviceAdminReceiver::class.java)
// Verify we're Profile Owner, not Device Owner
if (dpm.isProfileOwnerApp(packageName)) {
dpm.setProfileName(adminComponent, "Corporate Profile")
dpm.setCrossProfileCalendarPackages(adminComponent, setOf(calendarPackage))
}
For managed configurations use RestrictionsManager:
val restrictionsManager = getSystemService(RestrictionsManager::class.java)
val appRestrictions = restrictionsManager.applicationRestrictions
val serverUrl = appRestrictions.getString("server_url") ?: BuildConfig.DEFAULT_SERVER
val ssoEnabled = appRestrictions.getBoolean("sso_enabled", false)
Allows IT admin to change config via Intune Policy without app release.
Certificates and VPN in Work Profile
Installing client certificates via KeyChain.createInstallIntent() works only in personal profile. In work profile—only via DevicePolicyManager.installCaCert() and installKeyPair(). Confusion here costs days of debugging.
For VPN in Work Profile—VpnService with setAlwaysOnVpnPackage() via DPC. Work profile traffic goes through corporate VPN, personal—direct. User doesn't feel this.
Testing and Tools
Separate emulator with Work Profile—Android Studio AVD with "Work profile" option. For integration tests with real MDM use TestDPC (Google open source)—mimics Enterprise MDM behavior without Intune.
Android Debug Bridge switch between profiles:
adb shell am switch-user 10 # switch to work profile (user id device-dependent)
adb shell pm list packages --user 10
Firebase Crashlytics in Work Profile requires separate init—SDK doesn't send data across profile boundary by default.
Implementation Stages
- Audit — EMM platform, device fleet, IT policy requirements
- DPC development — create/enhance Device Policy Controller for Profile Owner
- Managed Config schema — XML schema for AppConfig Community (Intune/Workspace ONE standard)
- Integration testing — TestDPC + real fleet devices
- IT documentation — deployment instruction via EMM
Timeline: typical project (existing app + Work Profile without custom DPC)—2–3 working days. Custom DPC from scratch—from 1 week.







