How to add native code to your app with Expo Modules
Article Summary
Jacob Clausen from Expo shows how to break free from SDK limitations. Building custom native modules doesn't mean abandoning Expo's developer experience.
This hands-on tutorial walks through creating a custom Expo Module that detects audio routes (speaker, headphones, Bluetooth) in React Native apps. It demonstrates the full workflow from TypeScript API design through Swift and Kotlin implementation, proving you can extend Expo apps with native code while keeping Continuous Native Generation.
Key Takeaways
- Expo Modules API abstracts JSI for consistent cross-platform native code
- Local modules live in version control, root native folders stay generated
- Events, AsyncFunction, OnStartObserving handle JS to native communication automatically
- Build locally with Xcode/Android Studio or remotely with EAS Build
- Audio route detection requires AVFoundation (iOS) and AudioManager (Android)
Expo Modules let you write custom Swift and Kotlin code without ejecting from the Expo ecosystem or managing native project files manually.
About This Article
React Native developers need to figure out which audio output device is currently active, whether that's a speaker, headphones, Bluetooth, or wired headset. This requires using platform-specific native APIs like AVFoundation on iOS and AudioManager on Android.
Jacob Clausen's tutorial shows how to use the Expo Modules API to build a local module. It uses AsyncFunction to check the current route and Events with OnStartObserving and OnStopObserving lifecycle hooks. These hooks automatically emit route changes whenever JavaScript listeners are added or removed.
Apps can now check audio routes immediately with getCurrentRouteAsync() and update the UI reactively when routes change through onAudioRouteChange events. This all works while keeping Continuous Native Generation intact and eliminating the need to manage native projects manually.