Framework guide
Expo vs bare React Native
@markpdf/react-native does not depend on any native modules of its own — it uses global fetch/FormData/XMLHttpRequest, available in both. The difference is in which picker you use to get the uri/name of the file.
Expo: expo-document-picker
Does not require additional permissions on app.json — the operating system’s file chooser handles access.
Bare RN: react-native-document-picker
On Android, check that your targetSdkVersion is compatible with the version of react-native-document-picker you install — recent versions of Android Scoped Storage change how content:// URIs are resolved. Follow the package installation guide for your version of RN.
Permisos
Neither expo-document-picker nor react-native-document-picker require explicit storage permissions in most cases — both delegate to the system’s native file picker (Document Picker on iOS, Storage Access Framework on Android), which does not need READ_EXTERNAL_STORAGE. If your app also needs to access the photo gallery to attach scanned images, use expo-image-picker (Expo) or react-native-image-picker (bare) and follow their separate permission requirements — that’s separate from @markpdf/react-native.
Where does the API key live?
Unlike a web app, a mobile app binary does not have a “server” that serves environment variables at runtime — any string embedded in the JS bundle is removable by someone with the .ipa/.apk. Options, from most to least safe:
- Proxy on your backend (recommended for production): the app calls your own endpoint, which in turn calls markpdf with the key saved server-side. The app never sees the markpdf key.
- Embedded low privilege key: if you do not have your own backend, use a key dedicated only to that app, with limited usage and billing limits, assuming it can be leaked.
- Build environment variables (
EAS Secrets in Expo, .env + react-native-config in bare): they prevent hardcoding the key in the versioned source code, but they do not prevent it from ending up in the final decompilable bundle. Useful to not commit the key to the repo, not to hide it from the end user.
If your app handles sensitive documents from real users, use option 1 (proxy in your backend). A key embedded in the binary, even if it is not in the repo, is still removable with standard decompilation tools.
Networking en segundo plano
Uploading large PDFs from the picker may take time; If the user minimizes the app during upload, iOS/Android may suspend the network task depending on the operating system and the state of the app. For long, reliable background uploads, consider a background upload library (e.g. react-native-background-upload) rather than relying on fetch/XMLHttpRequest to survive indefinitely with the app in the background — this is a general RN limitation, not specific to @markpdf/react-native.