Chapter 11 of 12 ~20 min read

Writing Custom Native Modules (Kotlin & Swift)

Expo Modules API in Kotlin / Swift vs classical CordovaPlugin.execute() Java methods.


1. Custom Native Code: Cordova vs Expo Module

In Cordova, extending native functionality required inheriting from CordovaPlugin and parsing JSON action strings inside a monolithic execute() switch statement.

In modern React Native with the Expo Module API, you write concise, declarative Kotlin (Android) and Swift (iOS) with compile-time type safety:

Legacy Cordova Java Plugin
public class MyPlugin extends CordovaPlugin {
    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
        if ("greet".equals(action)) {
            try {
                String name = args.getString(0);
                callbackContext.success("Hello " + name);
                return true;
            } catch (JSONException e) {
                callbackContext.error("Bad args");
                return false;
            }
        }
        return false;
    }
}
Modern Expo Module (Kotlin)
import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition

class MyModule : Module() {
  override fun definition() = ModuleDefinition {
    Name("MyModule")

    // Automatic type marshaling & Promise resolution
    AsyncFunction("greet") { name: String ->
      "Hello $name from Kotlin!"
    }

    Function("getBatteryLevel") {
      // Direct return without callback boilerplate
      85
    }
  }
}