Expo Modules in Kotlin

Writing an Expo Module in Kotlin

create-expo-module scaffolds a local module, one that lives in the app's modules/ folder rather than in its own npm 2,036 package. Its flags answer the prompts, so the command runs unattended:

Scaffolding a local Expo ModuleShell
npx create-expo-module@latest booknest-device --local --name BookNestDevice \
  --package expo.modules.booknestdevice -p android apple \
  --features Constant Function AsyncFunction --description "Device facts for BookNest"
Output
The local module will be created in modules/booknest-device directory.
✔ Downloaded module template from npm registry.
✔ Created the module from template files
✅ Successfully created Expo module in modules/booknest-device

It wrote Kotlin and Swift modules, a Gradle 19,597 file and expo-module.config.json, which names the classes to autolink. Replacing the template's sample functions with BookNest's gives:

modules/booknest-device/android/.../BookNestDeviceModule.kt (excerpt)Kotlin
class BookNestDeviceModule : Module() {
  private val context: Context
    get() = appContext.reactContext ?: throw Exceptions.ReactContextLost()
  override fun definition() = ModuleDefinition {
    Name("BookNestDevice")
    Constant("sdkInt") { Build.VERSION.SDK_INT }           // computed once
    Function("freeSpaceMb") {                               // synchronous
      StatFs(context.filesDir.path).availableBytes / (1024 * 1024)
    }
    AsyncFunction("isPowerSaveModeAsync") {                 // runs off the JS thread
      context.getSystemService(PowerManager::class.java).isPowerSaveMode
    }

The JavaScript side, src/BookNestDeviceModule.ts, declares a class with sdkInt: number, freeSpaceMb(): number and isPowerSaveModeAsync(): Promise<boolean>, and exports requireNativeModule<BookNestDeviceModule>('BookNestDevice'), a lookup by the Name() above. There is no Codegen, so that declaration is a promise you keep by hand. After a rebuild, the demo screen logged:

Output of 197
 LOG  API 36, 8819 MB free
 LOG  power saver: false

No MainApplication.kt edit and no plugin: autolinking found expo-module.config.json in modules/.