【问题标题】:Android smart-card interface over USB通过 USB 的 Android 智能卡接口
【发布时间】:2017-11-10 02:22:52
【问题描述】:

我需要使用通过 USB 连接到 Android 手机的智能卡读卡器读取/写入智能卡。 原生 API 可以做到这一点,还是我必须安装其他库?

谢谢

【问题讨论】:

    标签: android usb smartcard


    【解决方案1】:

    在 java 中,使用包 javax.smarcard 进行通信,该包不适用于 Android,因此请使用 look here 了解如何通信或发送/接收 APDU(智能卡命令)。

    使用 USB Host API 连接: :

    //Allows you to enumerate and communicate with connected USB devices.
    UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
    //Explicitly asking for permission
    final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
    PendingIntent mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
    HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
    
    UsbDevice device = deviceList.get("//the device you want to work with");
    if (device != null) {
        mUsbManager.requestPermission(device, mPermissionIntent);
    }
    

    现在您将需要端点,只需通过批量输出端点发送 APDU(智能卡命令)并期望通过批量输入端点接收响应 APDU。

    获取端点的代码 ::

    UsbEndpoint epOut = null, epIn = null;
    UsbInterface usbInterface;
    
    UsbDeviceConnection connection = mUsbManager.openDevice(device);
    
        for (int i = 0; i < device.getInterfaceCount(); i++) {
            usbInterface = device.getInterface(i);
            connection.claimInterface(usbInterface, true);
    
            for (int j = 0; j < usbInterface.getEndpointCount(); j++) {
                UsbEndpoint ep = usbInterface.getEndpoint(j);
    
                if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                    if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
                        // from host to device
                        epOut = ep;
    
                    } else if (ep.getDirection() == UsbConstants.USB_DIR_IN) {
                        // from device to host
                        epIn = ep;
                    }
                }
            }
        }
    

    要发送命令,请使用:

    public void write(UsbDeviceConnection connection, UsbEndpoint epOut, byte[] command) {
    result = new StringBuilder();
    connection.bulkTransfer(epOut, command, command.length, TIMEOUT);
    //For Printing logs you can use result variable
    for (byte bb : command) {
        result.append(String.format(" %02X ", bb));
    }
    }
    

    要读取数据或发送二进制读取,您可以使用以下代码:

    public int read(UsbDeviceConnection connection, UsbEndpoint epIn) {
    result = new StringBuilder();
    final byte[] buffer = new byte[epIn.getMaxPacketSize()];
    int byteCount = 0;
    byteCount = connection.bulkTransfer(epIn, buffer, buffer.length, TIMEOUT);
    //For Printing logs you can use result variable
    if (byteCount >= 0) {
        for (byte bb : buffer) {
            result.append(String.format(" %02X ", bb));
        }
    
        //Buffer received was : result.toString()
    } else {
        //Something went wrong as count was : " + byteCount
    }
    
    return byteCount;
    }
    

    现在让我们以这个命令为例:62000000000000000000 你如何发送这个是:

    write(connection, epOut, "62000000000000000000");
    

    现在,在您成功发送 APDU 命令后,您可以使用以下命令读取响应:

    read(connection, epIn);
    

    并收到类似的东西

    80 18000000 00 00 00 00 00 3BBF11008131FE45455041000000000000000000000000F1
    

    现在代码中收到的响应将在read()方法的结果变量中。同样您可以编写自己的通信命令。

    【讨论】:

      【解决方案2】:

      遗憾的是,原生 Android 系统中没有像 PC/SC 这样的抽象层。但是您可以使用Android USB library 直接与 USB 智能卡读卡器对话。

      【讨论】:

      • 其实我需要通过USB将读卡器直接连接到手机上,因为我没有PC或其他任何东西,只有Android手机和读卡器。
      • 而且我还需要支持没有NFC的手机
      • 等等,您的意思是要将 USB 智能卡读卡器连接到 Android 手机?
      • 是的。 SC & Droid 有一个应用程序支持这个,但他们不提供代码
      • 但是由于智能卡读卡器设备主要属于CCID USB类,我是否必须通过UBS库实现这个协议?
      猜你喜欢
      • 2017-04-19
      • 1970-01-01
      • 2012-12-22
      • 2012-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多