From 6483796d9c117a7dee7c2ffcef090600b04bd21c Mon Sep 17 00:00:00 2001 From: Lars Schmertmann Date: Tue, 13 Dec 2016 15:34:32 +0100 Subject: Android: Add support for sendCommand to QNearFieldTarget For the communication with a German ID card its required to execute commands. This change enables support for sendCommand. Change-Id: I95773c047953b244cd5c3e22bfc7abf7f7eb656e --- src/nfc/qnearfieldtarget.cpp | 3 +- src/nfc/qnearfieldtarget.h | 3 +- src/nfc/qnearfieldtarget_android.cpp | 81 +++++++++++++++++++++++------------- 3 files changed, 56 insertions(+), 31 deletions(-) diff --git x/qtconnectivity/src/nfc/qnearfieldtarget.cpp y/qtconnectivity/src/nfc/qnearfieldtarget.cpp index 509160c1..a65b4be2 100644 --- x/qtconnectivity/src/nfc/qnearfieldtarget.cpp +++ y/qtconnectivity/src/nfc/qnearfieldtarget.cpp @@ -111,7 +111,7 @@ QT_BEGIN_NAMESPACE /*! \enum QNearFieldTarget::Error - This enum describes the error codes that that a near field target reports. + This enum describes the error codes that a near field target reports. \value NoError No error has occurred. \value UnknownError An unidentified error occurred. @@ -123,6 +123,7 @@ QT_BEGIN_NAMESPACE \value InvalidParametersError Invalid parameters were passed to a tag type specific function. \value NdefReadError Failed to read NDEF messages from the target. \value NdefWriteError Failed to write NDEF messages to the target. + \value CommandError Failed to send a command to the target. */ // Copied from qbytearray.cpp diff --git x/qtconnectivity/src/nfc/qnearfieldtarget.h y/qtconnectivity/src/nfc/qnearfieldtarget.h index dc081f5e..dfb474f6 100644 --- x/qtconnectivity/src/nfc/qnearfieldtarget.h +++ y/qtconnectivity/src/nfc/qnearfieldtarget.h @@ -91,7 +91,8 @@ public: ChecksumMismatchError, InvalidParametersError, NdefReadError, - NdefWriteError + NdefWriteError, + CommandError }; Q_ENUM(Error) diff --git x/qtconnectivity/src/nfc/qnearfieldtarget_android.cpp y/qtconnectivity/src/nfc/qnearfieldtarget_android.cpp index e0c1616d..478f4d8c 100644 --- x/qtconnectivity/src/nfc/qnearfieldtarget_android.cpp +++ y/qtconnectivity/src/nfc/qnearfieldtarget_android.cpp @@ -43,6 +43,7 @@ #define NDEFTECHNOLOGY "android.nfc.tech.Ndef" #define NDEFFORMATABLETECHNOLOGY "android.nfc.tech.NdefFormatable" +#define ISODEPTECHNOLOGY "android.nfc.tech.IsoDep" #define NFCATECHNOLOGY "android.nfc.tech.NfcA" #define NFCBTECHNOLOGY "android.nfc.tech.NfcB" #define NFCFTECHNOLOGY "android.nfc.tech.NfcF" @@ -84,7 +85,19 @@ QNearFieldTarget::Type NearFieldTarget::type() const QNearFieldTarget::AccessMethods NearFieldTarget::accessMethods() const { - AccessMethods result = NdefAccess; + AccessMethods result = UnknownAccess; + + if (m_techList.contains(QStringLiteral(NDEFTECHNOLOGY)) + || m_techList.contains(QStringLiteral(NDEFFORMATABLETECHNOLOGY))) + result |= NdefAccess; + + if (m_techList.contains(QStringLiteral(ISODEPTECHNOLOGY)) + || m_techList.contains(QStringLiteral(NFCATECHNOLOGY)) + || m_techList.contains(QStringLiteral(NFCBTECHNOLOGY)) + || m_techList.contains(QStringLiteral(NFCFTECHNOLOGY)) + || m_techList.contains(QStringLiteral(NFCVTECHNOLOGY))) + result |= TagTypeSpecificAccess; + return result; } @@ -157,24 +170,23 @@ QNearFieldTarget::RequestId NearFieldTarget::readNdefMessages() return requestId; } - QNearFieldTarget::RequestId NearFieldTarget::sendCommand(const QByteArray &command) { - Q_UNUSED(command); - Q_EMIT QNearFieldTarget::error(QNearFieldTarget::UnsupportedError, QNearFieldTarget::RequestId()); - return QNearFieldTarget::RequestId(); - - //Not supported for now - /*if (command.size() == 0) { + if (command.size() == 0) { Q_EMIT QNearFieldTarget::error(QNearFieldTarget::InvalidParametersError, QNearFieldTarget::RequestId()); return QNearFieldTarget::RequestId(); } - AndroidNfc::AttachedJNIEnv aenv; - JNIEnv *env = aenv.jniEnv; + // Making sure that target has commands + if (!(accessMethods() & TagTypeSpecificAccess)) + return QNearFieldTarget::RequestId(); + + QAndroidJniEnvironment env; - jobject tagTech; - if (m_techList.contains(QStringLiteral(NFCATECHNOLOGY))) { + QAndroidJniObject tagTech; + if (m_techList.contains(ISODEPTECHNOLOGY)) { + tagTech = getTagTechnology(ISODEPTECHNOLOGY); + } else if (m_techList.contains(QStringLiteral(NFCATECHNOLOGY))) { tagTech = getTagTechnology(QStringLiteral(NFCATECHNOLOGY)); } else if (m_techList.contains(QStringLiteral(NFCBTECHNOLOGY))) { tagTech = getTagTechnology(QStringLiteral(NFCBTECHNOLOGY)); @@ -187,30 +199,41 @@ QNearFieldTarget::RequestId NearFieldTarget::sendCommand(const QByteArray &comma return QNearFieldTarget::RequestId(); } - QByteArray ba(ba); - - jclass techClass = env->GetObjectClass(tagTech); - jmethodID tranceiveMID = env->GetMethodID(techClass, "tranceive", "([B)[B"); - Q_ASSERT_X(tranceiveMID != 0, "sendCommand", "could not find tranceive method"); + // Connecting + QNearFieldTarget::RequestId requestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate()); + tagTech.callMethod("connect"); + if (catchJavaExceptions()) { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::TargetOutOfRangeError), + Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + return requestId; + } + // Making QByteArray + QByteArray ba(command); jbyteArray jba = env->NewByteArray(ba.size()); env->SetByteArrayRegion(jba, 0, ba.size(), reinterpret_cast(ba.data())); - jbyteArray rsp = reinterpret_cast(env->CallObjectMethod(tagTech, tranceiveMID, jba)); - - jsize len = env->GetArrayLength(rsp); - QByteArray rspQBA; - rspQBA.resize(len); - - env->GetByteArrayRegion(rsp, 0, len, reinterpret_cast(rspQBA.data())); - - qDebug() << "Send command returned QBA size: " << rspQBA.size(); - - + // Writing + QAndroidJniObject myNewVal = tagTech.callObjectMethod("transceive", "([B)[B", jba); + if (catchJavaExceptions()) { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::CommandError), + Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + return requestId; + } + QByteArray result = jbyteArrayToQByteArray(myNewVal.object()); env->DeleteLocalRef(jba); + handleResponse(requestId, result); - return QNearFieldTarget::RequestId();*/ + // Closing connection, sending signal and exit + tagTech.callMethod("close"); + catchJavaExceptions(); // IOException at this point does not matter anymore. + QMetaObject::invokeMethod(this, "requestCompleted", Qt::QueuedConnection, + Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + + return requestId; } QNearFieldTarget::RequestId NearFieldTarget::sendCommands(const QList &commands) -- 2.11.0