sdk_nfc_flutter

A Flutter plugin for the Au10tix NFC module SDK, providing seamless integration for NFC-enabled passport and ID document scanning with real-time status updates.

Features

  • Passport & ID NFC Scanning: Scan MRZ data and extract NFC chip information from passports and ID documents
  • Real-time Status Updates: Receive live status updates during the scanning process with camera view control
  • Camera View Integration: Embedded camera view with automatic hiding during authentication
  • Resume Functionality: Handle interrupted NFC scans and resume them seamlessly
  • Comprehensive Result Data: Get scanned images, cropped versions, and NFC verification status
  • Flexible UI Options: Use fullscreen UI or integrate with your own camera implementation

Installation

Add this to your package's pubspec.yaml file:

dependencies:
  sdk_nfc_flutter: ^4.7.0
  sdk_core_flutter: ^4.7.0

Android Setup

Permissions

Ensure your android/app/src/main/AndroidManifest.xml includes the necessary permissions:

<!-- NFC permissions -->
<uses-permission android:name="android.permission.NFC" />
<uses-feature 
    android:name="android.hardware.nfc"
    android:required="true" />

<!-- Camera permissions for MRZ reading -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature 
    android:name="android.hardware.camera"
    android:required="true" />

Dependencies

Add the Au10tix NFC SDK dependency to your android/app/build.gradle:

dependencies {
    implementation("com.au10tix.sdk:au10tix:4.6.1.3")
    implementation("com.au10tix.sdk:nfc:4.6.1.3")
    
    // Required for NFC functionality
    implementation("org.jmrtd:jmrtd:0.7.35")
    implementation("com.madgag.spongycastle:prov:1.58.0.0")
    implementation("net.sf.scuba:scuba-sc-android:0.0.23")
    
    // ML Kit for text recognition
    implementation("com.google.android.gms:play-services-mlkit-text-recognition:19.0.1")
}

Usage

Important: SDK Initialization

Before using any NFC functionality, you must initialize the Au10tix SDK:

import 'package:sdk_core_flutter/sdk_core_flutter.dart';

// Initialize once at app startup
await Au10tix.init(yourAuthToken);

The token is managed internally by the SDK and used automatically for all subsequent NFC operations. This is consistent across both Android and iOS platforms.

Basic Passport Scanning with Camera View

import 'package:sdk_nfc_flutter/sdk_nfc_flutter.dart';

class NFCPassportPage extends StatefulWidget {
  @override
  _NFCPassportPageState createState() => _NFCPassportPageState();
}

class _NFCPassportPageState extends State<NFCPassportPage> {
  Map? _scanResult;
  
  Future<void> _startNFCSession() async {
    try {
      final result = await SdkNfcFlutter.startSession(
        isPassport: true, // true for passport, false for ID cards
      );
      
      setState(() {
        _scanResult = result;
      });
      
      if (result != null && result['nfc'] != null) {
        print('NFC scan completed successfully');
        print('Status: ${result['nfc']['status']}');
        print('Image path: ${result['nfc']['imagePath']}');
      }
    } catch (e) {
      print('NFC session error: $e');
    }
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('NFC Passport Scanner')),
      body: Column(
        children: [
          // Camera view with NFC scanning capability
          if (_scanResult == null)
            Expanded(
              child: StreamBuilder<dynamic>(
                stream: SdkNfcFlutter.streamNfcUpdates(),
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return Column(
                      children: [
                        Expanded(child: Container()), // Your camera view here
                        Padding(
                          padding: EdgeInsets.all(16),
                          child: Text(
                            _getStatusText(snapshot.data),
                            style: TextStyle(fontSize: 18, color: Colors.white),
                            textAlign: TextAlign.center,
                          ),
                        ),
                      ],
                    );
                  }
                  return Center(child: Text('Ready to scan'));
                },
              ),
            ),
          
          // Action buttons
          Padding(
            padding: EdgeInsets.all(16),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ElevatedButton(
                  onPressed: _startNFCSession,
                  child: Text('Start Scanning'),
                ),
                if (_scanResult != null)
                  ElevatedButton(
                    onPressed: () {
                      setState(() {
                        _scanResult = null;
                      });
                      _startNFCSession();
                    },
                    child: Text('Scan Again'),
                  ),
              ],
            ),
          ),
        ],
      ),
    );
  }
  
  String _getStatusText(dynamic update) {
    if (update == null) return 'Ready to scan';
    
    final status = update['nfc']?['status'] ?? update['passport']?['status'] ?? 0;
    
    switch (status) {
      case 0: return 'Gathering MRZ fields';
      case 1: return 'Waiting for Passport';
      case 2: return 'Authenticating the Passport';
      case 3: return 'Extracting DG1';
      case 4: return 'Extracting DG2';
      case 5: return 'Extracting DG7';
      case 6: return 'Extracting DG11';
      case 7: return 'Extracting DG12';
      case 8: return 'Extracting DG13';
      case 9: return 'Authenticating the NFC chip';
      default: return 'Processing...';
    }
  }
}

Using Fullscreen UI

Future<void> _startFullscreenNFC() async {
  try {
    final result = await SdkNfcFlutter.startUI(
      isPassport: true,
      uiConfig: UIConfig(
        showIntroScreen: true,
        showCloseButton: true,
      ),
    );
    
    print('Fullscreen NFC result: $result');
  } catch (e) {
    print('Fullscreen NFC error: $e');
  }
}

Handling NFC Resume

Future<void> _resumeNFCScan() async {
  try {
    await SdkNfcFlutter.resumeNfcScan();
    print('NFC scan resumed successfully');
  } catch (e) {
    print('Failed to resume NFC scan: $e');
  }
}

API Reference

SdkNfcFlutter

Main class for interacting with the NFC SDK.

Static Methods

  • static Future<dynamic> startSession({bool isPassport = true}) - Start NFC scanning with camera preview
  • static Future<dynamic> startUI({UIConfig? uiConfig, bool isPassport = true}) - Start NFC scanning with fullscreen UI
  • static void stopSession() - Stop the current scanning session
  • static Future<dynamic> resumeNfcScan() - Resume an interrupted NFC scan
  • static Stream<dynamic> streamNfcUpdates() - Stream of real-time scanning updates

Status Updates

The plugin provides real-time status updates through streamNfcUpdates():

Status Codes

  • 0 - Gathering MRZ fields (camera scanning passport MRZ)
  • 1 - Waiting for Passport (ready for NFC tap)
  • 2 - Authenticating the Passport (camera view automatically hidden)
  • 3-8 - Extracting data groups (DG1, DG2, DG7, DG11, DG12, DG13)
  • 9 - Authenticating the NFC chip (final step)

Camera View Behavior

  • Visible: During MRZ scanning and NFC waiting phases
  • Hidden: Automatically hidden during authentication (status 2) for security
  • Icon Changes: Shows security icon during authentication, NFC icon otherwise

Result Structure

Successful scans return a Map with the following structure:

  'nfc': {
    'status': 200,
    'message': 'NFC scan completed successfully',
    'nfcScanned': true,
    'imagePath': '/path/to/captured/image.jpg',
    'croppedFilePath': '/path/to/cropped/image.jpg',
    // Additional NFC data fields
  }

Error Handling

The plugin handles various error conditions:

  • Feature Manager Creation Errors: Proper validation and error messages
  • NFC Resume Errors: Graceful handling of resume failures
  • Authentication Failures: Clear error reporting for failed authentications

Always wrap SDK calls in try-catch blocks:

try {
  final result = await SdkNfcFlutter.startSession(isPassport: true);
  // Handle success
} on PlatformException catch (e) {
  print('Platform error: ${e.code} - ${e.message}');
} catch (e) {
  print('General error: $e');
}

Requirements

  • Flutter 3.3.0 or higher
  • Android API level 24 or higher (Android 7.0+)
  • NFC-enabled Android device
  • Au10tix SDK license and configuration
  • Camera permissions for MRZ scanning
  • NFC permissions for chip reading

Configuration

UI Configuration

When using startUI(), you can customize the experience:

final uiConfig = UIConfig(
  showIntroScreen: true,     // Show introduction screen
  showCloseButton: true,     // Show close button in UI
);

Permissions Setup

Add to your android/app/src/main/AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- NFC permissions -->
    <uses-permission android:name="android.permission.NFC" />
    <uses-feature 
        android:name="android.hardware.nfc"
        android:required="true" />
    
    <!-- Camera permissions -->
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature 
        android:name="android.hardware.camera"
        android:required="true" />
    
    <application>
        <!-- Your app configuration -->
    </application>
</manifest>

Troubleshooting

Common Issues

  1. NullPointerException during UI launch

    • Ensure proper Au10tix SDK configuration
    • Check that all required dependencies are included
  2. Camera view not showing

    • Verify camera permissions are granted
    • Check that the device has a working camera
  3. NFC not working

    • Ensure device has NFC capability
    • Check that NFC is enabled in device settings
    • Verify NFC permissions are granted
  4. Authentication phase issues

    • Camera automatically hides during authentication (status 2)
    • This is expected behavior for security reasons

Support

This plugin is built on top of the Au10tix NFC SDK. For SDK-specific issues or licensing questions, please contact Au10tix support.

License

Please refer to your Au10tix SDK license agreement for usage terms and conditions.

Libraries

sdk_nfc_flutter