Comment faire fonctionner NFC sur Android en utilisant Qt 5.6

J’essaie de lire les tags NFC sur mon téléphone Android en utilisant le module NFC de Qt.

Selon cette page , Qt supportera NFC sur Android à partir de la version 5.6. Cette version n’a pas encore été publiée, donc je l’ai construite à partir des sources, en suivant les instructions de cette page et je l’ai installée dans Qt Creator.

La première étape consiste à faire fonctionner la détection de tag / carte et je suis coincé là. Mon application de test instancie un QNearFieldManager , vérifie si NFC est disponible et connecte les slots aux signaux targetDetected et targetLost . La méthode QNearFieldManager::isAvailable indique que NFC est disponible (avec Qt 5.5 non), mais que les signaux targetDetected / targetLost ne sont jamais déclenchés.

Voici le code de mon application de test:

 #include  #include  #include  #include  #include  #include "window.h" Window::Window(QWidget *parent) : QWidget(parent) { nfcLabel_ = new QLabel(this); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(nfcLabel_, 1); setLayout(mainLayout); setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); setWindowTitle(tr("NFC Test")); nfc_ = new QNearFieldManager(this); if (nfc_->isAvailable()) { nfcLabel_->setText("NFC available"); } else { nfcLabel_->setText("NFC not available"); qWarning() <setTargetAccessModes(QNearFieldManager::NdefReadTargetAccess); // doesn't help nfc_->registerNdefMessageHandler(this, SLOT(handleNdefMessage(QNdefMessage,QNearFieldTarget*))); // doesn't help connect(nfc_, SIGNAL(targetDetected(QNearFieldTarget*)), this, SLOT(targetDetected(QNearFieldTarget*))); connect(nfc_, SIGNAL(targetLost(QNearFieldTarget*)), this, SLOT(targetLost(QNearFieldTarget*))); if (!nfc_->startTargetDetection()) { qWarning() <stopTargetDetection(); } void Window::targetDetected(QNearFieldTarget * /*target*/) { nfcLabel_->setText("Target detected"); } void Window::targetLost(QNearFieldTarget *target) { nfcLabel_->setText("Target lost"); target->deleteLater(); } void Window::handleNdefMessage(const QNdefMessage &/*message*/, QNearFieldTarget */*target*/) { qDebug() << "Ndef Message"; } 

J’ai dû louper quelque chose…

MISE À JOUR 1

Il semble que le fichier AndroidManifest.xml doit être modifié. J’ai essayé différentes choses, mais aucune ne semble produire l’effet désiré. Je ne peux que targetLost événements targetDetected et targetLost lorsque le manifeste définit un filtre d’intention comme celui-ci:

     

Cependant, cela entraîne également le démarrage de l’application à chaque fois qu’une cible est analysée, même si l’application est déjà en cours d’exécution. Ce dont j’ai besoin, c’est de démarrer l’application, puis d’attendre qu’une cible soit analysée. Comment puis-je accomplir cela?

MISE À JOUR 2

Vous trouverez ci-dessous le fichier AndroidManifest.xml complet que j’ai essayé.

                                   <!--  -->             

Si vous utilisez un tag NFC de certains fabricants, le même NFC doit également être présent dans le NFC mobile, à ce moment-là seulement, il sera couplé correctement. NFC ne supporte pas globalement. Par exemple Si le NFC Present présent dans le périphérique Sony ne prend en charge que sa fabrication et, dans la plupart des cas, il ne parvient pas à se connecter à d’autres périphériques tels que Nexus. Alors, essayez de trouver votre fabricant et connectez-le. J’espère que ça vous aide ..

Je ne crois pas que vous vouliez ces filtres d’intention dans votre manifeste. L’ajout de ceux-ci indique au système d’exploitation de démarrer votre application lorsqu’une balise est détectée (c’est pourquoi elle le fait). Il semble que vous vous enregissortingez correctement dans votre code pour les événements NFC. Le problème réside peut-être dans la marque de la puce NFC de votre téléphone, conjointement avec la balise que vous utilisez pour tester. Si votre téléphone est équipé d’une puce Broadcom NFC et que vous essayez d’utiliser le tag Mifare Classic de NXP, vous rencontrerez des problèmes. L’utilisation d’un tag Desfire ou NTAG peut aider.

J’ai résolu celui-ci.

La raison en est que, dans QtNfc.java, où qt gère les intentions NFC, il ne gère que les balises NDEF en filtrant les actions ACTION_NDEF_DISCOVERED ( et ACTION_TECH_DISCOVERED pour les balises NDEF ) sans ACTION_TAG_DISCOVERED .

Mais je suppose que vous voulez juste scanner une simple balise pour lire uid, comme je le fais. Vous devez donc append ACTION_TAG_DISCOVERED à la liste des filtres dans la fonction QtNfc.java start ():

 IntentFilter[] filters = new IntentFilter[3]; filters[0] = new IntentFilter(); filters[0].addAction(NfcAdapter.ACTION_TAG_DISCOVERED); filters[0].addCategory(Intent.CATEGORY_DEFAULT); ... 

Je pense qu’il serait plus correct de modifier le filtre en ACTION_TAG_DISCOVERED dans setContext. Le moyen le plus rapide est d’ouvrir qt creator qtconnectivity .pro pour la twig correspondante, de corriger QtNfc.java, de le construire et de remplacer libQt5Nfc.so dans le dossier android_armv7 \ lib qt (QtNfc.jar et QtNfc-bundled.jar dans le dossier android_armv7 \ jar être mis à jour pendant la construction).

C’est. Pas besoin de modifier le manifeste dans l’application de travail.

Au fait celui-ci:

  

qt append automatiquement lorsque vous ajoutez le module nfc à .pro

Celui-là

  

n’est pas nécessaire je suppose. Cela fonctionne sans elle.

Mais vous pouvez append ce filtre d’intention si vous voulez dire à Android de démarrer votre application lorsqu’une balise est détectée comme Anansi l’a mentionné. Mais je recommande vraiment d’append Android: alwaysRetainTaskState = “true” android: launchMode = “singleInstance” dans l’activité de l’application (comme ici ).

Je teste tout cela avec Android 4.4.4 exemple de tablette et ndefeditor. Il déclenche parfaitement targetDetected / targetLost. Il peut y avoir une autre application par défaut pour les tags dans le système (par exemple NFC Reader ) et elle s’ouvre sur chaque détection de tag, mais pas le temps où ndefeditor attend le tag (extraction du bouton). Et bien sur qt exemple dit “erreur de lecture NDEF” pour les tags non-NDEF, mais il les détecte et lit uid. Précisément ce dont j’avais besoin.

J’ajoute la suggestion à Qt Jira et soumet le patch .

La seule chose que je ne comprenais pas – pourquoi ndefeditor avait travaillé sur une autre tablette avec Android 4.2. Peut-être que c’est un aspect matériel et Android sur une autre tablette a toujours été intentionnel ACTION_NDEF_DISCOVERED?

Bonjour ci-dessous est la réponse, laissez-moi savoir si vous recherchez uniquement cela. 🙂 Tout d’abord, écrivez ceci dans onCreate ()

 //Code in onCreate mNfcAdapter = NfcAdapter.getDefaultAdapter(this); mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); // set an intent filter for all MIME data IntentFilter ndefIntent = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); try { ndefIntent.addDataType("*/*"); mIntentFilters = new IntentFilter[] { ndefIntent }; } catch (Exception e) { Log.fnLogToFile(strFunctionName + "-" + e.getMessage(), ErrorType.ERROR); Log.createCrashReport(); } mNFCTechLists = new Ssortingng[][] { new Ssortingng[] { NfcF.class.getName() } }; 

Ecrivez-le sur NewIntent à l’extérieur de onCreate ()

 @Override public void onNewIntent(Intent intent) { StackTraceElement[] arrFunctionName = Thread.currentThread().getStackTrace() ; Ssortingng strFunctionName = arrFunctionName[arrFunctionName.length-1].getMethodName(); Log.fnLogToFile(strFunctionName + "Entered", ErrorType.INFO); tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); Ssortingng strTagData = ""; // parse through all NDEF messages and their records and pick text type only Parcelable[] data = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); if (data != null) { try { for (int i = 0; i < data.length; i++) { NdefRecord [] recs = ((NdefMessage)data[i]).getRecords(); for (int j = 0; j < recs.length; j++) { if (recs[j].getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(recs[j].getType(), NdefRecord.RTD_TEXT)) { byte[] payload = recs[j].getPayload(); String textEncoding = ((payload[0] & 0200) == 0) ? "UTF-8" : "UTF-16"; int langCodeLen = payload[0] & 0077; //tag data is saved in strTagData strTagData += ("\n" + new String(payload, langCodeLen + 1, payload.length - langCodeLen - 1, textEncoding)); } } } } catch (Exception e) { Log.fnLogToFile(strFunctionName + "-" + e.getMessage(), ErrorType.ERROR); Log.createCrashReport(); Log.e("TagDispatch", e.toString()); } } } 

Vous obtiendrez des données NFC dans la variable strTagData

Autorisation dans le manifeste