Reputation: 21
I need to read/write to a smart-card using a smart-card reader attached to an Android phone by USB. Is this possible with native APIs or do I have to install other libraries?
Thank you
Upvotes: 2
Views: 6211
Reputation: 2252
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.
Upvotes: 2
Reputation: 2093
Sadly there is no abstraction layer like PC/SC
in the native Android system. But you can utilize Android USB library to talk directly to the USB smart card reader.
Upvotes: 1