使用 HCE 将位图从一个设备传输到另一个设备 (Android 4.4+)
transfering bitmap from one device to another (Android 4.4+) using HCE
我正在尝试使用 HCE 将图像从一台设备发送到另一台设备(一台设备处于卡模拟模式,另一台设备处于 reader 模式)。我可以发送字符串但不能发送图像。在 reader 方面,我总是将 TAG 作为 null
.
非常感谢您的帮助,在此先致谢。
HCE 端(标签side/sender):
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;
}
Reader 模式应用 (reader side/receiver):
@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;
}
}
您在实施模拟 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
(见下)!
您使用的 NDEF 消息大于映射版本 2.0 的 Type 4 标签的最大可能 NDEF 大小。由于 READ BINARY 命令的格式,可在类型 4 标签(映射版本 2.0)上寻址的 NDEF 消息的最大大小为 33022 字节(0x80FE
)。因此,此标记类型不支持您的 NDEF 消息。
您应该期望 reader 仅读取功能容器文件的部分内容(与您对 NDEF 文件所做的方式类似)。目前,您只允许偏移量为 0 且长度为 0x0F 的读取操作。
如果 READ BINARY 命令失败,Return 正确的状态字(当前您 return "file not found")。
即使没有 Le 字段,您也可能想要接受 SELECT(通过 AID)命令。
我正在尝试使用 HCE 将图像从一台设备发送到另一台设备(一台设备处于卡模拟模式,另一台设备处于 reader 模式)。我可以发送字符串但不能发送图像。在 reader 方面,我总是将 TAG 作为 null
.
非常感谢您的帮助,在此先致谢。
HCE 端(标签side/sender):
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;
}
Reader 模式应用 (reader side/receiver):
@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;
}
}
您在实施模拟 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
(见下)!您使用的 NDEF 消息大于映射版本 2.0 的 Type 4 标签的最大可能 NDEF 大小。由于 READ BINARY 命令的格式,可在类型 4 标签(映射版本 2.0)上寻址的 NDEF 消息的最大大小为 33022 字节(
0x80FE
)。因此,此标记类型不支持您的 NDEF 消息。您应该期望 reader 仅读取功能容器文件的部分内容(与您对 NDEF 文件所做的方式类似)。目前,您只允许偏移量为 0 且长度为 0x0F 的读取操作。
如果 READ BINARY 命令失败,Return 正确的状态字(当前您 return "file not found")。
即使没有 Le 字段,您也可能想要接受 SELECT(通过 AID)命令。