通过USB的Android智能卡接口

时间:2017-06-08 11:32:00

标签: android usb smartcard

我需要使用通过USB连接到Android手机的智能卡读卡器来读/写智能卡。 这可能是使用本机API还是我必须安装其他库?

谢谢

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

In java the communication takes place using package javax.smarcard which is not available for Android so take a look here for getting an idea as to how you can communicate or send/receive APDU (smartcard command).

Using the USB Host API to connect : :

//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);
}

And now you will need endpoints, simply send an APDU (smartcard command) over the bulk-out endpoint and expect to receive a response APDU over the bulk-in endpoint.

Code to get endpoints ::

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;
                }
            }
        }
    }

To send commands use this :

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));
}
}

And to read data or send binary read you can use this code:

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;
}

Now let's take an example of this command like the one here: 62000000000000000000 How you can send this is :

write(connection, epOut, "62000000000000000000");

Now after you have successfully sent the APDU command, you can read the response using :

read(connection, epIn);

And receive something like

80 18000000 00 00 00 00 00 3BBF11008131FE45455041000000000000000000000000F1

Now the response received in the code here will be in the result variable of read() method.And likewise you can write your own commands for communicating.