FusionNFC: Implement NFC for Cross-Platform Swift Mobile Apps

FusionNFC: Implement NFC for Cross-Platform Swift Mobile Apps

Learn how to read & write NFC tags, by writing minimal swift code for Android & iOS!

Introduction

Hi everyone 🙋🏻‍♂️! My name is Vedant, and it is time to explore another Fusion library! We use NFC tags for various daily use cases like making payments, sending SMS and virtual business cards, etc. If we want to develop an app for both platforms iOS and Android which will use the NFC feature then it seems almost impossible to use the same codebase at all without bothering about the configuration of each platform. Android and iOS NFC implementations differ a lot in terms of configuration so we will require to take care of individual edge cases.

FusionNFC is part of the Fusion project and provides you with one Swift API for developing NFC applications for both Android and iOS. So It becomes easy to use core NFC features seamlessly without bothering about the edge cases for Android. In this article, we will read and write an NFC tag by building a cross-platform native Swift app using SCADE that uses just a few lines of Swift code✌🏼.

How does FusionNFC work

FusionNFC wraps the NFC-relevant Android NDK APIs and iOS APIs and presents the NFC functionality as one easy-to-use API. FusionNFC is designed so that you don’t have to deal with iOS and Android os specific issues.

RFID & NFC

Radio Frequency Identification (RFID) is the general term for exchanging data using radio frequency, both actively or passively, using a variety of radio frequencies that allow communication across different distances. More specific to mobile apps, NFC stands for Near Field Communication and is a wireless technology that allows the exchange of data between your Android or iOS phone and the RFID device/chip using radio frequencies across short distances, usually centimeters.

Prerequisite

If you haven’t installed the SCADE IDE, download the SCADE IDE and install it on your macOS system. Please make sure that the XCode version is less than or equal to 13.0 and the Swift version is less than or equal to 5.4, otherwise, it will not be able to run on the Android platform.

Please also make sure you have the NFC tags ready with you and an NFC-enabled physical device (either an Android phone or an iPhone).

Integrate FusionNFC Library

SCADE provides users with all the necessary APIs including Swift foundation and objective C libs that are required to integrate the FusionNFC library. Let’s start by creating a new project, File -> New -> New Project. Then select the SCADE option, enter the name of the project, and click Create. We are ready to integrate the Fusion library into the SCADE app.

Now navigate to the Package.swift file and add the FusionNFC git URL as shown in the below SPM dependency:

// swift-tools-version:5.3

import Foundation
import PackageDescription

let SCADE_SDK = ProcessInfo.processInfo.environment["SCADE_SDK"] ?? ""

let package = Package(
  name: "NFCTool",
  platforms: [
    .macOS(.v10_14), .iOS(.v13),
  ],
  products: [
    .library(
      name: "NFCTool",
      type: .static,
      targets: [
        "NFCTool"
      ]
    )
  ],
  dependencies: [
    .package(
      name: "FusionNFC", url: "https://github.com/scade-platform/FusionNFC.git", .branch("main"))
  ],
  targets: [
    .target(
      name: "NFCTool",
      dependencies: [
        .product(name: "FusionNFC", package: "FusionNFC")
      ],
      exclude: ["main.page"],
      swiftSettings: [
        .unsafeFlags(["-F", SCADE_SDK], .when(platforms: [.macOS, .iOS])),
        .unsafeFlags(["-I", "\(SCADE_SDK)/include"], .when(platforms: [.android])),
      ]
    )
  ]
)

Design the App

We need to create a basic container to accommodate pages for reading and writing NFC tags. So navigate to main.page file and drag and drop the following UI widgets.

image2.png

a.) Toolbar: It will contain the readerButton and writerButton which will navigate to the Reader/Writer page.

b.) PageContainer: It will contain the Reader/Writer page content in the fragment area.

Now we will create two pages namely the Reader and Writer page.

Reader Page:

image3.png

a.) Label1: The urlLabel will be used to display the URL stored in the memory of the NFC tag.

b.) Label2: The descriptionLabel will be used to display the description stored in the memory of the NFC tag.

c.) Button: Upon the click of the readButton, it will read the data in the NFC tag.

Writer Page:

image4.png

a.) TextBox1: The urlTextBox will be used to edit the URL which will be stored in the memory of the NFC tag.

b.) TextBox2: The descriptionTextBox will be used to edit the description which will be stored in the memory of the NFC tag.

c.) Button : Upon the click of the writeButton, it will write the data to the NFC tag.

Let’s dive into the Code

We have created the layout file above to declare the pages and the widgets that we will use.

Main Page:

We will create the references for the ReaderPageAdapter and WriterPageAdapter so that these pages will be contained in the pageContainer.

  let readerPage: ReaderPageAdapter = ReaderPageAdapter()
  let writerPage: WriterPageAdapter = WriterPageAdapter()
  var pageContainer: SCDLatticePageContainer?

Now let’s include these snippets in the load method of main.page.swift :

    self.readerPage.load("reader.page")
    self.writerPage.load("writer.page")

    self.readerButton.onClick { _ in self.showPage(self.readerPage) }
    self.writerButton.onClick { _ in self.showPage(self.writerPage) }

    // Now,we get a reference to the page container
    self.pageContainer = self.page!.getWidgetByName("pageContainer1") as? SCDLatticePageContainer

    // Finally, we use the page container to show page1 (ReaderPage)
    self.reader.show(view: self.pageContainer)
  func showPage(_ page: SCDLatticePageAdapter) {
    page.show(view: self.pageContainer)
  }

Write NFC Page:

Let’s declare the nfcManager variable and instantiate it to use the core NFC features. On the click of the writeButton we will declare the write() method to write the URL and description to the NFC tags.

  var nfcManager: NFCManager?

Now inside the load() method, we will attach the onClick() listener method to call the write() method. Also, for the Android-specific code, we need to disable the foreground dispatcher for the NFC.

   override func load(_ path: String) {
    super.load(path)
    // initialize the NFCManager
    nfcManager = NFCManager(alertMessage: "Hold your iPhone near an NFC tag.")

    // connect the button action to write func
    self.writeButton.onClick { _ in
      print("clicked write button")
      self.write()
    }

    // Below code is only for Android
    self.page!.onExit.append(
      SCDWidgetsExitEventHandler { _ in
        self.nfcManager?.disableForegroundDispatch()
      })
  }

We will declare the NFCURIRecord and NFCTextRecord variables. Then assign the text values to these variables which will be used to create the NFCMessage object. It accepts the uriRecord and textRecord as input parameters. Finally, we will write this nfcMessage object to the NFC tag using writeTag() method.

 // write func
 func write() {

    // prepare the NFCURIRecord from the URL
    var uriRecord: NFCURIRecord?
    if let url = URL(string: urlTextBox.text) {
      uriRecord = NFCURIRecord(url: url)
    }

    // prepare the NFCTextRecord from the String and Locale
    let textRecord = NFCTextRecord(
      string: descriptionTextBox.text, locale: Locale(identifier: "en"))

    // initialize the NFCMessage with NFCURIRecord and NFCTextRecord
    let nfcMessage = NFCMessage(uriRecord: uriRecord, textRecord: textRecord)

    // initialize the NFCMessage
    nfcManager = NFCManager(alertMessage: "Hold your iPhone near an NFC tag.")

    // write NFC Tag
    nfcManager?.writeTag(nfcMessage)
  }

Read NFC Page:

Similarly to the write NFC page, we will declare the nfcManager variable and instantiate it to use the core NFC features. On the click of the readButton we will declare the read() method to read the URL and description stored in the memory of the NFC tags.

import FusionNFC
var nfcManager: NFCManager?
  override func load(_ path: String) {
        super.load(path)
        // initialize the NFCManager
        nfcManager = NFCManager(alertMessage: "Hold your iPhone near an NFC tag.")

        // connect the button action to read func
        self.readButton.onClick{_ in 
        print("clicked read ubtton")
        self.read()}

        // Below code is only for Android
        self.page!.onExit.append(SCDWidgetsExitEventHandler{_ in
            self.nfcManager?.disableForegroundDispatch()
        })     
      }

Let’s declare the read() NFC function which will internally use the readTag() method by nfcManager. The message object is returned which contains the textRecord and uriRecord and we will display the data using the urlLabel and descriptionLabel.

  // read func
  func read() {
    // read NFC Tag
    nfcManager?.readTag { message in

      // get url and text from NFCMessage
      guard let message = message else { return }
      if let uriRecord = message.uriRecord {
        self.urlLabel.text = "URL: \(uriRecord.url.absoluteString)"
     }

      if let textRecord = message.textRecord {
        self.descriptionLabel.text = "Description: \(textRecord.string)"
      }
    }
  }

Test the write/read feature for NFC tags:

Let’s test the write feature of the SCADE app that we have developed till now. We will either require an Android or iOS device. Navigate to the build.yaml file and add the build settings for each environment. For iOS declare the provisioning profile and the certificate as shown below:

  sign:
    provision-profile: /Users/vj/Desktop/certs/vj.mobileprovision
    certificate: /Users/vj/Desktop/certs/vj.p12

  plist:
    - key: CFBundleShortVersionString
      type: string  # string, bool, int, list or dict
      value: 1.0
    - key: CFBundleVersion
      type: string
      value: 1
    - key: NSLocationWhenInUseUsageDescription
      type: string
      value:
    - key: NSCameraUsageDescription
      type: string
      value: Take pictures from camera
    - key: NSPhotoLibraryUsageDescription
      type: string
      value: Choose a photo from your library
    - key: NFCReaderUsageDescription
      type: string
      value: This app read and write tags
    - key: UIRequiredDeviceCapabilities
      type: list
      value: ["armv7", "nfc"]

For the Android build settings, create one file AndroidManifest.xml, and add the below snippet to the build.yaml under the Android settings.

android:
  name: NFCTool
  id: com.scadefusion.nfc
  version-name: 1.0.0
  version-code: 1
  build-type: Debug
  key-store-properties:
  google-api-key:
  manifest-file: AndroidManifest.xml
  permissions: ["NFC"]

Now navigate to the AndroidManifest.xml file and add the below snippet to declare the NFC permissions and related settings.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.scade.rendersvg"
    android:versionCode="1"
    android:versionName="1.0.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="28" />

    <uses-permission android:name="android.permission.NFC" />

    <uses-feature android:glEsVersion="0x00020000"/>
    <uses-feature android:name="android.hardware.nfc" android:required="true" />

    <application
        android:name="com.scade.phoenix.PhoenixApplication"
        android:allowBackup="false"
        android:icon="@drawable/ic_launcher"
        android:label="RenderSVG"
        android:theme="@android:style/Theme.Black.NoTitleBar">
        <activity
            android:name="com.scade.phoenix.MainActivity"
            android:label="RenderSVG"
            android:windowSoftInputMode="adjustResize|stateHidden">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>


        </activity>

        <receiver android:name="com.FusionNFC_Android.NFCReceiver"/>

        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="AIzaSyAYoreZUQAcxs-Yt18zEAidBSqEuoqnKP4"/>
        <uses-library
            android:name="org.apache.http.legacy"
            android:required="false" />
    </application>

</manifest>

Now we are good to build the .apk or .ipa files and test the build on the Android or iOS system.

nfcimage5.jpeg

nfcimage6.jpeg

nfcimage7.jpeg

Voila 🎉! It was super easy to build an iOS/Android app using the SCADE IDE to read/write NFC tags. Fusion SDK offers a wide variety of libraries that are easy to understand and easy to integrate for various use cases.

It is cool. We encourage you to integrate any Fusion SDKs and try them out yourself 😊.

Source Code: https://github.com/6vedant/FusionNFCTool