Writing a native module for React Native using Kotlin
July 29, 2020
Open the project-level build.gradle
and make the following changes.
Include the Kotlin version:
buildscript {
ext.kotlin_version = '1.3.31'
repositories {
google()
jcenter()
add the following classpath in the dependencies to include the Kotlin Gradle plugin in same file of project-level build.gradle
dependencies {
classpath 'com.android.tools.build:gradle:3.4.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
Application modules build.gradle (app)
Now that we upgraded the build tool version, its time to include Kotlin to the project
Open build.gradle (app folder)
and we have to make a few changes.
At the top of the file, include the following Kotlin plugins.
apply plugin: 'com.android.application' // already exists
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
In the dependencies section add the following dependency in same file of build.gradle (app folder)
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
After you have followed all this steps, now you can test your app.
in the project folder and run the React Native app.Don’t just hot-reload the app.
Run in the terminal:
npx react-native run-android
We can now bridge Kotlin in React Native
Step 1) - Create folder in where MainActivity.java file exist
step 2)- Create a file with kotlin file like this
Main.kt
package com.bitfrit.ReactPackage
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
class Main : ReactPackage {
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
return emptyList()
}
override fun createNativeModules(
reactContext: ReactApplicationContext): List<NativeModule> {
val modules = ArrayList<NativeModule>()
modules.add(CustomNative(reactContext))
return modules
}
}
Step 3- Create a class with any name here i created
ToastModule.kt
package com.bitfrit.ReactPackage
import android.content.Context
import android.os.Build
import android.util.Log
import android.widget.Toast
import com.facebook.react.bridge.Callback
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import java.util.*
class CustomNative(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
override fun getName(): String {
return "CustomNative"
}
override fun getConstants(): Map<String, Any>? {
val constants = HashMap<String, Any>()
constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT)
constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG)
return constants
}
@ReactMethod
fun Toastshow(message: String, duration: Int) {
Toast.makeText(reactApplicationContext, message, duration).show()
}
companion object {
private val DURATION_SHORT_KEY = "SHORT"
private val DURATION_LONG_KEY = "LONG"
}
}
Step 4) - Register Main.kt with Mainapplication.java
package com.bitfrit;
import android.app.Application;
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.reactnativecommunity.asyncstorage.AsyncStoragePackage;
import com.reactnativecommunity.netinfo.NetInfoPackage;
import com.oblador.vectoricons.VectorIconsPackage;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;
import com.bitfrit.ReactPackage.Main;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
new ReactNativeHost(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 Main());
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}
/**
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
*
* @param context
* @param reactInstanceManager
*/
private static void initializeFlipper(
Context context, ReactInstanceManager reactInstanceManager) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("com.bitfrit.ReactNativeFlipper");
aClass
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
.invoke(null, context, reactInstanceManager);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
Now we will use Andorid Toast as React Native Module
App.js
import { View,Text,ScrollView,NativeModules} from 'react-native';
.
.
.
const {CustomNative}=NativeModules;
const App = () => {
const onButtonPress = () => {
CustomNative.Toastshow(msg, CustomNative.SHORT);
}
return <View style={{backgroundColor:Colors.black}}>
<Text onPress={()=>onButtonPress()} style={{fontSize:25}}>onButtonPress</Text>
</View>
}
export default App;