---
title: "Android SDK: NFC data listener"
slug: "android-sdk-nfc-data-listener"
description: "Enable NFC data listener for real-time callbacks on NFC reading success or failure. Ensure compliance and enhance your app's data processing capabilities."
updated: 2026-02-04T06:23:22Z
published: 2026-02-04T06:24:23Z
---

> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.veriff.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Android SDK: NFC data listener

> [!NOTE]
> This feature needs to be enabled for your integration.
> 
> Contact your **solutions engineer** for info and configuration.

Starting with Android SDK version 7.15.0, you can receive real-time callbacks when the SDK successfully reads or fails to read NFC data from identity documents. This allows your app to get access to extracted NFC data (DG1 and DG2) for additional processing or analytics.

Use the NFC data listener when you need to:

- Access raw NFC data (Machine Readable Zone and Face Image) for additional verification
- Track NFC reading success/failure for analytics
- Implement custom handling based on NFC scan results
- Store NFC data in your own systems for compliance or audit purposes

## Prerequisites

The listener will only receive callbacks if:

- NFC reading has been enabled for your integration by Veriff
- NFC reading [permissions have been granted](/v1/docs/android-sdk-guide#add-permissions) in the SDK
- The end-user's document supports NFC (e-passports, some ID cards)
- The device has NFC hardware capability

---

## Add NFC data listener

### Step 1: Implement the listener interface

Create a class that implements `VeriffNfcDataListener`:

**Kotlin**

```kotlin
import com.veriff.VeriffNfcDataListener
import com.veriff.NfcData
import android.util.Log

class MyNfcDataListener : VeriffNfcDataListener {
    
    override fun onNfcDataExtracted(nfcData: NfcData) {
        // Called when NFC reading succeeds
        Log.d("NFC", "DG1: ${nfcData.dg1}")
        Log.d("NFC", "DG2: ${nfcData.dg2}")
        
        // Process the NFC data as needed
        // Both dg1 and dg2 are Base64-encoded strings
    }
    
    override fun onNfcDataExtractionFailed() {
        // Called when NFC reading fails
        Log.w("NFC", "Failed to extract NFC data")
        
        // Handle failure case
    }
}
```

**Java**

```java
import com.veriff.VeriffNfcDataListener;
import com.veriff.NfcData;
import android.util.Log;
import org.jetbrains.annotations.NotNull;

public class MyNfcDataListener implements VeriffNfcDataListener {
    
    @Override
    public void onNfcDataExtracted(@NotNull NfcData nfcData) {
        // Called when NFC reading succeeds
        Log.d("NFC", "DG1: " + nfcData.getDg1());
        Log.d("NFC", "DG2: " + nfcData.getDg2());
        
        // Process the NFC data as needed
        // Both dg1 and dg2 are Base64-encoded strings
    }
    
    @Override
    public void onNfcDataExtractionFailed() {
        // Called when NFC reading fails
        Log.w("NFC", "Failed to extract NFC data");
        
        // Handle failure case
    }
}
```

### Step 2: register the listener in configuration

Add the listener to your Veriff Configuration when starting the SDK:

**Kotlin**

```kotlin
val configuration = Configuration.Builder()
    .veriffNfcDataListener(MyNfcDataListener())
    .build()

val intent = Sdk.createLaunchIntent(this, sessionUrl, configuration)
startActivityForResult(intent, REQUEST_CODE_VERIFF)
```

**Java**

```java
Configuration configuration = new Configuration.Builder()
```

```java
    .veriffNfcDataListener(new MyNfcDataListener())
    .build(); (edited)
Intent intent = Sdk.createLaunchIntent(this, sessionUrl, configuration);
startActivityForResult(intent, REQUEST_CODE_VERIFF);
```

---

## `NfcData` object

The `NfcData` object contains two properties:

| Property | Type | Description |
| --- | --- | --- |
| `dg1` | `string?` | DATA GROUP 1 — Machine Readable Zone Information (Base64-encoded). Contains passport number, name, birth date, nationality, etc. Follows ICAO Doc 9303, part 10, Section 4.7.1. |
| `dg2` | `string?` | DATA GROUP 2 — Encoded Identification Features — Face (Base64-encoded). Contains the face image from the document in JPEG2000 format. Follows ICAO Doc 9303, part 10, Section 4.7.2. |

Note: Both fields can be `null` if the specific data group is not available on the document or failed to read.

---

## Decoding NFC data

The NFC data is provided as Base64-encoded strings. To decode them back to binary data:

**Kotlin**

```kotlin
import java.util.Base64
override fun onNfcDataExtracted(nfcData: NfcData) {
    // Decode DG1 (Machine Readable Zone)
    nfcData.dg1?.let { dg1Base64 ->
        val dg1Bytes = Base64.getDecoder().decode(dg1Base64)
        // Process DG1 binary data
    }

    // Decode DG2 (Face Image)
    nfcData.dg2?.let { dg2Base64 ->
        val dg2Bytes = Base64.getDecoder().decode(dg2Base64)
        // dg2Bytes contains JPEG2000 encoded face image
        // You can save this as a file or process it further
    }
}
```

**Java**

```java
import java.util.Base64;
@Override
public void onNfcDataExtracted(@NotNull NfcData nfcData) {
    // Decode DG1 (Machine Readable Zone)
    if (nfcData.getDg1() != null) {
        byte[] dg1Bytes = Base64.getDecoder().decode(nfcData.getDg1());
        // Process DG1 binary data
    }

    // Decode DG2 (Face Image)
    if (nfcData.getDg2() != null) {
        byte[] dg2Bytes = Base64.getDecoder().decode(nfcData.getDg2());
        // dg2Bytes contains JPEG2000 encoded face image
        // You can save this as a file or process it further
    }
}
```

### Decoding Errors

You may get errors when decoding Base64 due to:

- Invalid Base64: ensure you are using `java.util.Base64`, not other `Base64` implementations
- Character encoding: do not try to decode as `UTF-8` string directly, DG2 is binary image data

---

## `NFCData` object

The `NFCData` object contains two properties:

| Property | Type | Description |
| --- | --- | --- |
| `dg1` | `string \| null` | DATA GROUP 1 — Machine Readable Zone Information (Base64-encoded). Contains passport number, name, birth date, nationality, etc. Follows ICAO Doc 9303, part 10, Section 4.7.1. |
| `dg2` | `string \| null` | DATA GROUP 2 — Encoded Identification Features — Face (Base64-encoded). Contains the face image from the document in JPEG2000 format. Follows ICAO Doc 9303, part 10, Section 4.7.2. |

---

## Additional info

### Listener Lifecycle

- **Global Singleton**: only one listener can be active at a time across your entire application.
- **Replacement**: setting a new listener in a new `Configuration` will replace any previously set listener.
- **Auto-Cleanup**: the listener is automatically cleared when the SDK session ends (when the user closes the SDK or verification completes).

### Threading

Callbacks are executed on the **main (UI) thread**. If you need to perform heavy processing, it is recommended to dispatch work to a background thread:

**Kotlin**

```kotlin
override fun onNfcDataExtracted(nfcData: NfcData) {
        lifecycleScope.launch(Dispatchers.IO) {
            // Heavy processing on background thread
            processNfcData(nfcData)
        }
    }
```

**Java**

```java
@Override
    public void onNfcDataExtracted(@NotNull NfcData nfcData) {
        new Thread(() -> {
            // Heavy processing on background thread
            processNfcData(nfcData);
        }).start();
    }
```

### Data Privacy

NFC data contains sensitive personal information:

- DG1: full name, date of birth, document number, nationality
- DG2: biometric face image

Ensure you:

- Handle this data in compliance with GDPR, CCPA, and other privacy regulations
- Implement appropriate security measures (encryption, secure storage)
- Only retain data for as long as necessary
- Have proper user consent mechanisms in place

---

### FAQ

#### Listener is not receiving callbacks

1. Check NFC is enabled: verify NFC is enabled in your Veriff integration configuration and permissions have been granted
2. Verify document type: not all documents have NFC chips
3. Check device hardware: ensure the device has NFC capability (`PackageManager.FEATURE_NFC`)
4. Verify listener registration: ensure the listener is set before starting the SDK session

#### DG1 or DG2 is `null`

Although this scenario is unlikely to happen, if it occurs contact the Customer Support and your Solutions Engineer to report and troubleshoot the issue.

---

## Changelog

| Date | Description |
| --- | --- |
| Feb 4, 2026 | FAQ > “DG1 or DG2 is `null`" question updated |
| Feb 3, 2026 | Documentation published |
