Tap the camera button in an app, and a photo appears a moment later. Start a run, and the app follows your location. Rotate the phone and the interface responds.
JavaScript may be responsible for the application logic behind those features, but it does not talk directly to the camera sensor, GPS hardware, or accelerometer. Even cross-platform apps built in React Native have to cross from
JavaScript into native platform code before they can reach many device capabilities.
The route can pass through a JavaScript runtime, framework bindings, Android or iOS APIs, system services, hardware abstraction layers, as well as drivers. It also changes depending on the framework and the hardware involved. A request for the user’s location, for example, is very different from
processing 30 camera frames every second.
JavaScript Only Sees the APIs Its Runtime Gives It
Consider a web app that wants the user’s current location.
Its JavaScript can call navigator.geolocation.getCurrentPosition(). The method looks like direct access to location hardware, but navigator.geolocation is actually a Web API exposed by the browser. Chrome, Safari, or another browser handles the request and connects it to location services
available through the operating system.
Packaged mobile apps take another route. React Native exposes platform functionality to JavaScript through APIs backed by native code. Developers can also create native modules when an application needs functionality that the framework or an existing library does not provide. Capacitor uses
plugins for the same broad purpose, connecting JavaScript-facing APIs to native implementations on both Android and iOS.
So “JavaScript mobile app” can describe quite different systems. A Progressive Web App running in Chrome, a React Native application, and also a Capacitor application may all open the camera, but they do not reach it through the same software stack.
Their JavaScript engines can differ too. React Native uses Hermes by default in current releases. Chrome uses Google’s V8, while Apple’s browser stack uses WebKit and JavaScriptCore.
JavaScript starts the request. The runtime determines where it can go from there.
Crossing From JavaScript Into Native Code
Hardware-backed features eventually reach code that can work with Android or iOS APIs. How they get there depends heavily on the framework architecture.
Older React Native versions used an asynchronous JavaScript bridge. Data passed between JavaScript and native code had to be serialized, transferred, and reconstructed on the other side. For occasional calls, the cost was often unremarkable. High-frequency communication exposed the limits much
faster.
Modern React Native uses a different architecture. Its JavaScript Interface, or JSI, allows JavaScript and C++ to interact without relying on the old serialized bridge. Turbo Native Modules use this architecture to expose native functionality.
For a location lookup, the overhead is usually small: JavaScript may receive a handful of values such as latitude, longitude, and accuracy. Camera processing is less forgiving. A single uncompressed 1920 × 1080 RGBA frame is roughly 8 MB. At 30 frames per second, repeatedly copying and serializing
full frames would create a substantial amount of work.
React Native camera libraries such as VisionCamera therefore keep frame processing close to native code and use JSI-based mechanisms instead of sending every full frame through the legacy JavaScript bridge.
Similar pressure appears with high-frequency readings from device sensors, real-time audio processing, and some Bluetooth workloads. In these cases, unnecessary copying, serialization, or work on a busy thread can show up as dropped frames, delayed input, or increased CPU use.
Capacitor has a different architecture. Its plugins communicate between the web layer and native implementations rather than using React Native’s JSI. Both frameworks can expose a camera method to JavaScript, but the machinery behind that method is not interchangeable.
Android or iOS Decides What Happens Next
Reaching native code is only part of the trip. The application still has to use APIs provided by the operating system.
Take location tracking. On Android, an app might use the Fused Location Provider API from Google Play services or Android’s LocationManager. On iOS, developers commonly work with Apple’s Core Location framework.
Neither API is simply a command to read a GPS chip. Phones can estimate location using satellite signals, Wi-Fi, cellular networks, and other available information. What the application receives depends on the API, requested accuracy, available sources, device state, and permissions.
Camera access has a similar abstraction. Android provides Camera2 and the higher-level CameraX library. On iOS, applications commonly use AVFoundation. Developers work with concepts such as camera devices, capture sessions, focus, exposure, and image output while the platform deals with much of
the hardware-specific implementation.
A Samsung Galaxy and a Google Pixel can contain different camera components while exposing the Android camera APIs an application expects.
Some platform differences still reach application code. Android and iOS have their own APIs, background-execution rules, permission models, and hardware capabilities. A cross-platform library can hide common differences, but specialized features often require platform-specific work.
Permission Checks Can End the Request Early
The operating system may stop a hardware request before the application receives any data.
Camera, microphone, location, and nearby-device access can expose sensitive information, so Android and iOS put them behind permission controls. Having the right API call in the code is not enough.
On Android, several sensitive permissions must be requested at runtime. Newer Android versions also use more specific Bluetooth permissions than older releases. Location access may be approximate instead of precise.
iOS has its own authorization rules. Location access, for example, can depend on whether the app is currently in use and which level of access the user has approved.
Browsers add another layer for web applications. The Geolocation API requires a secure context and user permission. A site cannot silently retrieve a visitor’s location simply because its JavaScript calls the API.
Permission states also change. Someone can deny camera access, grant it later in system settings, or reduce the level of location access after using the app for months.
The application has to work in each of those states. A QR scanner needs an alternative screen when camera access is denied. A mapping feature cannot assume precise coordinates will always be available. Bluetooth setup has to recover cleanly when nearby-device permission is missing.
Below the Platform API, the Stack Gets Device-Specific
Android’s camera architecture shows how much still happens below an application-facing API.
An app can call CameraX or Camera2, but those APIs sit above lower-level platform components. Android defines a camera Hardware Abstraction Layer, or HAL, that provides a standard interface between the Android camera framework and device-specific implementations. Vendor code and drivers then deal
with the actual hardware.
Other components have their own paths. Accelerometers and gyroscopes feed readings through the sensor stack. Bluetooth communication passes through its own services and controller interfaces. The implementation can also vary by phone manufacturer and chipset.
A common diagram reduces the process to:
JavaScript → native code → operating system → driver → hardware
It is useful for orientation, but real devices can insert system services, inter-process communication, native libraries, HAL implementations, vendor processes, and kernel drivers between those boxes.
Application developers normally stay several layers above that machinery. Still, those lower levels occasionally become visible through device-specific bugs. A Bluetooth feature that works on a Pixel may behave differently on a particular Samsung model even when the JavaScript code is identical.
That is one reason testing hardware-dependent functionality only in an emulator is risky. Camera behavior, Bluetooth radios, GPS accuracy, and physical device sensors need real hardware at some point in the test cycle.
The Data Makes the Same Journey Back
Once the platform completes the operation, the result has to return to application code.
A one-time location request may come back as coordinates, accuracy information, and a timestamp. A camera plugin might return a file URI rather than the raw pixels. An accelerometer can produce a continuing stream of measurements.
The amount and frequency of that data change the engineering problem.
An occasional location update places little pressure on the boundary between native and JavaScript code. Motion data can arrive many times per second. Video is heavier again. At 60 FPS, each frame arrives roughly every 16.7 milliseconds. If an application needs to analyze every frame before the
next one arrives, there is little room for unnecessary work.
For that reason, computationally intensive processing often remains in native code even when most of the application is written in JavaScript. A computer vision pipeline might analyze camera frames natively and send JavaScript only the detected barcode or object coordinates. A Bluetooth
integration can process a stream of binary packets before exposing the values the interface actually needs.
Moving less data across the boundary can matter more for mobile performance than maximizing the percentage of code written in one language.
Hardware Is Where Shared Code Has Clear Limits
Cross-platform development works particularly well for UI, forms, networking, state management, as well as business logic that behaves similarly on both Android and iOS. Hardware integration can reduce that overlap.
Common operations are rarely a problem. Mature libraries already cover tasks such as taking a photo, selecting an image, retrieving a location, and reading standard device sensors.
More specialized requirements change the calculation. A product may need a manufacturer’s Bluetooth SDK, continuous background location, custom camera processing, or access to a platform API that has no equivalent on the other operating system. Shared JavaScript can still drive much of the
product, while the hardware integration uses Swift or Objective-C on iOS and Kotlin or Java on Android.
How much native work is required depends less on whether a product “uses Bluetooth” or “uses the camera” than on what it actually does with them.
Reading a heart-rate value occasionally from a standard BLE monitor is one task. Maintaining a background connection to proprietary industrial equipment, decoding a continuous stream of binary data, recovering from dropped connections, and supporting several phone models is another.
Both can sit behind one JavaScript screen. Underneath, they are very different engineering problems.
