Integrating Native Modules with React Native: Accessing Device Features

December 20, 2024By Rakshit Patel

React Native allows developers to build cross-platform mobile apps with a single JavaScript codebase. But sometimes, the built-in features of React Native may not be sufficient, especially when you need to access device-specific features like camera, GPS, sensors, or Bluetooth.

This is where Native Modules come in. Native modules enable you to bridge Java (for Android) or Swift/Objective-C (for iOS) code into React Native, giving you direct access to native device features.

In this guide, you’ll learn:

  1. What Native Modules are.
  2. Why you might need them.
  3. How to create custom native modules for both Android and iOS.

What Are Native Modules in React Native?

A Native Module in React Native is a bridge between JavaScript and native code (Java/Swift/Objective-C). React Native provides a way to call native methods from JavaScript, allowing you to access device features not natively supported by React Native.

When Do You Need a Native Module?

  • Access to features like Bluetooth, Camera, Sensors, or Biometric Authentication.
  • Using custom SDKs that have no official React Native library.
  • When you need better performance for computationally expensive tasks (e.g., image processing).

How Do Native Modules Work?

  1. JavaScript Side: Call native methods using the NativeModules API.
  2. Native Side (Java/Swift): Write custom functions to interact with native APIs.
  3. Bridge: The React Native bridge handles communication between JavaScript and Native code.

Creating a Custom Native Module (Step-by-Step Guide)

We’ll create a simple custom native module for both Android and iOS. The module will expose a function to get the device name.


Part 1: Creating a Native Module for Android

Step 1: Create a New React Native Project

npx react-native init NativeModuleExample
cd NativeModuleExample


Step 2: Create a New Native Module in Android (Java)

  1. Navigate to android/app/src/main/java/com/nativemoduleexample/.
  2. Create a new file called DeviceInfoModule.java.

DeviceInfoModule.java


package com.nativemoduleexample;

import android.os.Build;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Promise;

public class DeviceInfoModule extends ReactContextBaseJavaModule {

DeviceInfoModule(ReactApplicationContext context) {
super(context);
}

@Override
public String getName() {
return "DeviceInfo";
}

@ReactMethod
public void getDeviceName(Promise promise) {
try {
String deviceName = Build.MODEL; // Get the device model name
promise.resolve(deviceName);
} catch (Exception e) {
promise.reject("Error", e);
}
}
}

Explanation

  • ReactContextBaseJavaModule: Base class for native modules.
  • @ReactMethod: Exposes the method to React Native.
  • Promise: Used to return data asynchronously (similar to resolve/reject in JavaScript).

Step 3: Register the Module in MainApplication.java

  1. Open MainApplication.java.
  2. Add your module to the list of packages.

MainApplication.java


package com.nativemoduleexample;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;

import java.util.Arrays;
import java.util.List;

import com.nativemoduleexample.DeviceInfoPackage; // Import the package

public class MainApplication extends Application implements ReactApplication {

private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}

@Override
protected List getPackages() {
return Arrays.asList(
new MainReactPackage(),
new DeviceInfoPackage() // Register the package here
);
}

@Override
protected String getJSMainModuleName() {
return "index";
}
};
}


Step 4: Create the Package Class (DeviceInfoPackage.java)

  1. In the same directory as DeviceInfoModule.java, create DeviceInfoPackage.java.

DeviceInfoPackage.java


package com.nativemoduleexample;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;

import java.util.Arrays;
import java.util.List;

import com.nativemoduleexample.DeviceInfoPackage; // Import the package

public class MainApplication extends Application implements ReactApplication {

private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}

@Override
protected List getPackages() {
return Arrays.asList(
new MainReactPackage(),
new DeviceInfoPackage() // Register the package here
);
}

@Override
protected String getJSMainModuleName() {
return "index";
}
};
}


Step 5: Call Native Module from JavaScript

App.js


import React, { useEffect, useState } from 'react';
import { View, Text, NativeModules } from 'react-native';

const App = () => {
const [deviceName, setDeviceName] = useState('');

useEffect(() => {
NativeModules.DeviceInfo.getDeviceName()
.then((name) => setDeviceName(name))
.catch((error) => console.error(error));
}, []);

return (

Device Name: {deviceName}

);
};

export default App;


Part 2: Creating a Native Module for iOS (Swift)


Step 1: Open the iOS Project in Xcode

npx pod-install

Open the iOS project in Xcode.


Step 2: Create a New Native Module

  1. Right-click the NativeModuleExample folder and create a new Swift file called DeviceInfo.swift.
  2. Xcode will ask if you’d like to create a Bridging Header. Click Yes.

DeviceInfo.swift


import Foundation

@objc(DeviceInfo)
class DeviceInfo: NSObject {

@objc
func getDeviceName(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
let deviceName = UIDevice.current.name
resolve(deviceName)
}

@objc
static func requiresMainQueueSetup() -> Bool {
return false
}
}


Step 3: Register the Module in RCTBridgeModule

  1. Open AppDelegate.m and import the module.
  2. Create a bridging file DeviceInfo.m.

DeviceInfo.m

#import <React/RCTBridgeModule.h>

@interface RCT_EXTERN_MODULE(DeviceInfo, NSObject)
RCT_EXTERN_METHOD(getDeviceName:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
@end


Step 4: Call Native Module from JavaScript

App.js


import React, { useEffect, useState } from 'react';
import { View, Text, NativeModules } from 'react-native';

const App = () => {
const [deviceName, setDeviceName] = useState('');

useEffect(() => {
NativeModules.DeviceInfo.getDeviceName()
.then((name) => setDeviceName(name))
.catch((error) => console.error(error));
}, []);

return (

Device Name: {deviceName}

);
};

export default App;


Testing the Native Module

Run the following command to test the app on Android or iOS:

npx react-native run-android
npx react-native run-ios

Check if the Device Name is displayed on the screen.


Summary of Key Concepts

  1. Native Modules bridge JavaScript to Native (Java, Swift, or Objective-C).
  2. Write native functions and expose them using React Bridge.
  3. Call native functions using NativeModules in JavaScript.

Conclusion

Integrating Native Modules into a React Native app allows access to native device features like camera, Bluetooth, sensors, etc. This guide showed you how to create a custom getDeviceName module for both Android and iOS.

With this knowledge, you can now create custom modules to extend your React Native app’s functionality. 🚀

Rakshit Patel

Author ImageI am the Founder of Crest Infotech With over 15 years’ experience in web design, web development, mobile apps development and content marketing. I ensure that we deliver quality website to you which is optimized to improve your business, sales and profits. We create websites that rank at the top of Google and can be easily updated by you.

CATEGORIES