# NFC Scan

The NFC Scan module reads the secure [NFC](https://developer.incode.com/docs/glossary#nfc-scan) chip embedded in ICAO 9303-compliant travel documents, such as e-passports. It then returns the document holder's data, including the chip's portrait image. When a flow captures multiple IDs, NFC Scan applies only to the first ID.

For an overview of this module and how it works, see [NFC Scan](https://developer.incode.com/docs/nfc).

How you use this module depends on your [integration pattern](https://developer.incode.com/docs/android-common-implementation-patterns#integration-patterns). In Patterns 1 and 2, you add the module to a `FlowConfig` in code as shown on this page. In Pattern 3, you define your modules and configuration in Dashboard as a Flow or Workflow and reference it by ID with `startFlow()` or `startWorkflow()` as shown on [Run Flows Configured in Dashboard](https://developer.incode.com/docs/android-run-flows-configured-online).

## Add NFC Scan

1. Ensure you've [declared](https://developer.incode.com/docs/android-installation#declare-dependencies) the `nfc` dependency in your `[module]/build.gradle`.
2. Add [ID Scan](https://developer.incode.com/docs/android-id-scan), then [Process ID](https://developer.incode.com/docs/android-process-id), before NFC Scan. NFC Scan reads the chip after the document has been captured and processed.
3. Add the module with `addNfcScan(nfcScan)`:

   ```kotlin
   flowConfigBuilder.addNfcScan(nfcScan)
   ```
   ```java
   flowConfigBuilder.addNfcScan(nfcScan);
   ```

### Example

The example below builds an `NfcScan` module that shows the NFC symbol confirmation screen and processes the chip data, adds it to the flow after the ID Scan and Process ID steps, and listens for the result through `onNfcScanCompleted()`.

```kotlin
val nfcScan = NfcScan.Builder()
    .setShowNfcSymbolConfirmationScreen(true)
    .setProcessNfcData(true)
    .build()

val flowConfig = FlowConfig.Builder()
    // ... add the ID Scan and Process ID steps first
    .addNfcScan(nfcScan)
    .build()

val onboardingListener = object : OnboardingListener() {
    override fun onNfcScanCompleted(nfcScanResult: NfcScanResult) {
        // NFC scan completed. Process the result.
    }
}

IncodeWelcome.getInstance()
    .startOnboarding(activityContext, sessionConfig, flowConfig, onboardingListener)
```
```java
NfcScan nfcScan = new NfcScan.Builder()
    .setShowNfcSymbolConfirmationScreen(true)
    .setProcessNfcData(true)
    .build();

FlowConfig flowConfig = new FlowConfig.Builder()
    // ... add the ID Scan and Process ID steps first
    .addNfcScan(nfcScan)
    .build();

IncodeWelcome.OnboardingListener onboardingListener = new IncodeWelcome.OnboardingListener() {
    @Override
    public void onNfcScanCompleted(@NonNull NfcScanResult nfcScanResult) {
        // NFC scan completed. Process the result.
    }
};

IncodeWelcome.getInstance()
    .startOnboarding(activityContext, sessionConfig, flowConfig, onboardingListener);
```

### Transparent Background Mode

To show the NFC scanning bottom sheet on a transparent background, so your screen remains visible during the scan, configure the module like this:

```kotlin
val nfcScan = NfcScan.Builder()
    .setShowTutorials(false)
    .setShowNfcSymbolConfirmationScreen(false)
    .setIdType(IdScan.IdType.PASSPORT) // or ID
    .setShowInitialDataConfirmationScreen(false)
    // ... other builder options as needed
    .build()
```
```java
NfcScan nfcScan = new NfcScan.Builder()
    .setShowTutorials(false)
    .setShowNfcSymbolConfirmationScreen(false)
    .setIdType(IdScan.IdType.PASSPORT) // or ID
    .setShowInitialDataConfirmationScreen(false)
    // ... other builder options as needed
    .build();
```

## Configuration Options

Configure the module with `NfcScan.Builder`. The table below lists the most common options.

| Setting                                       | Description                                                                                                                                                                                                                                                                                                                                                                                               |
| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `setShowNfcSymbolConfirmationScreen(Boolean)` | Shows a screen asking the user whether their document contains an NFC chip. If you disable this, handle the no-chip case yourself so a user whose document has no NFC chip does not get stuck.                                                                                                                                                                                                            |
| `setProcessNfcData(Boolean)`                  | Submits the chip data to the back end for identity validation. When enabled, two additional `FaceMatch.MatchType` options become available beyond the default `ID_SELFIE`: `NFC_SELFIE` compares the chip portrait to the selfie, and `NFC_3_WAY` compares the cropped ID image, the chip portrait, and the selfie. See [Face Match](https://developer.incode.com/docs/android-face-match). |
| `setShowTutorials(Boolean)`                   | Shows tutorials on how to scan the document.                                                                                                                                                                                                                                                                                                                                                              |
| `setIdType(IdScan.IdType)`                    | Sets the document type to use for NFC scanning.                                                                                                                                                                                                                                                                                                                                                           |
| `setNfcMaxRetries(Integer)`                   | Sets the maximum number of NFC scan attempts. Default: `5`.                                                                                                                                                                                                                                                                                                                                               |

For each NFC read, the SDK tries the PACE protocol first and falls back to BAC when PACE is unavailable or fails. PACE and BAC are alternatives, not both required. An NFC chip whose access protocol the device cannot complete fails the scan and routes through the retries configured using `NfcScan.Builder.setNfcMaxRetries(...)`.

For the complete option set, see `NfcScan.Builder` in [API Reference](https://developer.incode.com/docs/android-api-reference).

## Result

NFC Scan delivers an `NfcScanResult` to the `onNfcScanCompleted(NfcScanResult)` callback on the `OnboardingListener`. Key fields include:

- `compositeCheckDigit`: The Machine Readable Zone (MRZ) composite check digit (DG1); `<` when unset.
- `dateOfBirth`: The date of birth in `yyMMdd` format (DG1).
- `dateOfBirthCheckDigit`: The check digit for the date of birth; `<` when unset.
- `dateOfExpiry`: The document expiry date in `yyMMdd` format (DG1).
- `dateOfExpiryCheckDigit`: The check digit for the expiration date; `<` when unset.
- `documentCode`: The MRZ document code. One of the following: `TD1`, `TD2`, `TD3`, `MRVA`, or `MRVB`. The default is `TD3`.
- `documentNumber`: The 9 most-significant digits of the document number.
- `documentNumberCheckDigit`: The check digit for the document number; `<` when unset.
- `gender`: The document holder's gender. One of the following: `MALE`, `FEMALE`, `UNKNOWN`, or `UNSPECIFIED`.
- `issuingStateOrOrganization`: The issuing state or organization as a 3-letter code.
- `nationality`: The document holder's nationality as a 3-letter code.
- `optionalData1`: First optional data field (ID-1 and ID-3 style MRZs).
- `optionalData2`: Second optional data field (ID-1 style MRZs only); may be `null`.
- `personalNumber`: Personal number, if encoded in `optionalData1`.
- `personalNumberCheckDigit`: The check digit for the personal number (TD3 only); may be `null`.
- `primaryIdentifier`: The document holder's last name.
- `secondaryIdentifier`: The document holder's first name.
- `secondaryIdentifierComponents`: The secondary identifier split into its individual components.
- `dg1EncodedData`: The Base64-encoded string of the entire MRZ (DG1).
- `faceBitmap`: The document holder's face image decoded from the chip (DG2); `null` when unavailable.
- `dg2EncodedData`: The Base64-encoded DG2 (encoded face features); `null` when unavailable.
- `sodEncodedData`: The Base64-encoded Document Security Object (SOD); `null` when unavailable.
- Fields inherited from `BaseResult`:
  - `resultCode`: The `ResultCode` for this result.
  - `error`: When `resultCode` is `ERROR`, the `Throwable` that caused it; otherwise, `null`.
  - `deviceStats`: The `DeviceStats` snapshot of the device state when the result was produced.
  - `motionStatus`: Device motion assessment during capture. One of the following:
    - `UNCLEAR`: Motion could not be determined; the default.
    - `PASS`: Device motion was within acceptable limits.
    - `FAIL`: Excessive device motion was detected.

Errors surface through `OnboardingListener.onError(Throwable)`. If the `nfc` library dependency is missing when this module runs, the SDK delivers a `MissingNfcDependencyException` to that callback.

For the authoritative field definitions, see `NfcScanResult` in [API Reference](https://developer.incode.com/docs/android-api-reference).
