Your managed Expo habit-tracking app needs a native camera SDK with iOS and Android permission entries; how do you add it without committing ios and android?
answer
- change inputs, never outputs
- npx expo install the package
- plugin entry with permission strings
- regenerate, then rebuild the native app
- no plugin shipped: write a local one
basics
~20 sInstall the library with npx expo install, add its config plugin and permission strings to the app config, then regenerate with npx expo prebuild or let EAS Build do it, and ship a new native build. The native folders stay generated.
solid answer
~40 sUnder Continuous Native Generation the fix is always a change to the inputs. Install the package with `npx expo install` so autolinking picks it up, and register its config plugin in the app config's `plugins` with the options it needs; for `expo-camera` that is `cameraPermission` (the iOS usage string) and, for audio, `microphonePermission` and `recordAudioAndroid`. Then regenerate: locally with `npx expo prebuild` (clean by default since SDK 57) followed by a native build, or in the cloud, where EAS Build prebuilds a project without native folders. Because native code changed, the app needs a new native build; a JavaScript-only update cannot deliver it. If a library needs native setup but ships no plugin, write a small local config plugin rather than editing the generated files.
code
bash · 4 linesnpx expo install expo-camera
# add the expo-camera plugin entry to app.json, then:
npx expo prebuild
npx expo run:iosgo deeper
Recall the steps: install the package, add its plugin to the app config, regenerate, and build a new native app.
Explain what autolinking handles and what the plugin handles, and why a hand edit to generated files never reaches EAS Build.
Show the rollout: a new binary rather than an update, guarding calls for older binaries, explicit plugin options, and a plan when a library ships no plugin.
Decide when a library's native demands justify leaving CNG versus investing in local plugins, and what that means for the rest of the app's lifetime.
## The scenario A habit-tracking app built with Expo keeps its native folders generated. The team wants photo check-ins: a user proves a habit by taking a picture. That needs a native camera library, and the library needs **permission strings** on iOS (`NSCameraUsageDescription` in `Info.plist`) and a **permission entry** on Android (`AndroidManifest.xml`). The tempting shortcut is to run prebuild once, edit the generated files, and commit them. Under CNG that is exactly what not to do. ## The CNG way: change the inputs 1. **Install the package** with `npx expo install expo-camera`, which picks a version compatible with the installed SDK. Autolinking will link its native code on the next generation. 2. **Register its config plugin** in the app config. The plugin writes the native entries so you never touch `Info.plist` or `AndroidManifest.xml` yourself. 3. **Regenerate**: run `npx expo prebuild` locally (since SDK 57 this deletes and recreates the folders), or push and let **EAS Build** run prebuild on a project that has no native folders. 4. **Build and install a new native binary**, because native code and permissions changed. 5. **Verify on both platforms** that the permission prompt shows the text you configured. ```json { "expo": { "plugins": [ [ "expo-camera", { "cameraPermission": "Allow HabitLoop to take photo check-ins.", "microphonePermission": false, "recordAudioAndroid": false } ] ] } } ``` In `expo-camera`'s plugin, `cameraPermission` and `microphonePermission` set the iOS usage descriptions (`false` leaves one out), and `recordAudioAndroid` defaults to `true`, adding the Android audio permission unless you turn it off, which matters for an app that never records video with sound. ## If the library ships no config plugin Many native libraries need nothing beyond autolinking. Some need extra native setup and do not ship a plugin. The options, in order of preference: - use a **community-maintained plugin** for that library, if one exists; - write a **local config plugin** in the repository that makes the needed native change during prebuild; - as a last resort, stop generating the native folders for this app, which is a much larger decision. How to write that plugin is a topic of its own; the CNG point is that the change lives in the repository as code that runs on every generation. ## Why not edit and commit once | Shortcut | What breaks | |---|---| | Edit generated `Info.plist` | the next default prebuild deletes it | | Commit `ios/` and `android/` | EAS Build stops running prebuild and ignores native fields in the app config | | Keep the edit only on one laptop | CI and EAS produce a build without the permission | The third row is the most common real failure: the app works on the developer's device and crashes or fails review from the cloud build because the permission string is missing. ## Rolling it out - **Native change, new binary**: an over-the-air update cannot add a native module or a permission, so this ships through a store build. Guard the JavaScript that calls the camera so an older binary without the module does not crash. - **Development builds**: the team needs a new development build that includes the module. A sandbox client with a fixed set of native modules can run the module only if that module happens to be bundled in it. - **Removing it later** is symmetrical: uninstall the package and delete the plugin entry, and the next generation leaves nothing behind. ## Checking the result Because the native folders are generated, verify the **generated output** rather than trusting the config by eye: - After `npx expo prebuild`, open the generated `Info.plist` and `AndroidManifest.xml` and confirm the camera entries are present, and that no unwanted audio permission slipped in. - Build from a clean checkout on CI or EAS, not only on the laptop that ran prebuild, so the check covers the real path to users. - Trigger the permission prompt on both platforms and read the text users will actually see. - Remove the plugin temporarily and regenerate once, to confirm the entries disappear; that proves nothing was edited by hand.
- The camera works in a local build of the habit app but the EAS build has no camera permission text; what is the likely cause?The permission was added by editing the generated `Info.plist` locally instead of through the plugin options in the app config. EAS Build regenerates the native project from config, so the hand edit never reaches it. Move the string into the plugin's `cameraPermission` option.
- Why is recordAudioAndroid worth setting explicitly with expo-camera?It defaults to `true`, so the plugin adds the Android audio-recording permission even if the app only takes photos. Setting it to `false` keeps an unneeded permission out of the generated Android manifest.
saying these in an interview costs you the question
- Run prebuild once, edit Info.plist, and commit the folders
- An over-the-air update can ship the new camera module
- Autolinking also writes the permission strings for you
- No config plugin means the library cannot be used with CNG
- npx expo run:ios alone applies the new plugin to an existing ios folder