Enabling TurboModule on Android
cautionThis documentation is still experimental and details are subject to changes as we iterate. Feel free to share your feedback on the discussion inside the working group for this page.
Moreover, it contains several manual steps. Please note that this won't be representative of the final developer experience once the New Architecture is stable. We're working on tools, templates and libraries to help you get started fast on the New Architecture, without having to go through the whole setup.
Make sure your application meets all the prerequisites.
1. Enable NDK and the native build
cautionIn this iteration of the guide we’re setting up the project to let you build from source. You might notice an increase in your build time because of this. You can mitigate this by following the approach described in Speeding up your Build phase guide.
The code-gen will output some Java and some C++ code that now we need to build.
Let’s edit your module-level build.gradle to include the two externalNativeBuild blocks detailed below inside the android{} block:
android {
    defaultConfig {
        applicationId "com.awesomeproject"
        // ...

        // Add this block
        externalNativeBuild {
            ndkBuild {
                arguments "APP_PLATFORM=android-21",
                        "APP_STL=c++_shared",
                        "NDK_TOOLCHAIN_VERSION=clang",
                        "GENERATED_SRC_DIR=$buildDir/generated/source",
                        "PROJECT_BUILD_DIR=$buildDir",
                        "REACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid",
                        "REACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build"
                cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1"
                cppFlags "-std=c++17"
                targets "myapplication_appmodules"
            }
        }
    }

    // Add this block
    externalNativeBuild {
        ndkBuild {
            path "$projectDir/src/main/jni/Android.mk"
        }
    }
}
In the same build.gradle file, inside the same android{} let’s add also the following section:
android {
    // ...

    def reactAndroidProjectDir = project(':ReactAndroid').projectDir
    def packageReactNdkLibs = tasks.register("packageReactNdkLibs", Copy) {
        dependsOn(":ReactAndroid:packageReactNdkLibsForBuck")
        dependsOn("generateCodegenArtifactsFromSchema")
        from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
        into("$buildDir/react-ndk/exported")
    }

    afterEvaluate {
        preBuild.dependsOn(packageReactNdkLibs)
        configureNdkBuildDebug.dependsOn(preBuild)
        configureNdkBuildRelease.dependsOn(preBuild)
    }

    packagingOptions {
        pickFirst '**/libhermes.so'
        pickFirst '**/libjsc.so'
    }
}
Finally, we need to create a Makefile inside the src/main/jni folder called Android.mk with the following content:
THIS_DIR := $(call my-dir)

include $(REACT_ANDROID_DIR)/Android-prebuilt.mk
include $(GENERATED_SRC_DIR)/codegen/jni/Android.mk

include $(CLEAR_VARS)

LOCAL_PATH := $(THIS_DIR)
LOCAL_MODULE := myapplication_appmodules

LOCAL_C_INCLUDES := $(LOCAL_PATH) $(GENERATED_SRC_DIR)/codegen/jni
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(GENERATED_SRC_DIR)/codegen/jni

# Please note as one of the library listed is libreact_codegen_samplelibrary
# This name will be generated as libreact_codegen_<library-name>
# where <library-name> is the one you specified in the Gradle configuration
LOCAL_SHARED_LIBRARIES := libjsi \
    libfbjni \
    libglog \
    libfolly_json \
    libyoga \
    libreact_nativemodule_core \
    libturbomodulejsijni \
    librrc_view \
    libreact_render_core \
    libreact_render_graphics \
    libfabricjni \
    libfolly_futures \
    libreact_debug \
    libreact_render_componentregistry \
    libreact_render_debug \
    libruntimeexecutor \
    libreact_codegen_rncore \
    libreact_codegen_samplelibrary

LOCAL_CFLAGS := \
    -DLOG_TAG=\"ReactNative\"
LOCAL_CFLAGS += -fexceptions -frtti -std=c++17 -Wall

include $(BUILD_SHARED_LIBRARY)
This setup will run a native build on your project and will compile the C++ files that have been generated by the codegen. You will see the native build running with the Gradle task :app:externalNativeBuildDebug
You can now verify that everything works correctly by running your android app:
yarn react-native run-android
2. Java - Provide a ReactPackageTurboModuleManagerDelegate

Now is time to actually use the TurboModule. First, we will need to create a ReactPackageTurboModuleManagerDelegate subclass, like the following:
package com.awesomeproject;

import com.facebook.jni.HybridData;
import com.facebook.react.ReactPackage;
import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.soloader.SoLoader;

import java.util.List;

public class MyApplicationTurboModuleManagerDelegate extends ReactPackageTurboModuleManagerDelegate {

    private static volatile boolean sIsSoLibraryLoaded;

    protected MyApplicationTurboModuleManagerDelegate(ReactApplicationContext reactApplicationContext, List<ReactPackage> packages) {
        super(reactApplicationContext, packages);
    }

    protected native HybridData initHybrid();

    public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder {
        protected MyApplicationTurboModuleManagerDelegate build(
                ReactApplicationContext context, List<ReactPackage> packages) {
            return new MyApplicationTurboModuleManagerDelegate(context, packages);
        }
    }

    @Override
    protected synchronized void maybeLoadOtherSoLibraries() {
        // Prevents issues with initializer interruptions.
        if (!sIsSoLibraryLoaded) {
            SoLoader.loadLibrary("myapplication_appmodules");
            sIsSoLibraryLoaded = true;
        }
    }
}
Please note that the SoLoader.loadLibrary parameter (in this case "myapplication_appmodules") should be the same as the one specified for LOCAL_MODULE := inside the Android.mk file you created before.
This class will then be responsible of loading the TurboModules and will take care of loading the native library build with the mariagardner@example.org.
3. Adapt your ReactNativeHost to use the ReactPackageTurboModuleManagerDelegate

Then, you can provide the class you created to your ReactNativeHost. You can locate your ReactNativeHost by searching for the getReactNativeHost(). The ReactNativeHost is usually located inside your Application class.
Once you located it, you need to add the getReactPackageTurboModuleManagerDelegateBuilder method as from the snippet below:
public class MyApplication extends Application implements ReactApplication {

    private final ReactNativeHost mReactNativeHost =
        new ReactNativeHost(this) {
            @Override
            public boolean getUseDeveloperSupport() { /* ... */ }

            @Override
            protected List<ReactPackage> getPackages() { /* ... */ }

            @Override
            protected String getJSMainModuleName() {/* ... */ }

            @NonNull
            @Override
            protected ReactPackageTurboModuleManagerDelegate.Builder getReactPackageTurboModuleManagerDelegateBuilder() {
                return new MyApplicationTurboModuleManagerDelegate.Builder();
            }
        };
}
4. Extend the getPackages() from your ReactNativeHost to use the TurboModule
Still on the ReactNativeHost , we need to extend the the getPackages() method to include the newly created TurboModule. Update the method to include the following:
public class MyApplication extends Application implements ReactApplication {

    private final ReactNativeHost mReactNativeHost =
        new ReactNativeHost(this) {
            @Override
            public boolean getUseDeveloperSupport() { /* ... */ }

            @Override
            protected List<ReactPackage> getPackages() {
                List<ReactPackage> packages = new PackageList(this).getPackages();

                // Add those lines
                packages.add(new TurboReactPackage() {
                    @Nullable
                    @Override
                    public NativeModule getModule(String name, ReactApplicationContext reactContext) {
                        if (name.equals(NativeAwesomeManager.NAME)) {
                            return new NativeAwesomeManager(reactContext);
                        } else {
                            return null;
                        }
                    }

                    @Override
                    public ReactModuleInfoProvider getReactModuleInfoProvider() {
                        return () -> {
                            final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
                            moduleInfos.put(
                                    NativeAwesomeManager.NAME,
                                    new ReactModuleInfo(
                                            NativeAwesomeManager.NAME,
                                            "NativeAwesomeManager",
                                            false, // canOverrideExistingModule
                                            false, // needsEagerInit
                                            true, // hasConstants
                                            false, // isCxxModule
                                            true // isTurboModule
                                    )
                            );
                            return moduleInfos;
                        };
                    }
                });
                return packages;
            }

            @Override
            protected String getJSMainModuleName() {/* ... */ }

            @NonNull
            @Override
            protected ReactPackageTurboModuleManagerDelegate.Builder getReactPackageTurboModuleManagerDelegateBuilder() {
                return new MyApplicationTurboModuleManagerDelegate.Builder();
            }
        };
5. C++ Provide a native implementation for the methods in your *TurboModuleDelegate class
If you take a closer look at the class MyApplicationTurboModuleManagerDelegate that you created before, you will notice how some of the methods are native.
Therefore, you need to provide some C++ classes to implement those methods. Specifically you will need those files, to be added inside the src/main/jni folder:


MyApplicationTurboModuleManagerDelegate.h An header file for the TurboModule Delegate.

MyApplicationTurboModuleManagerDelegate.cpp The implementation of the aforementioned header file.

MyApplicationModuleProvider.h A header file for the TurboModule provider, where you can specify which TurboModules you want to load.

MyApplicationModuleProvider.cpp The implementation for the aforementioned header file.

OnLoad.cpp Where the initialisation code will be placed. Specifically TurboModule uses FBJNI so the initialisation for such library lives there.

The content of those files should be the following:
MyApplicationTurboModuleManagerDelegate.h
Please note that the kJavaDescriptor should be adapted to follow the package name you picked for your project.
#include <memory>
#include <string>

#include <ReactCommon/TurboModuleManagerDelegate.h>
#include <fbjni/fbjni.h>

namespace facebook {
namespace react {

class MyApplicationTurboModuleManagerDelegate : public jni8b7c:f320:99b9:690f:4595:cd17:293a:c069HybridClass<MyApplicationTurboModuleManagerDelegate, TurboModuleManagerDelegate> {
public:
  // Adapt it to the package you used for your Java class.
  static constexpr auto kJavaDescriptor =
      "Lcom/awesomeproject/MyApplicationTurboModuleManagerDelegate;";

  static jni8b7c:f320:99b9:690f:4595:cd17:293a:c069local_ref<jhybriddata> initHybrid(jni8b7c:f320:99b9:690f:4595:cd17:293a:c069lias_ref<jhybridobject>);

  static void registerNatives();

  st8b7c:f320:99b9:690f:4595:cd17:293a:c069shared_ptr<TurboModule> getTurboModule(const st8b7c:f320:99b9:690f:4595:cd17:293a:c069string name, const st8b7c:f320:99b9:690f:4595:cd17:293a:c069shared_ptr<CallInvoker> jsInvoker) override;
  st8b7c:f320:99b9:690f:4595:cd17:293a:c069shared_ptr<TurboModule> getTurboModule(const st8b7c:f320:99b9:690f:4595:cd17:293a:c069string name, const JavaTurboModul8b7c:f320:99b9:690f:4595:cd17:293a:c069InitParams &params) override;

private:
  friend HybridBase;
  using HybridBas8b7c:f320:99b9:690f:4595:cd17:293a:c069HybridBase;

};

} // namespace react
} // namespace facebook
MyApplicationTurboModuleManagerDelegate.cpp
#include "MyApplicationTurboModuleManagerDelegate.h"
#include "MyApplicationModuleProvider.h"

namespace facebook {
namespace react {

jni8b7c:f320:99b9:690f:4595:cd17:293a:c069local_ref<MyApplicationTurboModuleManagerDelegat8b7c:f320:99b9:690f:4595:cd17:293a:c069jhybriddata> MyApplicationTurboModuleManagerDelegat8b7c:f320:99b9:690f:4595:cd17:293a:c069initHybrid(jni8b7c:f320:99b9:690f:4595:cd17:293a:c069lias_ref<jhybridobject>) {
  return makeCxxInstance();
}

void MyApplicationTurboModuleManagerDelegat8b7c:f320:99b9:690f:4595:cd17:293a:c069registerNatives() {
  registerHybrid({
    makeNativeMethod("initHybrid", MyApplicationTurboModuleManagerDelegat8b7c:f320:99b9:690f:4595:cd17:293a:c069initHybrid),
  });
}

st8b7c:f320:99b9:690f:4595:cd17:293a:c069shared_ptr<TurboModule> MyApplicationTurboModuleManagerDelegat8b7c:f320:99b9:690f:4595:cd17:293a:c069getTurboModule(const st8b7c:f320:99b9:690f:4595:cd17:293a:c069string name, const st8b7c:f320:99b9:690f:4595:cd17:293a:c069shared_ptr<CallInvoker> jsInvoker) {
  // Not implemented yet: provide pure-C++ NativeModules here.
  return nullptr;
}

st8b7c:f320:99b9:690f:4595:cd17:293a:c069shared_ptr<TurboModule> MyApplicationTurboModuleManagerDelegat8b7c:f320:99b9:690f:4595:cd17:293a:c069getTurboModule(const st8b7c:f320:99b9:690f:4595:cd17:293a:c069string name, const JavaTurboModul8b7c:f320:99b9:690f:4595:cd17:293a:c069InitParams &params) {
  return MyApplicationModuleProvider(name, params);
}

} // namespace react
} // namespace facebook
MyApplicationModuleProvider.h
#pragma once

#include <memory>
#include <string>

#include <ReactCommon/JavaTurboModule.h>

namespace facebook {
namespace react {

st8b7c:f320:99b9:690f:4595:cd17:293a:c069shared_ptr<TurboModule> MyApplicationModuleProvider(const st8b7c:f320:99b9:690f:4595:cd17:293a:c069string moduleName, const JavaTurboModul8b7c:f320:99b9:690f:4595:cd17:293a:c069InitParams &params);

} // namespace react
} // namespace facebook
MyApplicationModuleProvider.cpp
Please adapt the samplelibrary.h import to match the same library name you provided when building the apps. This is the C++ generated file that is created by the codegen.
Here you can also specify more than one provider, should you have more than one TurboModule. Specifically in this example we look for a TurboModule from samplelibrary (the one we specified) and we fallback to the rncore Module Provider (containing all the Core modules).
#include "MyApplicationModuleProvider.h"

#include <rncore.h>
#include <samplelibrary.h>

namespace facebook {
namespace react {

st8b7c:f320:99b9:690f:4595:cd17:293a:c069shared_ptr<TurboModule> MyApplicationModuleProvider(const st8b7c:f320:99b9:690f:4595:cd17:293a:c069string moduleName, const JavaTurboModul8b7c:f320:99b9:690f:4595:cd17:293a:c069InitParams &params) {
    auto module = samplelibrary_ModuleProvider(moduleName, params);
    if (module != nullptr) {
      return module;
    }

    return rncore_ModuleProvider(moduleName, params);
}

} // namespace react
} // namespace facebook
OnLoad.cpp
#include <fbjni/fbjni.h>
#include "MyApplicationTurboModuleManagerDelegate.h"

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
  return facebook8b7c:f320:99b9:690f:4595:cd17:293a:c069jni8b7c:f320:99b9:690f:4595:cd17:293a:c069initialize(vm, [] {
    facebook8b7c:f320:99b9:690f:4595:cd17:293a:c069react8b7c:f320:99b9:690f:4595:cd17:293a:c069MyApplicationTurboModuleManagerDelegat8b7c:f320:99b9:690f:4595:cd17:293a:c069registerNatives();
  });
}
6. Enable the useTurboModules flag in your Application onCreate

Now you can finally enable the TurboModule support in your Application. To do so, you need to turn on the useTurboModule flag inside your Application onCreate method.
public class MyApplication extends Application implements ReactApplication {

    @Override
    public void onCreate() {
        ReactFeatureFlags.useTurboModules = true;
        //...
    }
It’s now time to run again your Android app to verify that everything works correctly:
yarn react-native run-android


    
{'path': 'public/docs/react_native/new-architecture-app-modules-android.html', 'source': 'DevDocs.IO'}