React Native Bridging Modules for Android from Scratch on Windows

When using React Native to write mobile apps, JavaScript is the primary programming language. However, sometimes, you may want to call a platform API that not supported by existing React Native component or use a third-party Android library that built as an AAR file. For these cases, you need to write native code for bridging using Android Studio and Xcode. In this article, I will demonstrate how to create a simplest React Native Bridge module step by step.

Prerequisites

React Native Bridge Module: Hello World

Here is my project structure:

--Project folder

  --package.json

  --android // a folder that contains Java code for native module

  --index.js

Package.json

Create an empty folder named react-native-helloworld, which is also the module name. Initialize the project:

cd react-native-helloworld
npm init

react native module init

There is a package.json file generated.

Android

Create a simple Android project. You can refer to React Native docs:

react native android

MyModule extends ReactContextBaseJavaModule class and implements the functionality required by the JavaScript.

package com.yushulx.helloworld;

import android.widget.Toast;

import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

public class MyModule extends ReactContextBaseJavaModule {

  public MyModule(ReactApplicationContext reactContext) {
    super(reactContext);
  }

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

  @ReactMethod
  public void alert(String message) {
    Toast.makeText(getReactApplicationContext(), message, Toast.LENGTH_LONG).show();
  }
}

The string returned by getName() has to be same as the class name. Here it is MyModule.

MyPackage is used to register the module.

package com.yushulx.helloworld;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MyPackage implements ReactPackage {

  @Override
  public List<Class<? extends JavaScriptModule>> createJSModules() {
    return Collections.emptyList();
  }

  @Override
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    return Collections.emptyList();
  }

  @Override
  public List<NativeModule> createNativeModules(
                              ReactApplicationContext reactContext) {
    List<NativeModule> modules = new ArrayList<>();

    modules.add(new MyModule(reactContext));

    return modules;
  }

}

Index.js

This file is used to wrap the native module in a JavaScript module.

import {NativeModules} from 'react-native';
module.exports = NativeModules.MyModule;

So far, we have finished the React Native module.

React Native Example

Create a React Native project:

react-native init Example

Since all Node modules should be installed under {React Native project}\node_modules\, we need to add the project directory of the bridging module to the package.json file of the React Native project.

"dependencies": {
	"react": "16.0.0-alpha.6",
	"react-native": "0.43.3",
	"react-native-helloworld":"file:../"
},

Install the module:

npm install

react native install module

Link the dependency:

react-native link

This command will cause some file changes.

  • android\settings.gradle
    include ':react-native-helloworld'
    project(':react-native-helloworld').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-helloworld/android')
    
  • android\app\build.gradle
    dependencies {
        compile project(':react-native-helloworld')
    }
    
  • android\app\src\main\java\com\example\MainApplication.java
    import com.yushulx.helloworld.MyPackage;
    protected List<ReactPackage> getPackages() {
          return Arrays.<ReactPackage>asList(
              new MainReactPackage(), 
              new MyPackage()
          );
        }
    

Use the custom React Native module in index.android.js:

import MyModule from 'react-native-helloworld';

const onButtonPress = () => {
  MyModule.alert('Hello World');
};

export default class Example extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Button title='Click' onPress={onButtonPress}/>
      </View>
    );
  }
}

Run the Android app:

react native android app

Source Code

https://github.com/yushulx/react-native-helloworld

  • John Lington

    Great tutorial, thanks Xiao Ling

  • Phạm Hoàng Minh Nhật

    Hi Xiao Ling , I want to load a xml layout to my app but the error is `package R does not exist` , can you help me with this issue ? thank

  • Anky An

    Hi Xiao Ling. This project is for calling some native methods from React Native. The native project is just some classes. What if I want to start a native activity in an existing Android app? Or integrate React Native with an existing Android project?

  • Augusto Gonzalez

    Thanks you so much.

  • http://www.dynamsoft.com/ Xiao Ling

    Right. {React Native project} means your React Native project, not the bridging module project :)

  • Augusto Gonzalez

    I would like to know exactly which is this:
    Since all Node modules should be installed under {React Native project}node_modules, we need to add the project directory of the bridging module to the package.json file of the React Native project.

    the project directory is C:/root/myreactnativeproject?
    Is that right?

  • Shongsu

    Thanks. It helped me a lot.

  • idhamhafidz

    thanks. awesome tutorial