expo: Expo fails to install app on Android device with a work profile

Summary

Steps to Reproduce

  1. Set up a work profile on your Android device
  2. Connect your device via USB and enable USB debugging
  3. Run npm run android to install your Expo app to the Android device

Expected Result The app is installed to the device and launches

Actual Result npm run android fails with the following stack trace:

BUILD SUCCESSFUL in 3m 8s
1141 actionable tasks: 28 executed, 1113 up-to-date
Waiting on http://localhost:8081
Error: Exception occurred while executing 'list':
java.lang.SecurityException: Shell does not have permission to access user 10
 com.android.server.am.ActivityManagerService.handleIncomingUser:12581 android.app.ActivityManager.handleIncomingUser:4290 com.android.server.pm.PackageManagerShellCommand.translateUserId:3421
	at com.android.server.am.UserController.handleIncomingUser(UserController.java:2281)
	at com.android.server.am.ActivityManagerService.handleIncomingUser(ActivityManagerService.java:12581)
	at android.app.ActivityManager.handleIncomingUser(ActivityManager.java:4290)
	at com.android.server.pm.PackageManagerShellCommand.translateUserId(PackageManagerShellCommand.java:3421)
	at com.android.server.pm.PackageManagerShellCommand.runListPackages(PackageManagerShellCommand.java:931)
	at com.android.server.pm.PackageManagerShellCommand.runListPackages(PackageManagerShellCommand.java:837)
	at com.android.server.pm.PackageManagerShellCommand.runList(PackageManagerShellCommand.java:696)
	at com.android.server.pm.PackageManagerShellCommand.onCommand(PackageManagerShellCommand.java:209)
	at com.android.modules.utils.BasicShellCommandHandler.exec(BasicShellCommandHandler.java:97)
	at android.os.ShellCommand.exec(ShellCommand.java:38)
	at com.android.server.pm.PackageManagerService$IPackageManagerImpl.onShellCommand(PackageManagerService.java:5996)
	at android.os.Binder.shellCommand(Binder.java:1049)
	at android.os.Binder.onTransact(Binder.java:877)
	at android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:4313)
	at com.android.server.pm.PackageManagerService$IPackageManagerImpl.onTransact(PackageManagerService.java:5980)
	at android.os.Binder.execTransactInternal(Binder.java:1285)
	at android.os.Binder.execTransact(Binder.java:1244)
Error: /Users/user_dir/Library/Android/sdk/platform-tools/adb exited with non-zero code: 255
    at ChildProcess.completionListener (/Users/user_dir/Development/app_dir/node_modules/@expo/spawn-async/build/spawnAsync.js:52:23)
    at Object.onceWrapper (node:events:640:26)
    at ChildProcess.emit (node:events:520:28)
    at ChildProcess.emit (node:domain:475:12)
    at maybeClose (node:internal/child_process:1092:16)
    at Process.ChildProcess._handle.onexit (node:internal/child_process:302:5)
    ...
    at Object.spawnAsync [as default] (/Users/user_dir/Development/app_dir/node_modules/@expo/spawn-async/build/spawnAsync.js:17:21)
    at ADBServer.runAsync (/Users/user_dir/Development/app_dir/node_modules/@expo/cli/build/src/start/platforms/android/ADBServer.js:80:77)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async Object.isPackageInstalledAsync (/Users/user_dir/Development/app_dir/node_modules/@expo/cli/build/src/start/platforms/android/adb.js:87:22)
    at async AndroidDeviceManager.isAppInstalledAsync (/Users/user_dir/Development/app_dir/node_modules/@expo/cli/build/src/start/platforms/android/AndroidDeviceManager.js:143:16)
    at async AndroidPlatformManager.openProjectInCustomRuntimeAsync (/Users/user_dir/Development/app_dir/node_modules/@expo/cli/build/src/start/platforms/PlatformManager.js:84:14)
    at async runAndroidAsync (/Users/user_dir/Development/app_dir/node_modules/@expo/cli/build/src/run/android/runAndroidAsync.js:45:5)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Notes As far as I can tell, this is new to adb and there is a --user flag to specify which user the app should be run as. You can also reproduce this error by running adb shell pm list packages, but it works if you run adb shell pm list packages --user 0. It fails if you try to run adb shell pm list packages --user 10 due to adb not having access to the work profile.

Expo needs to support specifying the user to run as.

What platform(s) does this occur on?

Android

SDK Version

47.0.14 and 48.x.x

Environment

expo-env-info 1.0.5 environment info: System: OS: macOS 13.3.1 Shell: 5.9 - /bin/zsh Binaries: Node: 16.14.0 - ~/.nvm/versions/node/v16.14.0/bin/node Yarn: 1.22.19 - ~/.nvm/versions/node/v16.14.0/bin/yarn npm: 8.3.1 - ~/.nvm/versions/node/v16.14.0/bin/npm Watchman: 2023.02.27.00 - /opt/homebrew/bin/watchman Managers: CocoaPods: 1.12.1 - /Users/user_dir/.rbenv/shims/pod SDKs: iOS SDK: Platforms: DriverKit 22.1, iOS 16.1, macOS 13.0, tvOS 16.1, watchOS 9.1 Android SDK: API Levels: 23, 26, 30, 31, 33 Build Tools: 29.0.2, 30.0.3, 31.0.0 System Images: android-31 | Google APIs ARM 64 v8a IDEs: Android Studio: 2022.1 AI-221.6008.13.2211.9514443 Xcode: 14.1/14B47b - /usr/bin/xcodebuild npmPackages: expo: ~47.0.14 => 47.0.14 react: 18.1.0 => 18.1.0 react-dom: 18.1.0 => 18.1.0 react-native: 0.70.8 => 0.70.8 react-native-web: ~0.18.9 => 0.18.10 npmGlobalPackages: eas-cli: 3.10.2 expo-cli: 6.3.2 Expo Workflow: bare

Minimal reproducible example

This occurs with a brand new Expo app. You just need to set up a work profile on your Android device first:

  1. npx create-expo-app my-app
  2. cd my-app
  3. npm run android
~/Development/my-app(main|✔) % npm run android

> my-app@1.0.0 android
> expo start --android

Starting project at /Users/user_dir/Development/my-app
Starting Metro Bundler
› Opening exp://10.0.0.100:19000 on Pixel_5
Error: Exception occurred while executing 'list':
java.lang.SecurityException: Shell does not have permission to access user 10

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 3
  • Comments: 15 (7 by maintainers)

Commits related to this issue

Most upvoted comments

For others who are running into this issue, this very hacky workaround will allow you to deploy under a device with a work profile:

In your project, open the file node_modules/@expo/cli/build/src/start/platforms/android/adb.js, and replace the function adbArgs with this:

function adbArgs(pid, ...options) {
    const args = [];
    if (pid) {
        args.push("-s", pid);
    }

    // Add the --user param whenever Expo tries to call `adb shell pm list packages`
    options = options.map(option => {
        if (option === "packages") {
            return "packages --user 0";
        }
        return option;
    });

    return args.concat(options);
}

Please add @nickfletcherr 's fix to the official repo, it seems the only way, otherwise I will have to delete my secure folder and lose my collection of “nudes” I gathered throughout the years, just to debug my app 👯‍♂️

@panalgin your words really spoke to me, it should be landed as part of SDK 50. I’ve added the ability to customize the user number (globally) using environment variables. A better solution would involve adding some settings / prompts, but that will take longer to land.

@hichemfantar @EvanBacon thank you so much guys, this means a lot for my research purposes 😁

Hey Kudo,

Here’s the output of those commands:

% adb shell am get-current-user
0
% adb shell pm list users
Users:
	UserInfo{0:Nick:c13} running
	UserInfo{10:Work profile:1030} running

Thanks for the fix @EvanBacon @panalgin your private stash is now safe thanks to the power of open source.

Thanks @nickfletcherr I just tried it and it works