From Zero to App

Use NFC tags in your Titanium SDK app

Note: This tutorial is currently for Android only. iOS support will be added in a future version.

This tutorial shows you how to read NFC tags (specifically NTAG215 and NTAG213 tags) in your Titanium Android app using the ti.nfc module.

1. Download the ti.nfc Module

Download the ti.nfc module from https://github.com/tidev/ti.nfc and place the zip file in the app root folder.

2. Add the Module to tiapp.xml

Open your tiapp.xml file and add the module inside the <modules> node:

<modules>
    <module>ti.nfc</module>
</modules>

This tells Titanium to include the ti.nfc module in your app.

3. Add NFC Intent Filters

Add the following inside the <application> node in tiapp.xml:

<activity android:name=".YourAppActivity" android:theme="@style/Theme.Custom.Splash" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation" android:exported="true">
    <intent-filter>
        <action android:name="android.nfc.action.TECH_DISCOVERED"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>

    <intent-filter>
        <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>

    <intent-filter>
        <action android:name="android.nfc.action.TAG_DISCOVERED"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

Replace YourAppActivity with your app's main activity name. You can find this by building the project and checking the log when the app starts. It will show something like Starting app: com.your.app/.YourappActivity. Use the name after the final slash (for example, .YourappActivity).

Why Add Intent Filters?

Intent filters tell Android that your app wants to receive NFC events. Android has three types of NFC discovery:

  1. TECH_DISCOVERED - Used for tags that match specific technology (like NfcA, NfcF, Ndef). This gives you access to raw tag data.
  2. NDEF_DISCOVERED - Used for NDEF formatted tags. NDEF is a standard format that stores data in records. This filter includes a mimeType to specify what kind of data you accept.
  3. TAG_DISCOVERED - Used as a fallback for any NFC tag. This catches tags that do not match the other filters.

By adding all three intent filters, your app can receive any type of NFC tag. Without these filters, Android will not deliver NFC tag events to your app.

4. Create the App

Create an Alloy project with a blank app. You do not need any windows or views because we will use console.log to read the tag data.

Make sure your app has at least one controller (for example, index.js) where you can add the NFC code.

5. Add the NFC Code

Add the following code to your main controller (for example, app/controllers/index.js):

const nfc = require("ti.nfc");

function setupNfc() {
    let dispatchFilter = nfc.createNfcForegroundDispatchFilter({
        intentFilters: [{
                action: nfc.ACTION_NDEF_DISCOVERED,
                mimeType: "*/*",
            },
            {
                action: nfc.ACTION_NDEF_DISCOVERED,
                scheme: "http",
            },
        ],
        techLists: [
            ["android.nfc.tech.NfcF"],
            ["android.nfc.tech.Ndef"],
            ["android.nfc.tech.MifareClassic"],
            ["android.nfc.tech.NfcA"],
        ],
    });

    nfcAdapter = nfc.createNfcAdapter({
        onNdefDiscovered: handleDiscovery,
        onTagDiscovered: handleDiscovery,
        onTechDiscovered: handleDiscovery,
    });

    nfcAdapter.addEventListener("didDetectTags", function() {});

    if (!nfcAdapter.isEnabled()) {
        return;
    }

    var act = Ti.Android.currentActivity;
    act.addEventListener("newintent", function(e) {
        nfcAdapter.onNewIntent(e.intent);
    });

    act.addEventListener("resume", function() {
        nfcAdapter.enableForegroundDispatch(dispatchFilter);
    });
    act.addEventListener("pause", function() {
        nfcAdapter.disableForegroundDispatch();
    });
}

function handleDiscovery(e) {
    if (e.messages && e.messages.length > 0 && e.messages[0].records) {
        let nfcText = e.messages[0].records[0].text;
        console.log(nfcText);
    }
}

setupNfc();

Code Explanation

Here is what each part does:

require("ti.nfc") - Loads the NFC module.

createNfcForegroundDispatchFilter - Creates a filter that tells Android which tags your app wants to receive. The intentFilters section specifies NDEF discovery. The techLists section lists the tag technologies your app supports (NfcF, Ndef, MifareClassic, NfcA).

createNfcAdapter - Creates the NFC adapter with callback functions for different tag types. The callbacks handle when NDEF tags, regular tags, or tech-discovered tags are detected.

onNdefDiscovered, onTagDiscovered, onTechDiscovered - These are callback properties. When a tag is detected, the adapter calls these functions automatically.

nfcAdapter.isEnabled() - Checks if NFC is enabled on the device. If NFC is not enabled, the function returns and the app does not set up NFC.

newintent event - Android fires this event when a tag is discovered while the app is running. The code calls onNewIntent to process the tag.

resume event - When the app becomes active, enableForegroundDispatch registers your app to receive NFC events. This is called foreground dispatch and ensures your app gets the tag even if other apps also listen for NFC.

pause event - When the app goes to the background, disableForegroundDispatch stops receiving NFC events. This allows other apps to receive tags.

handleDiscovery - This function processes the discovered tag. It reads the first record from the first message and logs the text. The e.messages array contains the tag data. Each message has a records array with the actual data.

console.log outputs the tag text to the console. You can see this in the console or debug log output.

Testing the App

Note: You need to have some text written on the NFC tag before you can read it. If your tag is empty, use another app like NFC Tools to write a text block to the tag first.

Build and run the app on an Android device using:

ti build -p android -T device

When you tap an NFC tag to the phone, the console log shows the tag text.

Make sure your Android device has NFC enabled in settings.

Summary

To summarize, you:

  1. Downloaded the ti.nfc module
  2. Added the module to tiapp.xml
  3. Added intent filters to receive NFC events
  4. Created a blank app
  5. Added NFC code with foreground dispatch and tag discovery handling

The app now reads NFC tags and outputs the tag text to the console.

More to come soon

  • iOS NFC support
  • Writing tags
  • Setting a password on tags