You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter应用调用NFC标签transceive方法触发NoSuchMethodError问题

问题:使用nfc_manager读取NFC标签时出现NoSuchMethodError错误

读取NFC标签时触发如下错误:

Error reading data: NoSuchMethodError: Class '_Map<Object?, Object?>' has no instance method 'transceive'.
Receiver: _Map len:5
Tried calling: transceive(_Uint8List)

相关代码如下:

nfc_service.dart

import 'dart:typed_data';
import 'dart:convert';
import 'package:nfc_manager/nfc_manager.dart';
import 'package:nfc_manager/platform_tags.dart'; // Ensure this import is included

class NfcService {
  Future<String> readData(NfcTag tag) async {
    try {
      // Print the contents of tag.data for debugging
      print('!!!!!!!!!!!!! TAG DATA: ${tag.data}');

      // Extract NFC-A data from the tag
      final nfcaData = tag.data['nfca'];

      // Print the type and contents of nfcaData for debugging
      print('QQQQQQ nfcaData type: ${nfcaData.runtimeType}');
      print('MMMMMM nfcaData contents: $nfcaData');

      if (nfcaData != null) {
        // Create NfcA instance from the tag
        final nfca = NfcA.from(tag);

        // Check if nfca is not null
        if (nfca != null) {
          // Prepare the command to read data from the tag
          final command = Uint8List.fromList(
              [0x3A, 0x00, 0x01]); // Example command for reading

          // Call transceive method with the command
          final result = await nfca.transceive(data: command);

          // Print raw result for debugging
          print('Raw result (Uint8List): $result');

          // Attempt to decode the result using UTF-8
          String resultText;
          try {
            resultText = utf8.decode(result, allowMalformed: true);
          } catch (e) {
            resultText =
                'Failed to decode text: ${result.toString()}'; // Show raw result if decoding fails
          }

          return resultText;
        } else {
          return 'NfcA instance could not be created';
        }
      } else {
        return 'Unsupported NFC tag type or no NFC-A data';
      }
    } catch (e, s) {
      print('SSSSSS Stack trace:\n$s');
      return 'Error reading data: $e';
    }
  }
}

scan_page.dart

import 'package:flutter/material.dart';
import 'package:nfc_manager/nfc_manager.dart';
import 'package:soremar_inventory/services/nfc_service.dart';

class ScanTagPage extends StatefulWidget {
  const ScanTagPage({super.key});

  @override
  ScanTagPageState createState() => ScanTagPageState();
}

class ScanTagPageState extends State<ScanTagPage> {
  final NfcService _nfcService = NfcService();
  bool _isScanning = false;
  String _scanMessage =
      'Placez votre téléphone près de l\'étiquette NFC pour scanner.';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Controller un produit'),
        centerTitle: true,
        backgroundColor: const Color.fromARGB(255, 42, 48, 161),
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () {
            Navigator.of(context).pop();
          },
        ),
      ),
      body: Stack(
        children: [
          // Background GIF
          Positioned.fill(
            child: Image.asset(
              'assets/images/scan.gif', // Ensure the path is correct
              fit: BoxFit.cover,
            ),
          ),
          // Foreground content
          Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                ElevatedButton(
                  onPressed: _startScan,
                  child: const Text('Cliquez ici pour scanner une tag NFC'),
                ),
                if (_isScanning) const CircularProgressIndicator(),
                Text(_scanMessage),
              ],
            ),
          ),
        ],
      ),
    );
  }

  void _startScan() async {
    if (_isScanning) return; // Prevent starting multiple scans

    setState(() {
      _isScanning = true;
      _scanMessage =
          'Placez votre téléphone près de l\'étiquette NFC pour scanner.';
    });

    try {
      await NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
        final data = await _nfcService.readData(tag);
        setState(() {
          _scanMessage = 'Data: $data';
        });
        _stopScan(); // Stop scan after reading data
      }).catchError((e) {
        setState(() {
          _scanMessage = 'Error: $e';
        });
        _stopScan(); // Ensure the session is stopped on error
      });
    } catch (e) {
      setState(() {
        _scanMessage = 'Error: $e';
      });
      _stopScan(); // Ensure the session is stopped on error
    }
  }

  void _stopScan() {
    NfcManager.instance.stopSession().catchError((e) {
      print('Error stopping NFC session: $e');
    });
    setState(() {
      _isScanning = false;
    });
  }
}

问题分析

错误核心是代码尝试调用_Map对象的transceive方法,但该方法仅存在于NfcA实例中。出现此问题的可能原因:

  1. NfcA.from(tag)未正确返回NfcA实例,可能是标签不支持NfcA协议,或依赖包版本存在兼容性问题
  2. 直接依赖tag.data['nfca']的存在性,未通过官方API验证标签协议支持性
  3. NFC指令不匹配目标标签的通信规范,导致底层调用异常

解决方案

1. 严格验证标签协议支持性

使用NfcA.isSupported(tag)替代直接判断tag.data['nfca'],确保标签确实支持NfcA协议:

// 替换原nfcaData判断逻辑
if (NfcA.isSupported(tag)) {
  final nfca = NfcA.from(tag);
  if (nfca != null) {
    // 执行后续读取操作
  } else {
    return '无法初始化NfcA实例';
  }
} else {
  return '该NFC标签不支持NfcA协议';
}

2. 更新nfc_manager依赖到最新稳定版

旧版本可能存在NfcA.from(tag)返回值异常问题,在pubspec.yaml中更新依赖:

dependencies:
  nfc_manager: ^最新稳定版本号

执行flutter pub get完成更新。

3. 修正NFC指令适配目标标签

当前使用的[0x3A, 0x00, 0x01]可能不符合目标标签的通信规范,建议先执行标签选中指令(如ISO7816标准的选择指令),再执行读取操作:

// 先发送标签选中指令
final selectCommand = Uint8List.fromList([0x00, 0xA4, 0x04, 0x00, 0x00]);
await nfca.transceive(data: selectCommand);

// 再发送读取指令(根据标签文档调整)
final readCommand = Uint8List.fromList([0x3A, 0x00, 0x01]);
final result = await nfca.transceive(data: readCommand);

4. 完善平台权限配置

确保Android和iOS的NFC权限配置正确:

  • Android:在AndroidManifest.xml中添加
    <uses-permission android:name="android.permission.NFC" />
    <uses-feature android:name="android.hardware.nfc" android:required="true" />
    
  • iOS:在Info.plist中添加
    <key>NFCReaderUsageDescription</key>
    <string>需要访问NFC功能以读取标签数据</string>
    <key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
    <array>
      <string>A0000002471001</string> <!-- 根据标签AID调整 -->
    </array>
    

内容的提问来源于stack exchange,提问作者Mohammed Elyaakoubi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 06:37:07