Flutter NFC经典Mifare卡操作插件nfc_classic_mifare的使用

Flutter NFC经典Mifare卡操作插件nfc_classic_mifare的使用

说明

这是一个用于Android的Flutter插件,用于读取和写入NFC卡片。本插件仅支持Mifare Classic卡,并且仅限于NfcA技术。此外,它仅在默认密码的情况下工作。

注意事项

  • 仅支持Mifare Classic卡。
  • 仅支持NfcA技术。
  • 仅在默认密码的情况下工作。

设置

  • 要求Android API级别为19或更高版本。
  • AndroidManifest.xml文件中添加权限<uses-permission android:name="android.permission.NFC" />

注意点

  • 记住不要在任何卡的扇区0中写入数据。
  • 如果在任何扇区的第4个块中写入数据,请记录下你写入的内容,因为这是新的密码,用于读取和写入该扇区的数据。
  • 密码参数在所有情况下都是可选的,只有在扇区有自定义密码时才需要。

感谢

此插件基于Andres Maldonado的原始包mifare_nfc_classichttps://github.com/MaldonadoAndres/mifare_nfc_classic/)。遗憾的是,我的拉取请求尚未集成Null Safety功能,所以我发布了自己的分支并使用了新的包名。

使用方法

检查NFC可用性
// 检查NFC是否可用
AVAILABILITY isAvailable = await NfcClassicMifare.availability;

switch(isAvailable) {
  case(AVAILABILITY.AVAILABLE):
    // NFC已启用。
    break;
  case(AVAILABILITY.NOT_ENABLED):
    // 设备支持NFC但用户需要启用它。
    break;
  case(AVAILABILITY.NOT_SUPPORTED):
    // 设备不支持NFC。
    break;
}
获取扇区或块的数量
int _sectorCount = await NfcClassicMifare.sectorCount;
int _blockCount = await NfcClassicMifare.blockCount;
读取特定扇区
// 读取特定扇区
List<String> _sector = await NfcClassicMifare.readSector(sectorIndex: index, password: password);

/*
返回值示例:
[
  "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
  "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
  "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
  "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
]
*/
读取特定扇区内的特定块
// 读取特定扇区内的特定块
String _block = await NfcClassicMifare.readBlock(blockIndex: _blockIndex, password: password);

/*
返回值示例:
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
*/
读取卡片的所有扇区
// 读取卡片的所有扇区
List<List<String>> _card = await NfcClassicMifare.readAll(password: password);

/*
返回值示例:
[
  [
    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
  ],
  ...
  ...
  ...
  [
    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
  ]
]
*/

// 注意:此操作可能需要几秒钟时间,请保持卡片靠近手机至少2秒。
写入特定扇区内的特定块
// 写入特定扇区内的特定块
bool didWrite = await NfcClassicMifare.writeBlock(blockIndex: _blockIndex, message: _message, password: password);

/*
返回值示例:
didWrite 表示操作是否成功完成。
*/
更改扇区的密码
// 更改扇区的密码
await NfcClassicMifare.changePasswordOfSector(sectorIndex: _sectorIndex, newPassword: _newPassword, password: password);
写入原始十六进制数据
// 写入原始十六进制数据
await NfcClassicMifare.writeRawHexToBlock(blockIndex: _blockIndex, message: rawHex, password: password);

完整示例Demo

import 'package:flutter/material.dart';
import 'package:nfc_classic_mifare/nfc_classic_mifare.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  [@override](/user/override)
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final isAvailable = NfcClassicMifare.availability;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FutureBuilder(
        future: isAvailable,
        builder: (_, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            switch (snapshot.data) {
              case AVAILABILITY.AVAILABLE:
                return ExamplePage();
                break;
              case AVAILABILITY.NOT_ENABLED:
                return Scaffold(
                  body: Center(
                    child: Text('NFC Not Enabled.'),
                  ),
                );
                break;
              case AVAILABILITY.NOT_SUPPORTED:
                return Scaffold(
                  body: Center(
                    child: Text('NFC Not Supported.'),
                  ),
                );
                break;
              default:
                return Scaffold(
                  body: Center(
                    child: Text('How?'),
                  ),
                );
            }
          } else {
            return Container();
          }
        },
      ),
    );
  }
}

更多关于Flutter NFC经典Mifare卡操作插件nfc_classic_mifare的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter NFC经典Mifare卡操作插件nfc_classic_mifare的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何使用Flutter的nfc_classic_mifare插件来操作经典Mifare卡的代码示例。这个插件允许你读取和写入NFC Mifare经典卡的数据。

首先,你需要在你的pubspec.yaml文件中添加nfc_classic_mifare依赖:

dependencies:
  flutter:
    sdk: flutter
  nfc_classic_mifare: ^x.y.z  # 请替换为最新版本号

然后运行flutter pub get来获取依赖。

接下来,你可以在你的Flutter应用中使用这个插件。以下是一个简单的示例,展示如何读取和写入Mifare卡的数据。

import 'package:flutter/material.dart';
import 'package:nfc_classic_mifare/nfc_classic_mifare.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('NFC Mifare Classic Example'),
        ),
        body: NFCMifarePage(),
      ),
    );
  }
}

class NFCMifarePage extends StatefulWidget {
  @override
  _NFCMifarePageState createState() => _NFCMifarePageState();
}

class _NFCMifarePageState extends State<NFCMifarePage> {
  NfcClassicMifare? _nfcClassicMifare;
  String _status = 'Please tap your Mifare Classic card...';
  List<int>? _data;

  @override
  void initState() {
    super.initState();
    _nfcClassicMifare = NfcClassicMifare();
    _nfcClassicMifare!.onNfcCardDiscovered!.listen((NfcCard card) async {
      setState(() {
        _status = 'Card discovered: ${card.id}';
      });
      
      try {
        // 读取块数据
        int blockNumber = 4; // 示例块号,你可以根据需要修改
        List<int> blockData = await _nfcClassicMifare!.readBlock(blockNumber);
        setState(() {
          _data = blockData;
          _status = 'Block $blockNumber data: ${blockData.map((e) => e.toRadixString(16).padLeft(2, '0')).join(' ')}';
        });

        // 写入块数据
        List<int> newData = [0xAA, 0xBB, 0xCC, 0xDD]; // 示例数据,你可以根据需要修改
        await _nfcClassicMifare!.writeBlock(blockNumber, newData);
        setState(() {
          _status = 'Block $blockNumber written with: ${newData.map((e) => e.toRadixString(16).padLeft(2, '0')).join(' ')}';
        });

      } catch (e) {
        setState(() {
          _status = 'Error: $e';
        });
      }
    });

    _nfcClassicMifare!.startNfcDiscovery();
  }

  @override
  void dispose() {
    _nfcClassicMifare!.stopNfcDiscovery();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(_status, style: TextStyle(fontSize: 20)),
          if (_data != null)
            Text('Hex Data: ${_data!.map((e) => e.toRadixString(16).padLeft(2, '0')).join(' ')}',
                style: TextStyle(fontSize: 16)),
        ],
      ),
    );
  }
}

代码解释:

  1. 依赖添加:在pubspec.yaml中添加nfc_classic_mifare依赖。
  2. 初始化插件:在_NFCMifarePageStateinitState方法中初始化NfcClassicMifare对象,并监听onNfcCardDiscovered事件。
  3. NFC卡发现:当NFC卡被发现时,读取指定块的数据,并显示在UI上。然后写入新的数据到该块。
  4. UI更新:使用setState方法来更新UI以显示NFC卡的状态和数据。
  5. 资源清理:在dispose方法中停止NFC发现,以释放资源。

请注意,此示例代码仅用于演示目的,实际使用时你可能需要根据具体需求调整块号和读写数据。此外,确保你的设备和NFC卡支持所需的操作。

回到顶部