Skip to content
Titanium SDK

Native modules

Written for Titanium SDK 13.4.0 and later

A native module wraps platform code and exposes it to JavaScript. Write one when the SDK has no API for something the platform does, or when you need a native library that has no JavaScript equivalent.

Before you do, check the modules directory - somebody may already have. And check Hyperloop, which reaches native APIs directly without a module at all.

Create one

ti create --type module --id com.example.thing --name thing --platforms android --workspace-dir .

--platforms takes android, ios or both, and each gets its own directory with its own build.

thing/
  android/
    manifest              id, version, and what it needs
    timodule.xml          module-level tiapp settings
    build.gradle
    src/com/example/thing/
      ThingModule.java    the module object
      ExampleProxy.java   a proxy
    lib/                  third-party jars
    platform/             files copied into the app build
    assets/
  documentation/index.md
  example/app.js          runs against the built module
  LICENSE

The manifest

version: 1.0.0
apiversion: 4
architectures: arm64-v8a armeabi-v7a x86 x86_64
name: thing
moduleid: com.example.thing
guid: 1bf6ca03-c384-44f1-8bdc-f06454872771
platform: android
minsdk: 13.4.1.GA

minsdk is the oldest Titanium SDK the module supports, and the build refuses when a project's SDK is older. apiversion is the module API generation - 4 on Android, 2 on iOS for 13.4.

Bump version on every release. It is what a project pins against.

What the code looks like

Titanium's Android bridge is Kroll, driven by annotations:

@Kroll.module(name = "Thing", id = "com.example.thing")
public class ThingModule extends KrollModule {

    @Kroll.method
    public String greet(String name) {
        return "Hello " + name;
    }

    @Kroll.constant
    public static final String VERSION = "1.0.0";
}

@Kroll.method exposes a method, @Kroll.getProperty and @Kroll.setProperty make a property, and @Kroll.constant makes a constant. A KrollProxy subclass becomes an object your JavaScript can create.

On iOS the equivalent is an Objective-C class extending TiModule, where methods are exposed by naming convention rather than annotation.

Build and test

Build from the module directory:

ti build --platform android --build-only

That produces a distributable zip. example/app.js is a real app the module build runs, which is the fastest way to exercise what you just wrote.

Install it into a project by unzipping it there - see using modules for the layout and for declaring it in tiapp.xml.

Things that catch people

apiversion and minsdk are promises. A module built against an old SDK may link against internals that moved. When a project fails at link time with a message naming nothing, a stale module is the first suspect.

Architectures cost size. Every one in architectures is compiled and shipped. Drop the ones you do not need.

The bridge is the slow part. A call from JavaScript into native crosses Kroll, and a loop that crosses per iteration is where the time goes. Pass a collection and return a collection rather than calling per item.

Threading is yours to get right. A long native call blocks the JavaScript thread. Do the work on a background thread and call back.

Next

Hyperloop does much of this without a module.

Edit this page on GitHubLast updated Nov 9, 2026