Techletter #37 | July 5, 2023
Writing a native module can actually give a better performance to your app. It’s not always important, but sometimes when you are implementing something which is not available within React native ecosystem you need the help of a native language like Java.
Believe me! It’s been years since I have written anything in Java. I have been using only JavaScript and hope will be continuing with it. But, writing Java can be necessary. For example, I faced a lot of problems while searching for a React native library that can work efficiently with the call logs. You will find a few of them, but there comes a time when they aren’t solving all the problems related to calls. So, you need to write your own module for achieving the task that you want.
Here, I will be showing how you can implement your module and call the method present in the Java module in the React native file.
android/app/src/main/java/com/your_package/ReactCustomModule.java
package com.YOUR_PACKAGE_NAME;
import android.annotation.SuppressLint;
import android.provider.Settings;
import androidx.annotation.NonNull;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactMethod;
public class ReactCustomModule extends ReactContextBaseJavaModule {
private static ReactApplicationContext reactContext;
ReactOneCustomMethod(ReactApplicationContext context) {
super(context);
reactContext = context;
}
@NonNull
@Override
public String getName() {
return "ReactCustomModule";
}
@ReactMethod
public void getSimpleName(Promise response) {
try {
response.resolve("Example Package");
} catch (Exception e) {
response.reject("Error", e);
}
}
}
All Java/Kotlin native modules in Android need to implement the getName()
method. This method returns a string, which represents the name of the native module. The native module can then be accessed in JavaScript using its name. Once you write the above class, next you need to register the module that you have written.
android/app/src/main/java/com/your_package/ReactCustomPackage.java
package com.YOUR_PACKAGE_NAME;
import androidx.annotation.NonNull;
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 ReactCustomPackage implements ReactPackage {
@NonNull
@Override
public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new ReactCustomModule(reactContext));
return modules;
}
@NonNull
@Override
public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
Now go to the MainApplication.java
in the same folder
package com.YOUR_PACKAGE_NAME;
// Not Necessary
import com.YOUR_PACKAGE_NAME.ReactCustomPackage;
import android.app.Application;
import android.content.res.Configuration;
import androidx.annotation.NonNull;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactNativeHost;
import com.facebook.soloader.SoLoader;
import expo.modules.ApplicationLifecycleDispatcher;
import expo.modules.ReactNativeHostWrapper;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
new ReactNativeHostWrapper(this, new DefaultReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
packages.add(new ReactCustomPackage());
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
@Override
protected boolean isNewArchEnabled() {
return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
}
@Override
protected Boolean isHermesEnabled() {
return BuildConfig.IS_HERMES_ENABLED;
}
});
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
// If you opted-in for the New Architecture, we load the native entry point for this app.
DefaultNewArchitectureEntryPoint.load();
}
ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
ApplicationLifecycleDispatcher.onApplicationCreate(this);
}
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig);
}
}
Now you can use the Java module that you have written directly in your React native file
import { NativeModules } from "react-native";
const {ReactCustomModule} = NativeModules;
export const nativeMethod = async () => {
try {
const data = await ReactCustomModule.getSimpleName();
// Data returned from the java module to make use of it here in react code
console.log({ data });
} catch (error) {
console.log(error);
}
}
Resources: