我正在尝试使用HCE将图像从一个设备发送到另一个设备(一个设备处于卡仿真模式,另一个设备处于读卡器模式)。我能够发送一个字符串,但不能发送图像。在读者方面,我总是将TAG作为null
。
非常感谢你的帮助,谢谢。
HCE方(标签方/发件人):
private final static byte[] SELECT_APP = new byte[] { (byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xd2, (byte)0x76, (byte)0x00, (byte)0x00, (byte)0x85, (byte)0x01, (byte)0x01, (byte)0x00, };
private final static byte[] SELECT_CC_FILE = new byte[] { (byte)0x00, (byte)0xa4, (byte)0x00, (byte)0x0c, (byte)0x02, (byte)0xe1, (byte)0x03, };
private final static byte[] SELECT_NDEF_FILE = new byte[] { (byte)0x00, (byte)0xa4, (byte)0x00, (byte)0x0c, (byte)0x02, (byte)0xe1, (byte)0x04, };
private final static byte[] SUCCESS_SW = new byte[] { (byte)0x90, (byte)0x00, };
private final static byte[] FAILURE_SW = new byte[] { (byte)0x6a, (byte)0x82, };
private final static byte[] CC_FILE = new byte[] {
0x00, 0x0f, // CCLEN
0x20, // Mapping Version
0x00, 0x3b, // Maximum R-APDU data size
0x00, 0x34, // Maximum C-APDU data size
0x04, 0x06, // Tag & Length
(byte)0xe1, 0x04, // NDEF File Identifier
0x00, 0x32, // Maximum NDEF size
0x00, // NDEF file read access granted
(byte)0xff, // NDEF File write access denied
};
public void onCreate() {
super.onCreate();
mAppSelected = false;
mCcSelected = false;
mNdefSelected = false;
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.transferimage1);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
mBitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream);
byte[] byteArray = stream.toByteArray();
NdefRecord picRecord = NdefRecord.createMime("image/jpeg", byteArray);
NdefMessage ndefMessage = new NdefMessage(new NdefRecord[] { picRecord });
int nlen = ndefMessage.getByteArrayLength(); // <- this is 164906
mNdefRecordFile = new byte[nlen + 2];
mNdefRecordFile[0] = (byte)((nlen & 0xff00) / 256);
mNdefRecordFile[1] = (byte)(nlen & 0xff);
System.arraycopy(ndefMessage.toByteArray(), 0, mNdefRecordFile, 2, ndefMessage.getByteArrayLength());
}
@Override
public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
if (Arrays.equals(SELECT_APP, commandApdu)) {
mAppSelected = true;
mCcSelected = false;
mNdefSelected = false;
return SUCCESS_SW;
} else if (mAppSelected && Arrays.equals(SELECT_CC_FILE, commandApdu)) {
mCcSelected = true;
mNdefSelected = false;
return SUCCESS_SW;
} else if (mAppSelected && Arrays.equals(SELECT_NDEF_FILE, commandApdu)) {
mCcSelected = false;
mNdefSelected = true;
return SUCCESS_SW;
} else if (commandApdu[0] == (byte)0x00 && commandApdu[1] == (byte)0xb0) {
int offset = (0x00ff & commandApdu[2]) * 256 + (0x00ff & commandApdu[3]);
int le = 0x00ff & commandApdu[4];
byte[] responseApdu = new byte[le + SUCCESS_SW.length];
if (mCcSelected && offset == 0 && le == CC_FILE.length) {
System.arraycopy(CC_FILE, offset, responseApdu, 0, le);
System.arraycopy(SUCCESS_SW, 0, responseApdu, le, SUCCESS_SW.length);
return responseApdu;
} else if (mNdefSelected) {
if (offset + le <= mNdefRecordFile.length) {
System.arraycopy(mNdefRecordFile, offset, responseApdu, 0, le);
System.arraycopy(SUCCESS_SW, 0, responseApdu, le, SUCCESS_SW.length);
return responseApdu;
}
}
}
return FAILURE_SW;
}
@Override
public void onDeactivated(int reason) {
mAppSelected = false;
mCcSelected = false;
mNdefSelected = false;
}
阅读器模式应用(阅读器端/接收器):
@Override
public void onTagDiscovered(Tag tag) {
Ndef ndef = Ndef.get(tag); // <- this returns null
NdefMessage message;
if (ndef != null) {
message = ndef.getCachedNdefMessage(); // <- cannot get NDEF message as ndef is null
} else {
return;
}
}
答案 0 :(得分:0)
您对模拟Type 4标记的实现存在一些问题:
功能容器将NDEF文件的最大大小定义为50个字节(0x00, 0x32
)。但是,您在NDEF文件中使用的实际长度值(前两个字节)要大得多:
int nlen = ndefMessage.getByteArrayLength(); // -> 164906
mNdefRecordFile[0] = (byte)((nlen & 0xff00) / 256); // -> 0x84
mNdefRecordFile[1] = (byte)(nlen & 0xff); // -> 0x2A
请注意,实际长度会被截断为0x842A
(参见下一个)!
对于映射版本为2.0的Type 4标记,使用大于最大可能NDEF大小的NDEF消息。由于READ BINARY命令的格式,在Type 4标记(映射版本2.0)上可寻址的NDEF消息的最大大小为33022字节(0x80FE
)。因此,此标记类型不支持您的NDEF消息。
您应该期望读者只读取功能容器文件的一部分(与NDEF文件的方式类似)。目前,您只允许偏移量为0且长度为0x0F的读取操作。
如果READ BINARY命令失败(当前返回“找不到文件”),则返回正确的状态字。
即使没有Le字段,您也可能希望接受SELECT(按AID)命令。