All Articles

React Native - How to make an Android native module

This is following an example from the official document with some of my personal input

Before creating a native module for a react-native project, you have to understand how react-native works for an Android app. A general tree is defined in AndroidManifest.xml like I have posted. And how the app actually works or how it is composed is declared in MainApplication.java

There are two default java files in a react-native project. One is MainApplication.java, which I am going to use in order to add a native module, and the ohter is MainActivity.java, which you rarely deal with throughout your project. The only thing declared in MainActivity.java is the name of your project like below;

package com.your-app-name;

import com.facebook.react.ReactActivity;

public class MainActivity extends ReactActivity {

  /**
   * Returns the name of the main component registered from JavaScript. This is used to schedule
   * rendering of the component.
   */
  @Override
  protected String getMainComponentName() {
    return "your-app-name";
  }
}

And everything else is declared in MainApplication.java. When you create a native module of your own, you have to pay attention to this section right here;

    @Override
    protected List<ReactPackage> getPackages() {
        @SuppressWarnings("UnnecessaryLocalVariable")
        List<ReactPackage> packages = new PackageList(this).getPackages();

        // packages.add(new MyReactNativePackage());  // <-- this is where you are going to add your module
        return packages;
    }

Technically, you are not adding a module to MainApplication.java. You are adding a package which includes a module to MainApplication.java.

First, you create your module like this. The below example is directly from the official website

// ToastModule.java

package com.your-app-name;

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;

import java.util.Map;
import java.util.HashMap;

public class ToastModule extends ReactContextBaseJavaModule {
// a native module is a Java class that extends ReactContextBaseJavaModule

  private static ReactApplicationContext reactContext;

  private static final String DURATION_SHORT_KEY = "SHORT";
  private static final String DURATION_LONG_KEY = "LONG";

  ToastModule(ReactApplicationContext context) {
    super(context);
    reactContext = context;
  }

  @Override
  public String getName() { // a ReactContextBaseJavaModule requires this method to be implemented
    return "ToastExample"; // this string represents the name of the NativeModule that you are creating
  }                        // therefore, you can access this module through React.NativeModules.ToastExample

  @Override
  public Map<String, Object> getConstants() {     // this is optional
    final Map<String, Object> constants = new HashMap<>();
    constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT);
    constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG);
    return constants;
  }

  @ReactMethod   // this decorator allows you to access this Java method with JavaScript. You will see what I mean later
  public void show(String message, int duration) {
    Toast.makeText(getReactApplicationContext(), message, duration).show();
  }
}

Now you have to create a package to register your module

// CustomToastPackage.java

package com.your-app-name;

import com.facebook.react.ReactPackage;
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 CustomToastPackage implements ReactPackage {

  @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 ToastModule(reactContext));  // Your module is added right here

    return modules;
  }

}

Now you add the package to MainApplication.java

...
import com.your-app-name.CustomToastPackage; // <-- Add this line with your package name.
...

protected List<ReactPackage> getPackages() {
  @SuppressWarnings("UnnecessaryLocalVariable")
  List<ReactPackage> packages = new PackageList(this).getPackages();

  packages.add(new CustomToastPackage()); // <-- Add this line with your package name.
  return packages;
}

Now you create a JavaScript file to wrap the native module you have just created, which is React.NativeModule.ToastExample.

//ToastExample.js

import { NativeModules } from "react-native";
module.exports = NativeModules.ToastExample;

This is not in the official document, but you can also do it like this

import { NativeModules } from "react-native";

const { ToastExample } = NativeModules;

export default ToastExample;

You can all the show method which you have decorated with ReactMethod in ToastModule.java like this

import ToastExample from "./ToastExample";

ToastExample.show("Awesome", ToastExample.SHORT);

This shows a toast with a text Awesome when you launch your Android app

Mar 16, 2020

AI Enthusiast and a Software Engineer