перенос растрового изображения с одного устройства на другое (Android 4.4+) с использованием HCE

Я пытаюсь отправить изображение с одного устройства на другое с помощью 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;
    }
   }

person user2203    schedule 16.04.2015    source источник
comment
Если вы получаете TAG как null, вы можете получить исключение Null Pointer Exception, опубликуйте трассировку Log Cat.   -  person Keshav1234    schedule 16.04.2015
comment
Можно использовать только NFC. HCE для других целей.   -  person ADK    schedule 16.04.2015
comment
Какой код вы используете для отправки изображения на стороне HCE? Какой код вы используете для получения изображения на стороне считывателя?   -  person Michael Roland    schedule 16.04.2015
comment
@MichaelRoland, я обновил код! Будем признательны за любую помощь. Заранее спасибо!   -  person user2203    schedule 20.04.2015
comment
Каковы значения полей SELECT_*, *_FILE, *_SW?   -  person Michael Roland    schedule 20.04.2015
comment
привет @MichaelRoland, я обновил свой вопрос, указанное выше значение я использую   -  person user2203    schedule 20.04.2015
comment
Не могли бы вы также опубликовать значение, которое вы получили для nlen в int nlen = ndefMessage.getByteArrayLength();?   -  person Michael Roland    schedule 21.04.2015
comment
@MichaelRoland nlen int nlen = ndefMessage.getByteArrayLength(); значение 164906   -  person user2203    schedule 21.04.2015


Ответы (1)


Есть несколько проблем с вашей реализацией эмулируемого тега типа 4:

  1. Контейнер возможностей определяет максимальный размер файла 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. Вы используете сообщение NDEF, размер которого превышает максимально возможный размер NDEF для тега типа 4 с версией сопоставления 2.0. Максимальный размер сообщения NDEF, адресуемого тегом типа 4 (версия сопоставления 2.0), составляет 33022 байта (0x80FE) из-за формата команды READ BINARY. Следовательно, ваше сообщение NDEF не поддерживается для этого типа тега.

  3. Вы должны ожидать, что читатель будет читать только части файла контейнера возможностей (так же, как вы делаете это для файла NDEF). В настоящее время вы разрешаете только операции чтения со смещением 0 и длиной 0x0F).

  4. Верните правильные слова состояния, если команда READ BINARY не удалась (в настоящее время вы возвращаете «файл не найден»).

  5. Возможно, вы захотите принять команду SELECT (по AID), даже если поле Le отсутствует.

person Michael Roland    schedule 22.04.2015