Native module
First, let's create a new class in the android / app / src / main / java folder, the CustomModule class:
package com.awesomeproject;
import android.widget.Toast;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.util.Map;
import java.util.HashMap;
public class CustomModule extends ReactContextBaseJavaModule {
CustomModule (ReactApplicationContext context) {
super(context);
reactContext = context;
}
@Override
public String getName() {
return "CustomModule";
}
private static ReactApplicationContext context;
}
This class contains the required getName () method. It is by the name that this method will return that you can access the native module from the Javascript code (more on that later).
Note also that the class constructor takes the application context as an argument. The application context is needed when we want to interact with Android components.
Let's create a method of the CustomModule class that will be called from the Javascript code:
@ReactMethod
public void show(String message, int duration) {
Toast.makeText(context,"Hello world", Toast.LENGTH_LONG).show();
}
Note that in order for the method to be available in RN, you need to use the “@ReactMethod” decorator.
The Toast class is an Android component that can trigger the popup message from below using the show () method.
Linking the module with the Android application
After the module has been created, it must be placed in a package (“package”).
Let's create a package in the same namespace:
package com.awesomeproject;
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 CustomPackage 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 CustomModule(reactContext));
return modules;
}
}
The “ReactPackage” interface contains two required methods: “createNativeModules” and “createViewManagers”. View manager in RN code is a component. Our module will use functions and is not an Android ui component and therefore is placed in the “createNativeModules” method.
Note: one package can contain several modules.
Next, the package must be associated with the Android application as follows:
//MainApplication.java
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new CustomPackage());
return packages;
}
Using a module in Javascript code
Now let's try to call the “show ()” method in the RN application:
const App = () => {
NativeModules.ToastExample.show();
return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView>
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={styles.scrollView}>
<Text>text</Text>
</ScrollView>
</SafeAreaView>
</>
);
};
Result:
Data exchange between RN and Android apps
Now, let's exchange data between applications. Let's create two new methods in the CustomModule class to find the sum:
@ReactMethod
public void sum(int a, int b, Promise res) {
try {
res.resolve(a+b);
} catch (IllegalViewOperationException e) {
res.resolve(e);
}
}
@ReactMethod
public void sum(float a, float b, Callback success, Callback fail) {
try {
success.invoke((a+b));
} catch (IllegalViewOperationException e) {
fail.invoke(e.getMessage());
}
}
The variables "a" and "b" will come from Javascript code and you need to remember about the correspondence of data types between Java and JS:
Note: since the Number type corresponds to several types from Java at once, we use an overload by creating two methods with the same name, but different types of parameters.
To return data to JS code, the com.facebook.react.bridge module contains the Promise and CallBack types.
Now let's use the method in Js:
const showRes = async () => {
const res = NativeModules.SendDataToRN.sum(400, 250);
alert(res);
};
const App = () => {
React.useEffect(() => {
showRes();
}, [])
return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView>
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={styles.scrollView}>
<Text>text</Text>
</ScrollView>
</SafeAreaView>
</>
);
};
Result:
Conclusion
The materials of the article can be used in all situations when the api for rn has not yet been written. As you can see from the examples, data exchange between applications is a fairly simple operation that does not require deep knowledge of Java programming.