Russian Qt Forum

Qt => Qt Embedded => Тема начата: iLya84a от Июль 03, 2014, 13:11



Название: Qt Android NFC
Отправлено: iLya84a от Июль 03, 2014, 13:11
Сделал QML-приложение для чтения тэгов Mifare Classic 1K (http://www.nxp.com/documents/data_sheet/MF1S503x.pdf).
USB-считыватель - ACR122T USB Token NFC Reader (http://www.acs.com.hk/en/products/109/acr122t-usb-tokens-nfc-reader/)
Пришлось решить массу интересных вопросов:
  • низкоуровневая работа со считывателем
  • защита приложения от сворачивания
  • работа с нативной клавиатурой
С удовольствием отвечу на вопросы.

(https://pbs.twimg.com/media/BrmuomsCQAAAyhj.jpg:large)


Название: Re: Qt Android NFC
Отправлено: kuzulis от Июль 03, 2014, 14:39
Цитировать
низкоуровневая работа со считывателем

Вот здесь можно поподробнее? Каким образом делали это? :)


Название: Re: Qt Android NFC
Отправлено: iLya84a от Июль 04, 2014, 09:18
Цитировать
низкоуровневая работа со считывателем

Вот здесь можно поподробнее? Каким образом делали это? :)
Я использовал ACR122T USB Token NFC Reader. С другими моделями, думаю, всё аналогично.
0. Идем на страницу (http://www.acs.com.hk/en/products/109/acr122t-usb-tokens-nfc-reader/), выбираем закладку Downloads.
1. Скачиваем ACS-Unified-LIB-Android-111-P.zip (http://www.acs.com.hk/download-driver/2992/ACS-Unified-LIB-Android-111-P.zip)
2. Внутри находим справку \ACS-Unified-LIB-Android-111-P\acssmc\doc\index.html
3. После нескольких таблиц на этой странице видим заголовок Package com.acs.smartcard Description. Здесь начинается то, что нам нужно:
  • Opening Reader
  • Closing Reader
  • Resetting Card
  • Setting Protocol
  • Transmitting APDU (http://en.wikipedia.org/wiki/Smart_card_application_protocol_data_unit)
4. В этом же архиве находится готовый тестовый проект \ACS-Unified-LIB-Android-111-P\ReaderTest. Мне он здорово помог разобраться во всех базовых операциях из пункта 3.
5. Теперь нам нужно разобраться с APDU командами. Для этого скачиваем API Driver Manual of ACR122T NFC Contactless Smart Card Reader (http://www.acs.com.hk/download-manual/1264/API-ACR122T-2.02.pdf).
6. Мне нужно было считывать данные из памяти карт Mifare Classic 1K. Для этого мне пригодились пункты:
  • 5.1 Load Authentication Keys
  • 5.2 Authentication
  • 5.3 Read Binary Blocks
Вот и всё!
Код привести, к сожалению, не могу - проект коммерческий. Но еще подробнее, если где-то возникнут сложности, расскажу.


Название: Re: Qt Android NFC
Отправлено: kuzulis от Июль 06, 2014, 12:46
Эмм.. так код с "низкоуровневой" работой с ридером был на JAVA?


Название: Re: Qt Android NFC
Отправлено: iLya84a от Июль 07, 2014, 09:38
Эмм.. так код с "низкоуровневой" работой с ридером был на JAVA?
Согласен, слова "низкоуровневый" и JAVA в одном предложении выглядят странно  :)
Но вот пример команды аутентификации из пункта 5.2:
Код:
int slotNum = 0;
byte block = 0x3E;
byte[] command = { (byte)0xFF, (byte)0x86, 0x00, 0x00, 0x05, 0x01, 0x00, block , 0x60, 0x00 };
byte[] response = new byte[2];
reader.transmit(slotNum, command, command.length, response, response.length);
Тут без листания мануала никак не обойтись  :)


Название: Re: Qt Android NFC
Отправлено: Old от Июль 07, 2014, 09:44
Это да, поэтому числовые константы и заменяют текстовыми. :)


Название: Re: Qt Android NFC
Отправлено: kuzulis от Июль 07, 2014, 10:31
Цитировать
Согласен, слова "низкоуровневый" и JAVA в одном предложении выглядят странно 

Не, я не про то. Я про то, что раз приложение написано на Qt, значит использовался C++, поэтому: каким образом использовались JAVA классы с C++ коде? Оборачивались враппером через JNI и дергались из C++?


Название: Re: Qt Android NFC
Отправлено: iLya84a от Июль 07, 2014, 11:38
каким образом использовались JAVA классы с C++ коде? Оборачивались враппером через JNI и дергались из C++?
Да. Немного подергать JAVA со стороны C++ мне тоже пришлось. В этом случае всё просто.
Я немного распишу как "испускать" сигналы со стороны JAVA, и обрабатывать их в QML.
Для работы со считывателем мне потребовались 3 сигнала:
Код:
class NfcReader : public QObject
{
    Q_OBJECT

public:
    ...
    static NfcReader *getInstance() { return s_instance; }
    ...
signals:
    void tagDetected(); // Поднесли карту к считывателю
    void tagReaded(int number); // Номер шкафчика прочитан
    void tagDisconnected(); // Карту убрали
};
Нам нужно описать нативные методы:
Код:
void tagDetected(JNIEnv */*env*/, jobject /*thiz*/)
{
    NfcReader::getInstance()->tagDetected();
}

void tagReaded(JNIEnv */*env*/, jobject /*thiz*/, int number)
{
    NfcReader::getInstance()->tagReaded(number);
}

void tagDisconnected(JNIEnv */*env*/, jobject /*thiz*/)
{
    NfcReader::getInstance()->tagDisconnected();
}

static JNINativeMethod methods[] = {
    {"tagDetected", "()V", (void *)tagDetected},
    {"tagReaded", "(I)V", (void *)tagReaded},
    {"tagDisconnected", "()V", (void *)tagDisconnected}
};
И зарегистрировать их:
Код:
// This method is called immediately after the module is load
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void */*reserved*/)
{
    JNIEnv *env;
    if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
        qCritical() << "Can't get the enviroument";
        return -1;
    }
    ...
    // Register our native methods
    if (env->RegisterNatives(s_classID, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
        qCritical() << "RegisterNatives failed";
        return -1;
    }
}
На JAVA-стороне эти методы описаны следующим образом:
Код:
    public static native void tagDetected();
    public static native void tagReaded(int number);
    public static native void tagDisconnected();
Вызываем эти методы в коде на JAVA - обрабатываем сигналы на стороне QML :)


Название: Re: Qt Android NFC
Отправлено: ilnile от Сентябрь 04, 2014, 20:14
Подскажите, вы пишите что работали с методами на JAVA.

Не могли бы вы рассказать как это работает?
Вы добавляете в проект на QML/c++ классы на JAVA, а потом к ним обращаетесь?

И еще очень интересно как работать с нативной клавиатурой.
Сегодня весь день искал как из qml поймать event появления клавиатуру.
Буду вам очень признателен.


Название: Re: Qt Android NFC
Отправлено: iLya84a от Сентябрь 08, 2014, 09:43
ilnile, вот как это работает:
  • Создаю в проекте папку android-sources
  • В *.pro файле добавляю строку ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android-sources
  • В папку /android-sources/libs подкладываю необходимые *.jar файлы
  • В папку android-sources/src/org/qtproject/qt5/android/bindings кладу *.java файлы
  • Далее использую JNI. Об этом было подробнее в посте (http://www.prog.org.ru/index.php?topic=27285.msg197619#msg197619) выше.
Deploying an Application on Android (http://qt-project.org/doc/qt-5/deployment-android.html)