LibraryWriting Java/Kotlin code for modules

Writing Java/Kotlin code for modules

Learn about Writing Java/Kotlin code for modules as part of React Native Cross-Platform Mobile Development

Native Modules in React Native: Bridging to Java/Kotlin

React Native allows you to leverage the power of native device features by writing custom native modules. This is crucial when a specific functionality isn't available through React Native's core components or third-party libraries, or when you need to optimize performance for computationally intensive tasks. This guide focuses on writing these modules using Java or Kotlin for Android.

Understanding the Bridge

The React Native bridge is the communication layer between your JavaScript code and the native platform (Java/Kotlin for Android, Objective-C/Swift for iOS). It serializes and deserializes data, enabling asynchronous communication. When you call a native method from JavaScript, the bridge sends a message to the native side, executes the code, and sends a response back.

Native modules extend React Native with platform-specific capabilities.

Native modules are classes written in Java or Kotlin that expose methods and constants to your JavaScript code. They act as a gateway to the native platform's APIs.

To create a native module, you'll typically create a Java or Kotlin class that extends ReactContextBaseJavaModule. This class will contain the methods you want to expose to JavaScript. These methods are annotated with @ReactMethod to make them callable from the JS side. You also need to register your module with React Native by implementing a ReactPackage.

Creating a Simple Native Module (Java/Kotlin)

Let's walk through creating a basic native module that exposes a simple string constant and a method to show an alert.

1. Create the Module Class

In your Android project (usually located at

code
android/app/src/main/java/...
), create a new Java or Kotlin file for your module. For example,
code
MyNativeModule.java
or
code
MyNativeModule.kt
.

Example (Java):

java
package com.your_app_name;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Promise;
import android.widget.Toast;
public class MyNativeModule extends ReactContextBaseJavaModule {
public MyNativeModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "MyNativeModule";
}
@ReactMethod
public void showMessage(String message) {
Toast.makeText(getReactApplicationContext(), message, Toast.LENGTH_LONG).show();
}
@ReactMethod
public void addNumbers(int a, int b, Promise promise) {
try {
int result = a + b;
promise.resolve(result);
} catch (Exception e) {
promise.reject("ERR_ADDITION_FAILED", e.getMessage());
}
}
}

Example (Kotlin):

kotlin
package com.your_app_name
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.Promise
import android.widget.Toast
class MyNativeModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
override fun getName(): String {
return "MyNativeModule"
}
@ReactMethod
fun showMessage(message: String) {
Toast.makeText(reactApplicationContext, message, Toast.LENGTH_LONG).show()
}
@ReactMethod
fun addNumbers(a: Int, b: Int, promise: Promise) {
try {
val result = a + b
promise.resolve(result)
} catch (e: Exception) {
promise.reject("ERR_ADDITION_FAILED", e.getMessage())
}
}
}

2. Create the Package

You need a

code
ReactPackage
to register your module. Create a new Java or Kotlin file for this, e.g.,
code
MyNativePackage.java
or
code
MyNativePackage.kt
.

Example (Java):

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 MyNativePackage implements ReactPackage {
@Override
public List createNativeModules(ReactApplicationContext reactContext) {
List modules = new ArrayList<>();
modules.add(new MyNativeModule(reactContext));
return modules;
}
@Override
public List createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}

Example (Kotlin):

kotlin
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
class MyNativePackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List {
val modules = mutableListOf()
modules.add(MyNativeModule(reactContext))
return modules
}
override fun createViewManagers(reactContext: ReactApplicationContext): List> {
return emptyList()
}
}

3. Register the Package

Finally, you need to register your

code
ReactPackage
in your
code
MainApplication.java
(or
code
MainApplication.kt
) file. Find the
code
getPackages()
method and add an instance of your package to the list.

Example (Java -

code
MainApplication.java
):

java
// ... other imports
import com.your_app_name.MyNativePackage;
public class MainApplication extends Application implements ReactApplication {
// ...
@Override
protected List getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List packages = new PackageList(this).getPackages();
// Packages that include code in this app that is packaged into the library
// or that use native modules.
packages.add(new MyNativePackage()); // <-- Add your package here
return packages;
}
// ...
}

Example (Kotlin -

code
MainApplication.kt
):

kotlin
// ... other imports
import com.your_app_name.MyNativePackage
class MainApplication : Application(), ReactApplication {
// ...
override fun getPackages(): List {
val packages = PackageList(this).packages
// Packages that include code in this app that is packaged into the library
// or that use native modules
packages.add(MyNativePackage()) // <-- Add your package here
return packages
}
// ...
}

Calling Native Methods from JavaScript

Once registered, you can access your native module and its methods from your React Native JavaScript code using

code
NativeModules
.

Example (JavaScript):

javascript
import React from 'react';
import { View, Button, NativeModules } from 'react-native';
const { MyNativeModule } = NativeModules;
const App = () => {
const handleShowMessage = () => {
MyNativeModule.showMessage('Hello from React Native!');
};
const handleAddNumbers = async () => {
try {
const sum = await MyNativeModule.addNumbers(5, 10);
console.log('Sum:', sum);
} catch (error) {
console.error('Error adding numbers:', error);
}
};
return (
);
};
export default App;

Data Types and Promises

The bridge supports various data types for arguments and return values, including strings, numbers, booleans, arrays, and objects. For asynchronous operations or methods that might take time, you should use

code
Promise
to handle the results and errors gracefully. The
code
@ReactMethod
annotation can accept a
code
Promise
as its last argument.

The React Native bridge acts as a serialization layer, converting JavaScript data types into a format that the native platform can understand, and vice-versa. This process involves converting data structures like arrays and objects into JSON or other serializable formats. When a method is called from JavaScript, the bridge sends a message containing the method name and its arguments. The native module executes the method, and if a Promise is used, the result or error is sent back to JavaScript through the bridge, deserialized, and then used to resolve or reject the JavaScript Promise.

📚

Text-based content

Library pages focus on text content

Best Practices and Considerations

  • Performance: Avoid passing large amounts of data across the bridge frequently. For heavy computations, consider offloading them to background threads on the native side.
  • Error Handling: Always implement robust error handling using Promises to catch and report issues from the native side.
  • Thread Safety: Be mindful of threading. Operations that modify UI elements must be performed on the main UI thread. Use
    code
    UiThreadUtil.runOnUiThread
    or Kotlin coroutines for this.
  • Module Naming: Use descriptive names for your modules and methods.
  • Constants: Expose constants from your native module using the
    code
    getConstants()
    method for static values.

When dealing with UI components, you'll create ViewManagers instead of NativeModules. ViewManagers are responsible for creating and managing native UI views.

Learning Resources

Native Modules - React Native Documentation(documentation)

The official React Native documentation on native modules, covering the basics of creating and using them.

Bridging to Native Code - React Native Documentation(documentation)

Detailed setup instructions for creating native modules on both Android and iOS platforms.

Writing Custom Native Modules in React Native (Android)(blog)

A practical guide with code examples for writing native modules specifically for Android.

React Native Native Modules: A Deep Dive(blog)

An in-depth explanation of the React Native bridge and how native modules work.

React Native Tutorial: Native Modules(video)

A video tutorial demonstrating the process of creating and using a native module in React Native.

Kotlin for Native Modules in React Native(blog)

An official blog post from React Native about using Kotlin for native module development.

Understanding the React Native Bridge(documentation)

Official documentation explaining the communication bridge between JavaScript and native code.

React Native Native UI Components(documentation)

Learn about creating native UI components (ViewManagers) which is related to native module development.

Advanced React Native: Native Modules and Bridging(tutorial)

A comprehensive course covering advanced topics including native module creation and bridging.

React Native Architecture: The Bridge(blog)

An article discussing the architecture of React Native, with a focus on the role of the bridge.