Skip to content
Titanium SDK
Guidesv13

You are reading the v13 guides. Titanium SDK v14 is current. See this page in v14.

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 11, 2026