Discovering NFC Tags

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:


  1. Create a class that inherits from the MNfcTagConnectionListener and CBase classes. For example,

    class CMyTagInitializer : public CBase, public MNfcTagConnectionListener                  
  2. 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);
  3. Subscribe to the NFC server using the CNfcTagDiscovery::AddTagSubscriptionL() method by specifying the interested tag type.

    iSubscription = CNfcTagSubscription::NewL(); 
    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>

class CNfcTagDiscovery;
class MNfcConnection;
class RNfcServer;
class CMyTagInitializer;
class CNfcType2Connection;

// A Class that waits for a tag and then opens a connection to it.
class CMyTagInitializer : public CBase, public MNfcTagConnectionListener
    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 );
		// From MNfcTagConnectionListener
    void TagDetected( MNfcTag* aNfcTag );  
    void TagLost();
    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 );

    return KErrNone; 

void CMyTagInitializer::TagDetected( MNfcTag* aNfcTag )
    iNfcTag = aNfcTag;
    // Open connection to the tag.
    iNfcTag->OpenConnection( *iTagConnection );

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;

    if ( iNfcTagDiscovery )

    delete iNfcTag;
    delete iSubscription;
    delete iNfcTagDiscovery;
    delete iScheduler;

void mainDoL()
    // Open handle to NFC server
    RNfcServer server;
    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;

Related concepts

Related tasks