Flutter智能卡读写插件flutter_pcsc_linux的使用

Flutter智能卡读写插件flutter_pcsc_linux的使用

flutter_pcsc_linuxflutter_pcsc 插件在 Linux 平台上的实现。它允许开发者在 Flutter 应用中读取和写入智能卡。

使用方法

该插件被官方推荐使用(通过 endorsed federated plugin),这意味着你可以直接使用 flutter_pcsc,而这个包会在你的应用中自动包含 flutter_pcsc_linux

示例代码

以下是一个完整的示例代码,展示了如何使用 flutter_pcsc_linux 插件来读取智能卡的序列号。

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_pcsc_linux/flutter_pcsc_linux.dart';
import 'dart:async';

import 'package:flutter_pcsc_platform_interface/flutter_pcsc_platform_interface.dart';

void main() {
  MyApp? myApp;

  runZonedGuarded(() async {
    PcscLinux.registerWith(); // 注册插件
    WidgetsFlutterBinding.ensureInitialized(); // 确保初始化
    FlutterError.onError = (FlutterErrorDetails details) {
      FlutterError.dumpErrorToConsole(details); // 错误处理
      myApp?.addError(details.toString());
    };

    runApp(myApp = MyApp());
  }, (Object error, StackTrace stack) {
    print(error.toString()); // 打印错误信息
    myApp?.addError(error.toString());
  });
}

class MyApp extends StatelessWidget {
  final GlobalKey<_MyAppBodyState> _myAppKey = GlobalKey();

  MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: const Text('智能卡读写插件示例'),
          ),
          body: MyAppBody(key: _myAppKey)),
    );
  }

  void addError(String msg) {
    _myAppKey.currentState?.addMessage(Message.error(msg));
  }
}

class MyAppBody extends StatefulWidget {
  const MyAppBody({required Key key}) : super(key: key);

  [@override](/user/override)
  _MyAppBodyState createState() {
    return _MyAppBodyState();
  }
}

// 消息类型
enum MessageType { info, error }

class Message {
  final String content;
  final MessageType type;
  Message(this.type, this.content);

  static info(String content) {
    return Message(MessageType.info, content);
  }

  static error(String content) {
    return Message(MessageType.error, content);
  }
}

class _MyAppBodyState extends State<MyAppBody> {
  static const List<int> getCardSerialNumberCommand = [0xFF, 0xCA, 0x00, 0x00, 0x00]; // 获取序列号命令
  final ScrollController _scrollController = ScrollController();

  final List<Message> _messages = [];

  [@override](/user/override)
  void initState() {
    super.initState();
    getCardSerialNumber();
  }

  void addMessage(Message m) {
    setState(() {
      _messages.add(m);
    });
  }

  Future<void> getCardSerialNumber() async {
    int ctx = await PcscPlatform.instance
        .establishContext(PcscConstants.CARD_SCOPE_USER); // 建立上下文
    Map<String, dynamic>? card;
    try {
      List<String> readers = await PcscPlatform.instance.listReaders(ctx); // 列出读卡器

      if (readers.isEmpty) {
        setState(() {
          _messages.add(Message.error('未检测到任何读卡器'));
        });
      } else {
        String reader = readers[0];
        setState(() {
          _messages.add(Message.info('使用读卡器: $reader'));
        });

        card = await PcscPlatform.instance.cardConnect(ctx, reader,
            PcscConstants.SCARD_SHARE_SHARED, PcscConstants.SCARD_PROTOCOL_ANY); // 连接卡片
        var response = await PcscPlatform.instance.transmit(card['h_card'],
            card['active_protocol'], getCardSerialNumberCommand); // 发送获取序列号命令
        var sw = response.sublist(response.length - 2);
        var sn = response.sublist(0, response.length - 2);

        if (sw[0] != 0x90 || sw[1] != 0x00) {
          setState(() {
            _messages.add(Message.error('卡片返回错误: ${hexDump(sw)}'));
          });
        } else {
          setState(() {
            _messages
                .add(Message.info('卡片序列号是: ${hexDump(sn)}'));
            _messages.add(Message.info('完成'));
          });
        }
      }
    } finally {
      if (card != null) {
        try {
          await PcscPlatform.instance
              .cardDisconnect(card['h_card'], PcscConstants.SCARD_RESET_CARD); // 断开卡片连接
        } on Exception catch (e) {
          setState(() {
            _messages.add(Message.error(e.toString()));
          });
        }
      }
      try {
        await PcscPlatform.instance.releaseContext(ctx); // 释放上下文
      } on Exception catch (e) {
        setState(() {
          _messages.add(Message.error(e.toString()));
        });
      }
    }
  }

  static String hexDump(List<int> csn) {
    return csn
        .map((i) => i.toRadixString(16).padLeft(2, '0').toUpperCase()) // 转换为十六进制字符串
        .join(' ');
  }

  _scrollToBottom() {
    _scrollController.jumpTo(_scrollController.position.maxScrollExtent); // 滚动到底部
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    TextStyle errorStyle = const TextStyle(color: Colors.red);
    WidgetsBinding.instance?.addPostFrameCallback((_) => _scrollToBottom());
    return Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
      Expanded(
          child: Column(children: [
        Expanded(
            child: ListView(
                controller: _scrollController,
                children: _messages
                    .map((e) => Text(e.content,
                        style: e.type == MessageType.error ? errorStyle : null)) // 显示消息
                    .toList())),
        Container(
            margin: const EdgeInsets.all(10),
            child: ElevatedButton(
                onPressed: () async {
                  await tryAgain();
                },
                child: const Text("重新尝试")))
      ]))
    ]);
  }

  tryAgain() async {
    setState(() {
      _messages.clear();
    });
    await getCardSerialNumber(); // 重新尝试读取序列号
  }
}

更多关于Flutter智能卡读写插件flutter_pcsc_linux的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter智能卡读写插件flutter_pcsc_linux的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


flutter_pcsc_linux 是一个用于在 Linux 平台上通过 PC/SC 接口读写智能卡(Smart Card)的 Flutter 插件。它允许你在 Flutter 应用程序中与智能卡进行交互,例如读取卡数据、写入数据、发送 APDU 命令等。

以下是如何使用 flutter_pcsc_linux 插件的基本步骤:

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 flutter_pcsc_linux 依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_pcsc_linux: ^0.1.0  # 请检查最新版本

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

2. 导入插件

在你的 Dart 文件中导入插件:

import 'package:flutter_pcsc_linux/flutter_pcsc_linux.dart';

3. 初始化 PC/SC 上下文

在使用插件之前,你需要初始化 PC/SC 上下文:

final pcsc = FlutterPcscLinux();
await pcsc.initializeContext();

4. 列出可用的读卡器

你可以列出系统中可用的智能卡读卡器:

final readers = await pcsc.listReaders();
print('Available readers: $readers');

5. 连接到读卡器

选择一个读卡器并连接到它:

final reader = readers.first;  // 选择第一个读卡器
await pcsc.connect(reader);

6. 发送 APDU 命令

你可以通过发送 APDU 命令与智能卡进行交互。例如,发送一个简单的 SELECT 命令:

final command = [0x00, 0xA4, 0x04, 0x00, 0x00];  // SELECT 命令
final response = await pcsc.transmit(command);
print('Response: $response');

7. 断开连接并释放资源

完成操作后,断开与读卡器的连接并释放资源:

await pcsc.disconnect();
await pcsc.releaseContext();

8. 处理错误

在实际使用中,可能会遇到各种错误,例如读卡器不可用、智能卡未插入等。你应该适当地处理这些错误:

try {
  await pcsc.connect(reader);
} catch (e) {
  print('Failed to connect to reader: $e');
}

9. 完整的示例代码

以下是一个完整的示例代码,展示了如何使用 flutter_pcsc_linux 插件与智能卡进行交互:

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  final pcsc = FlutterPcscLinux();
  try {
    await pcsc.initializeContext();
    final readers = await pcsc.listReaders();
    print('Available readers: $readers');
    
    if (readers.isNotEmpty) {
      final reader = readers.first;
      await pcsc.connect(reader);
      
      final command = [0x00, 0xA4, 0x04, 0x00, 0x00];  // SELECT 命令
      final response = await pcsc.transmit(command);
      print('Response: $response');
      
      await pcsc.disconnect();
    } else {
      print('No readers available');
    }
  } catch (e) {
    print('Error: $e');
  } finally {
    await pcsc.releaseContext();
  }
  
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter PC/SC Linux Example'),
        ),
        body: Center(
          child: Text('Check the console for output'),
        ),
      ),
    );
  }
}
回到顶部