Synchronizing Tapkey NFC Transponders¶
This chapter describes how to synchronize Tapkey NFC Transponders using the Tapkey Mobile SDK for Android
.
Only Tapkey NFC Transponders supported
Only NFC Transponder produced by Tapkey are supported. Empty NFC Transponder or those produced for a different purpose are not supported.
On Android, there are different modes in which the smartphone can work with NFC. For communication with NFC Transponder, the Reader/writer mode is used. The smartphone acts as an active NFC device to communicate with passive NFC Transponder.
This documentation explains how to use the Tapkey Mobile SDK for Android to synchronize Tapkey NFC Transponders, but does not discuss the basics of using NFC on Android.
For more details about NFC and Android, please refer to the Android NFC Documentation.
For more details about the Android NFC API, please refer to the Android NFC API Documentation.
General Concepts of Tapkey NFC Transponders¶
Tapkey NFC Transponders are individually encrypted and can only be read and written by the Tapkey Trust Service. Direct read/write access by smartphones or other parties is not possible. Therefore, in order to write data to a Tapkey NFC Transponder, an online connection between the server and the card is established. The mobile app acts as a relay between both by using the Tapkey Mobile SDK for Android.
sequenceDiagram participant CARD as Tapkey NFC Transponder participant APP as Client App participant TTS as Tapkey Trust Service APP -->> APP: Wait for Tapkey NFC Transponder CARD -->> APP: Tapkey NFC Transponder presented APP ->>+ TTS: Establish connection Note over TTS, CARD: Tapkey NFC Transponder is written by the Tapkey Trust Service loop Synchronization TTS -->> CARD: Send Data CARD -->> TTS: Receive Data end TTS ->>- APP: Connection Closed CARD -->> APP: Tapkey NFC Transponder removed
Managing Grants¶
Tapkey NFC Transponders are encrypted, and therefore grants cannot be directly written to Tapkey NFC Transponders using the SDK. Instead, grants are managed via the Tapkey Web API. After grants have been modified, affected Tapkey NFC Transponders need to be synchronized in order to apply the changes.
Setup Requisites¶
To use the NFC API of Android, it is required to declare the NFC feature and claim the NFC permission in the Android Manifest.
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="false" />
...
</manifest>
Start Listening for Tapkey NFC Transponders¶
To start listening for Tapkey NFC Transponders, first retrieve the Android NfcAdapter
.
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(activity);
// Handle if the smartphone does not support NFC or NFC is disabled gracefully
if (nfcAdapter == null || !nfcAdapter.isEnabled()) {
return;
}
The NFCAdapter will invoke the ReaderCallback on a Thread without a Looper. As synchronization requires a lot of asynchronous work, a Looper is required. Therefore, create a new Handler
on which the work will be posted.
Handler handler = new Handler(Looper.getMainLooper());
To start listening for Tapkey NFC Transponders, call the enableReaderMode
method on the NfcAdapter
.
// Create a Bundle and apply any NFC workarounds if required
Bundle options = new Bundle();
NfcWorkarounds.applyNfcReaderModeOptions(this, options);
// Enable the reader mode and provide the callback, flags, and options
nfcAdapter.enableReaderMode(
activity,
tag -> handler.post(() -> handleNewTag(tag)),
NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK,
options
);
The handleNewTag
method will be called for each new tag that is discovered.
Stop Listening for Tapkey NFC Transponders¶
To stop listening for Tapkey NFC Transponders, call the disableReaderMode
method on the NfcAdapter
.
if (nfcAdapter == null) {
return;
}
nfcAdapter.disableReaderMode(activity);
Begin NFC Session¶
Synchronizing a Tapkey NFC transponder can take several seconds. As it happens quite frequently that the connection between the smartphone and the NFC transponder is lost temporarily while the synchronization is ongoing due to factors like tag movement, the Tapkey Mobile SDK provides functionality to continue the process, as soon as the NFC connection is reestablished. This is achieved by using the RecoverableIsoDepConnection
interface.
First, retrieve the CardManager
from the Tapkey ServiceFactory
. Then, create an IsoDepConnection
from the detected NFC tag using the NfcUtils.getIsoDepConnectionForDesfire(tag)
method. If the returned IsoDepConnection
is null
, it indicates that the NFC tag technology is not supported.
RecoverableIsoDepConnection recoverableIsoDepConnection;
public void handleNewTag(Tag tag) {
// Retrieve the CardManager from Tapkey ServiceFactory
CardManager cardManager = tapkeyServiceFactory.getCardManager();
// Create an IsoDepConnection from the detected NFC Tag
IsoDepConnection isoDep = NfcUtils.getIsoDepConnectionForDesfire(tag);
// If the returned IsoDepConnection is null, the NFC Tag is not supported
if (isoDep == null) {
return;
}
if (recoverableIsoDepConnection == null) {
// If no synchronization has been started yet,
// create a new RecoverableIsoDepConnection.
// This allows you to continue the synchronization if the tag was lost or the connection was interrupted.
recoverableIsoDepConnection = NfcUtils.createRecoverableIsoDepConnection(tag.getId());
// Subscribe to the State observable to guide the user through the synchronization process
recoverableIsoDepConnection.getOnStateChanged().addObserver(state -> {
switch (state) {
case WaitingForTag:
// Indicate that the user should present the NFC Tag
break;
case Normal:
// Indicate that synchronization is ongoing
break;
case Completed:
// Indicate that synchronization is completed
break;
case WrongTag:
// Indicate that the wrong NFC Tag was presented and the synchronization
// cannot be continued until the original NFC Tag is presented.
break;
}
});
// Pass the RecoverableIsoDepConnection to the methods of `CardManager` to perform actions on the card
cardManager.syncCardAsync(userId, tag.getId(), recoverableIsoDepConnection, ....)
...;
}
// Whenever a Tag is discovered, pass it to the `RecoverableIsoDepConnection` to start or continue the connection.
recoverableIsoDepConnection.replaceConnection(tag.getId(), isoDep);
}
In the code snippet above, tag
represents the Tag
object obtained from the operating system. The RecoverableIsoDepConnection
instance, recoverableIsoDepConnection
, is used to manage the NFC connection and handle potential interruptions. By subscribing to the state observable, you can provide appropriate user guidance based on the different states of the synchronization process.
Ensure that you pass the RecoverableIsoDepConnection
to the relevant methods of the CardManager
for performing actions on the Tapkey NFC Transponder. The synchronization process can be initiated by calling cardManager.syncCardAsync(userId, tag.getId(), recoverableIsoDepConnection, ...)
.
Synchronize Tapkey NFC Transponders¶
To synchronize a Tapkey NFC Transponder, you can use the syncCardAsync
method of the CardManager
and pass the previously created RecoverableIsoDepConnection
instance. The syncCardAsync
method returns a Promise that resolves when the synchronization is successfully completed or rejects if the synchronization fails.
// The RecoverableIsoDepConnection that was created earlier
RecoverableIsoDepConnection recoverableIsoDepConnection = ...;
cardManager.syncCardAsync(userId, tag.getId(), recoverableIsoDepConnection, progress -> {
// Progress has changed
displayProgress(progress);
}, CancellationTokens.None)
.continueOnUi(aVoid -> {
// Synchronization completed
displaySuccess();
return null;
})
.catchOnUi(e -> {
// Synchronization failed
displayError(e);
return null;
})
.conclude();
You can monitor the progress of the synchronization by providing a callback function that receives the progress updates. In this example, the displayProgress(progress)
function is called with the updated progress value.
Register a Tapkey NFC Transponder¶
Before a grant can be assigned to a Tapkey NFC Transponder, the card needs to be registered to the owner's account. To accomplish this, you can use the takeCardOwnershipAsync
method of the CardManager
class and provide the owner's account ID and the previously created RecoverableIsoDepConnection
instance.
Transponder must be unassigned
Please note that the Tapkey NFC Transponder must either be unassigned or not have any grants assigned to it. If the card is already assigned to another owner's account and has grants, the grants must be removed by the current owner before this operation can succeed.
// The RecoverableIsoDepConnection that was created earlier
RecoverableIsoDepConnection recoverableIsoDepConnection = ...;
cardManager.takeCardOwnershipAsync(userId, ownerId, tag.getId(), recoverableIsoDepConnection, progress -> {
displayProgress(progress);
}, CancellationTokens.None)
.continueOnUi(aVoid -> {
// sync completed
displaySuccess();
return null;
})
.catchOnUi(e -> {
// sync failed
displayError(e);
return null;
})
.conclude();