Native Bridging for iOS and Android in React Native

Rupesh Chaudhari
Simform Engineering
10 min readJun 21, 2021

For those who are not familiar with React Native, it is a cross-platform development framework allowing you to create native apps for iOS and Android. Using React Native, you can maintain two platforms using the same codebase, allowing faster development, iteration, and knowledge-sharing.

With this framework, we have two sides, JavaScript and Native. Between the two is a bridge, allowing bidirectional and asynchronous communication. This is the power of React Native, on top of a multitude of other benefits.

In 2020, we’ve seen the likes of Facebook, Bloomberg, and Shopify using React Native to develop their mobile applications, amongst others in the Fortune 500. With over 11 million JavaScript developers and more companies switching to React Native, releasing your technology for React Native could bring more growth.

What is React Native bridging?

React Native Bridging is a concept that was developed by the React team to help the mobile app developers build their own custom modules, if not provided by the default Components given by React.

React Native provides developers with a variety of modules that developers can use to create functionality in the application. For example, React Native provides its own “Net Info” module to check for Internet Connectivity in applications. However, sometimes an app needs access to a platform API for which React doesn’t have a module yet. Or maybe the app needs a custom functionality that cannot be achieved using default React Native modules.

Hence, React Native allows us to write Native Code (Android and iOS) and communicate between native code and React Native JavaScript code to achieve custom-developed functionality.

According to the documentation, React Native team believes that if React Native doesn’t support a native feature that you need, you should be able to build it yourself by using Bridging.

There are two ways to bridge native code to JavaScript:

  1. Native Modules
  2. Native UI Components

But in this article, we are only going to discuss about native modules.

Native Modules can be used to access native iOS and Android features.

We will see how to create Native modules for both iOS and android separately by creating a demo application.

An overview of steps to create a native android module:

  1. Create a java class file that will contain all the native logic you want to execute and variables and callbacks you want to export to JavaScript.
  2. Create a java package for the java class you just created in the previous step and register the module in this package.
  3. Now the last step is to make the package available in the JavaScript code. To do so add your package in the return array of getPackages() method in the MainApplication.java file.
  4. That’s it you have now exported your native module to javascript, to access it we will use NativeModules from React Native.

We’ll understand this process in more detail by practically implementing a native module.

So now let’s directly jump into some code and practical implementation.

For this example, we will be creating a native module in android that alters with sound to reproduce a funny one. For example, we can make a person sound like an alien or a kid.

Let’s dive right in….
  • Let’s start by first creating a new React Native project:

Type the below command into your terminal window to create a new React Native Project from scratch

react-native init VoiceChanger

Here I have named the project “VoiceChanger” you are free to name it whatever you like.

  • Change your current working directory to the new project we just created

Type below command in your terminal window

cd VoiceChanger

For the sake of simplicity of this article, I will use a static mp3 file that we are going to modify in our native code, but you can also record the audio through the phone’s microphone and alter that.

Our UI is going to be straightforward and looking something like this on iOS and Android devices:

UI on iOS and Android

When the user taps any effect button then that type of voice will be played.

For example, if a user taps on the alien icon, then an alien-type voice will be played, and likewise for the child icon.

We will also cover how we can change the speed of audio, that is, we will be playing audio at 2x speed and 0.5x speed.

  • Modify your App.js to look something like this:

We have commented ,

const { VoiceChangingModule } = NativeModules;

because we have not created a native module yet. Once we have created NativeModule named “VoiceChangingModule” we will uncomment that line

Now we will be creating a Native Android Module, for that follow the below steps

  • Open Android studio in your project’s android directory
  • If you have opened the project correctly you will see something like this in your project files on the left side in android studio.
  • Navigate to the folder containing MainApplication.java
  • Right-click the folder name > Go to New Option > Select Java Class
  • Enter Java Class File Name

I have named the file as VoiceChangingModule, this is a module file that will contain all of our native android logic.

  • Paste this code in your VoiceChangingModule Class:

As you can notice we have a getName() method which returns a String, this is a name with which we can access our module in JavaScript code

  • Now we need to wrap our module in a package that will be exported to javascript for that we will create a new java class file

I am going to name this File “VoiceChangingPackage

  • Edit the package VoiceChangingPackage file to create and return the module we just created
  • Add the package in PackageList of getPackages() method of MainApplication.java

Yayyy!! That’s it we have successfully exported our Native Android module to Javascript.

Now let’s access the module from javascript, but before doing so let’s just add 4 methods to our VoiceChangingModule.java file

  • changeVoiceToAlien
  • changeVoiceToChild
  • speedUpVoice
  • slowDownVoice

After adding these methods our final VoiceChangingModule.java will look something like this.

As you can see, we have just tweaked a little bit of Pitch and speed of voice playback to achieve these kinds of voice effects.

Now let’s access these methods in javascript.

  • Get the Module in Javascript from NativeModules provided by react-native
const { VoiceChangingModule } = NativeModules;

Uncomment the above line in our App.js which we commented earlier.

  • Now add these functions in App.js which will be called on each voice effect icon’s press

Note: As we have only created this native module in android only so we can access this module in android platform only.

That’s it we have made a native android module and utilized it in javascript.

Now let’s run this example, in your command line type:

npx react-native run-android

Note: If you have done changes in native side and those are not reflecting you need to rebuild the project because you have changed native code.

Now that we have created a native android module, let’s take a look at how we can create a native iOS module?

An Overview of Steps to create a native iOS module:

  1. Create a swift class which will contain all the native logic and variable and callbacks you want to export to the javascript
  2. Create a bridging header file that will help communicate between swift and objective C, now import RCTBridgeModule in this file while providing an interface to register the bridge module.
  3. Create an objective C file and export module we created in the first step by using RCT_EXTERN_METHOD
  4. Now we can access the native module we just created in our javascript code

Like in the previous section of creating a native android module we’ll now similarly understand this process by creating a native iOS module.

So, we will now create an iOS native module for the same functionality that we achieved in android, i.e., adding voice effects to a sound.

  • We do not need to create a new project as we are going to add a native module in iOS in the same project that we created above in the native android module part.

If you have not followed (Native Android Module) then please refer above and set up a bare react native project

  • Open the project folder then navigate to the iOS folder and find VoiceChanger.xcodeworkspace and open it
VoiceChanger -> iOS -> VoiceChanger.xcodeworkspace
  • After opening the XCode project you will see something like this

NOTE: Appearance may vary based upon the version of XCode you are using.

  • The next step is to create a new swift file in the project, which will contain our native swift logic
File -> New -> File
  • After clicking the new file option a popup will appear asking us to select which type of file we want to create. As we want to create a swift file, select swift and click next
Swift -> Next
  • After clicking next, we will be asked for the name of the file we want to create, enter the name of the swift file, in my case, it is “VoiceChangerModule”. And select where do you want to create this file, select your projects folder, typically this folder contains all the native iOS logic and also AppDelegate file.
  • Click create, you will be prompted to if you want to create a bridging header file. Select Yes.

Bridging header file basically acts as a communicator between swift code and objective C code.

  • If you have clicked on creating a bridging header, you will have a “VoiceChanger-Bridging-Header.h” file. Paste the following code into that file.

RCTBridgeModule provides us an interface to register our bridge module

  • Download any mp3 or any audio file and place it in our project folder. Here I have named my sound file “sound_sample.mp3” so it would be better if you follow that.
  • Edit your “VoiceChangingModule.swift” file to write voice changing logic in it
  • As you can see, we have four functions:

1. changeVoiceToAlien()

2. changeVoiceToChild()

3. speedUpVoice()

4. slowDownVoice()

  • These four functions use a helper function playModifiedSound() which takes two parameters:
  1. value — Takes Float value — Describes how much value to be used, in this case, rate or pitch
  2. rateOrPitch — Takes String value — is used to just know whether to change rate of Audio or Pitch

We can also see we have requiresMainQueueSetup() function which returns true. This function is used to tell native code that we want to run our module on mainQueue Thread.

  • Now that we have written our native logic in our functions, it is time to export them to javascript. For that, we will create a new Objective-C file.
Go To File -> New -> File -> Select Objective-C type of file -> Enter File Name -> Click Next
Create New File
Select Objective-C and then Next
Enter File Name and then Next
  • Now that we have created an Objective-C file, let’s edit it to export our module and its functions to javascript

That’s it! We have now created and exported a native iOS module to javascript. Let’s see how will we access it in javascript.

But before that, we need to enable audio service for our iOS app.

For that Go To:

Add Capability Button in Signing and Capabilities tab in project details -> select Background Modes -> then check these two options
Enable Audio and Background Processing

Do not forget to build the project from XCode after doing changes.

  • After you have built the application from XCode go to your App.js file and edit it to call the native module methods that we just created on each button press.

Notice that we are calling differently for each platform with just one change, i.e., in android, we call the native module method with a parameter and in iOS without any parameter.

Yay!!, That’s it, we have made Native Android and iOS modules in React Native to use native code and achieve similar behavior in both platforms.

Thus, this is how we can create a bridge between React Native JavaScript code and native android/iOS Code.

If you want to skip the code and want to see the code in action, then feel free to download the demo of this project from below repository

https://github.com/mobile-simformsolutions/react-native-bridging

Conclusion: As we saw react-native bridging is a quite powerful feature for accessing native features that are not available in react native environment and it provides developers an option to develop their features natively if they want.

Hope you found this article helpful, if so then please don’t forget to give some claps 👏🏻 and share it with your other fellow developer friends.

Thank You!

--

--

Rupesh Chaudhari
Simform Engineering

React Native | Swift-UI | iOS | Android | React.js | Nextjs | .NET MAUI