This is part 2 of our previous tutorial on integrating Native modules. Find the iOS version here.

Looking to integrate Native Modules into your Expo application? Book a free 30-minute consultation with one of our Expo specialists today.

Let's start by saying that there may be alternative ways of doing things than shown in this guide. We implore you to use this guide and as many other resources as you can find in order to form an understanding of native modules.

You may wish to consider using the Expo Modules API as it offers a more modern approach, but if, for some reason, that doesn't work out for you, this guide covers a traditional approach.

With that in mind, let's begin!

We're going to assume you've got Kotlin files for this project. Much of the knowledge below can also apply to Java-based projects, but note that this guide was built with Kotlin in mind.

Partner with Morrow to transform your Expo app into a high-performing, secure, and user-friendly solution.
Fill out our Expo audit form and take the first step towards app excellence.

To integrate a Native library, you'll need to do a few things:

  • Create a package file (.kt)
  • Create a way to initialize your package
  • Write a config plugin
  • Add app build gradle changes (if needed)
  • Add project build gradle changes (if needed)
  • Add source files
  • Add package to MainApplication

Create a package file

With Kotlin, your native code is contained in a namespace (package). Meanwhile, with JavaScript, you'd import * from './some/module,' pointing to an actual file by its path. With Kotlin, you'd instead import my.package.somemodule, which would point towards a file within the package.

In our example, we'll call this ./MySdk/MySdkPackage.kt. An example of a package might look like this:

Create a way to initialise your package

This step involves writing a module that will be used to set up lifecycle event listeners, as well as exporting modules that will be available to JS.

For this example, we will assume we've got 1 just module called AuthModule. You can add more as needed, but this is designed to be an introduction.

In this example, we're going to create a 'subpackage' of 'MySdk', and we'll call this ./MySdk/modules/InitModules.kt:

Now, let's create our AuthModule. This is just an example that checks whether the email and the password apple 1 are passed to it. You would need to write your own logic for this, but again, this example is designed as an introduction to native modules. Let’s call this file ./MySdk/modules/AuthModule.kt:

Read "Building an offline-first app with Expo, Supabase and WatermelonDB".

Create a config plugin

Expo offers a great way to add native changes through the use of config plugins. Rather than pre-building/ejecting and dealing with native code directly, we can remain in the managed workflow and use a config plugin to make changes instead. There's a great number of different things you might need to do, so we'll go through some common scenarios that can apply across a wide range of native integrations.

You can call your plugin anything you want, but I recommend keeping it near to your native source files - for example, ./MySdk/ You can use TS for config plugins, but you need to ensure you run tsc on them to build JS versions. For brevity and simplicity, we will use JS for the plugin.

Add app build gradle changes (if needed)

Some native packages require you to change your app-level build gradle file. This can take many forms, but some common ones are defining a specific SDK version and adding dependencies and implementation calls.

To do this, we'll need to use the withAppBuildGradle function provided by @expo/config-plugins package. Like most config plugin functions, it accepts a config, modifies it, and returns the modified version. It's a common approach to modularising your configuration plugin by creating separate functions for each step and then calling them all from a single function.

In this example, we're going to add some implementation and dependency changes using regular JS functions - for example, we will say that we want to use com.somenative.sdk version 12.4.0. The way you write this will differ for each individual native library - be sure to check the documentation:

Add project-level build gradle changes

Like the app-level gradle changes we made above, we sometimes need to make changes to the project-level build gradle file. Again, you might need to do this for many reasons, but a common use case is to change the Kotlin version. To make these changes, we'll use the withProjectBuildGradle function from @expo/config-plugins package:

Adding source files

So far, we've added some boilerplate to our project, which is used for build-time requirements, but how about adding the files we created to our project? For this, we're going to use a few node filesystem API functions. First, let's recap the files we have:

  • ./MySdk/modules/AuthModule.kt
  • ./MySdk/modules/InitModules.kt
  • ./MySdk/MySdkPackage.kt

We need to copy these files to specific locations. We're going to use a withAndroidManifest function from @expo/config-plugins in order to extract the project root:

Read "Exploring React Native Bottom Sheet: Implementation, Examples, and Setup".

Add package to MainApplication

In order for our native code to be recognised by the app, we need to add the package to MainApplication of our Android project:

Run your config plugin

The final step is to bring the config plugin together with a single function, and add it to your plugins in your expo config file. At the bottom of your config plugin file, write the following:

Finally, in your app.config.js (or app.json) file, add the following to your expo.plugins:

Calling the code from JavaScript

This next and final step is how to call this code from JS. This is perhaps the simplest part of the guide:


In this guide, we covered the basics of adding a native Android module in an Expo application using a config plugin all the way through to calling a function from JS. As with the iOS guide, if you experience any issues or errors, we recommend you Google them or use the support of the dev community, as there can be a number of causes and solutions.

Happy coding!

Looking to integrate Native Modules into your Expo application? Book a free 30-minute consultation with one of our Expo specialists today.

Want experts on your side to drive forward your project?
Need a second opinion on something?
We’re here to help!
Find out more
a photo of the Morrow team sat at a dinner table
More insights