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.
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:
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:
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.
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