This tutorial describes how to detect specific NFC Forum tags using NFC Discovery API.
The NFC
Discovery API provides a mechanism to discover NFC tags at the device's
near field using the CNfcTagDiscovery class.
Before you begin, refer to the following:
nfcserver.h, RNfcServer
nfctagdiscovery.h, CNfcTagDiscovery
nfcconnection.h, MNfcConnection
nfctagconnectionlistener.h, MNfcTagConnectionListener
nfctagsubscription.h, CNfcTagSubscription
nfcconnection.h, MNfcConnection
nfctag.h, MNfcTag
Create a
class that inherits from the MNfcTagConnectionListener and CBase classes. For example,
class CMyTagInitializer : public CBase, public MNfcTagConnectionListener
Register
for receiving notifications when the specified tag is detected in
the proximity of the device using the CNfcTagDiscovery::AddTagConnectionListener() method.
Note: Only one listener can be added at a time.
CNfcTagDiscovery* iNfcTagDiscovery; iNfcTagDiscovery = CNfcTagDiscovery::NewL( aServer ); iNfcTagDiscovery->AddTagConnectionListener( MNfcTagConnectionListener& aListener);
Subscribe
to the NFC server using the CNfcTagDiscovery::AddTagSubscriptionL() method by specifying the interested tag type.
iSubscription = CNfcTagSubscription::NewL(); iSubscription->AddConnectionModeL(TNfcConnectionInfo::ENfcType1); iNfcTagDiscovery->AddTagSubscriptionL( *iSubscription );
When the tag of the interested type is detected, MNfcTagConnectionListener::TagDetected() is called back.
The returned tag is used to open the connection.
The sequence diagram below illustrates how the tag discovery works:

The following example illustrates how to detect and open a connection to the NFC Forum Type 2 tag.
#include <nfctag.h>
#include <nfctagsubscription.h>
#include <nfctagconnectionlistener.h>
#include <nfcconnectioninfo.h>
// FORWARD DECLARATIONS
class CNfcTagDiscovery;
class MNfcConnection;
class RNfcServer;
class CMyTagInitializer;
class CNfcType2Connection;
// CLASS DECLARATION
// A Class that waits for a tag and then opens a connection to it.
class CMyTagInitializer : public CBase, public MNfcTagConnectionListener
{
public:
static CMyTagInitializer* NewL( RNfcServer& aServer );
static CMyTagInitializer* NewLC( RNfcServer& aServer );
virtual ~CMyTagInitializer();
/*
* @param aConnection Connection variable that is initialized and opened.
* @param aMode Type of connection mode that is to be initialized.
*/
TInt InitConnectionL( MNfcConnection* aConnection,
TNfcConnectionInfo::TNfcConnectionMode aMode );
public:
// From MNfcTagConnectionListener
void TagDetected( MNfcTag* aNfcTag );
void TagLost();
private:
CMyTagInitializer( RNfcServer& aServer );
void ConstructL( RNfcServer& aServer );
CActiveScheduler* iScheduler;
CNfcTagDiscovery* iNfcTagDiscovery;
MNfcConnection* iTagConnection;
CNfcTagSubscription* iSubscription;
RNfcServer& iServer;
TNfcConnectionInfo::TNfcConnectionMode iMode;
MNfcTag* iNfcTag;
};
void CMyTagInitializer::ConstructL( RNfcServer& aServer )
{
iScheduler = new (ELeave) CActiveScheduler();
CActiveScheduler::Install( iScheduler );
iNfcTagDiscovery = CNfcTagDiscovery::NewL( aServer );
// Add tag connection listener.
iNfcTagDiscovery->AddTagConnectionListener( *this );
iSubscription = CNfcTagSubscription::NewL();
}
TInt CMyTagInitializer::InitConnectionL( MNfcConnection* aConnection,
TNfcConnectionInfo::TNfcConnectionMode aMode )
{
iTagConnection = aConnection;
iSubscription->AddConnectionModeL( aMode, 100 );
// Add tag subscription.
iNfcTagDiscovery->AddTagSubscriptionL( *iSubscription );
CActiveScheduler::Start();
return KErrNone;
}
void CMyTagInitializer::TagDetected( MNfcTag* aNfcTag )
{
iNfcTag = aNfcTag;
// Open connection to the tag.
iNfcTag->OpenConnection( *iTagConnection );
CActiveScheduler::Stop();
}
void CMyTagInitializer::TagLost()
{
// No step required here, next attempt to use the connection will fail with an error
}
CMyTagInitializer::CMyTagInitializer( RNfcServer& aServer ) :
iScheduler( NULL ),
iNfcTagDiscovery( NULL),
iTagConnection( NULL ),
iSubscription( NULL ),
iServer( aServer ),
iNfcTag( NULL )
{
}
CMyTagInitializer* CMyTagInitializer::NewL( RNfcServer& aServer )
{
CMyTagInitializer* self = NewLC( aServer );
CleanupStack::Pop( self );
return self;
}
CMyTagInitializer* CMyTagInitializer::NewLC( RNfcServer& aServer )
{
CMyTagInitializer* self = new (ELeave) CMyTagInitializer( aServer );
CleanupStack::PushL( self );
self->ConstructL( aServer );
return self;
}
CMyTagInitializer::~CMyTagInitializer()
{
if ( iNfcTagDiscovery )
{
iNfcTagDiscovery->RemoveTagConnectionListener();
iNfcTagDiscovery->RemoveTagSubscription();
}
delete iNfcTag;
delete iSubscription;
delete iNfcTagDiscovery;
delete iScheduler;
}
void mainDoL()
{
// Open handle to NFC server
RNfcServer server;
server.Open();
CleanupClosePushL( server );
// Create and start TagConnectionInitializer. Implementation below.
CMyTagInitializer* initializer = CMyTagInitializer::NewLC( server );
CNfcType2Connection* connection = CNfcType2Connection::NewLC( server );
initializer->InitConnectionL( connection, TNfcConnectionInfo::ENfcType2);
//
// In this point of execution the connection is open and can be used.
//
CleanupStack::PopAndDestroy( connection );
CleanupStack::PopAndDestroy( initializer );
CleanupStack::PopAndDestroy(); // server
}
TInt E32Main()
{
CTrapCleanup* cleanup = CTrapCleanup::New();
TRAPD( err, mainDoL() );
delete cleanup;
return err;
}