如何使用Qt5.6让NFC在Android上工作

如何使用Qt5.6让NFC在Android上工作,android,c++,qt,nfc,qt5.6,Android,C++,Qt,Nfc,Qt5.6,我正在尝试使用Qt的NFC模块读取Android手机上的NFC标签 据此,Qt将从5.6版开始在Android上支持NFC。这个版本还没有发布,所以我从源代码处编译了它,按照上面的说明,并在Qt creator中安装了它 第一步是让标签/卡片检测工作,我被卡在那里了。我的测试应用程序实例化一个QNearFieldManager,检查NFC是否可用,并将插槽连接到信号targetDetected和targetLost。 QNearFieldManager::isAvailable方法报告NFC可用

我正在尝试使用Qt的NFC模块读取Android手机上的NFC标签

据此,Qt将从5.6版开始在Android上支持NFC。这个版本还没有发布,所以我从源代码处编译了它,按照上面的说明,并在Qt creator中安装了它

第一步是让标签/卡片检测工作,我被卡在那里了。我的测试应用程序实例化一个
QNearFieldManager
,检查NFC是否可用,并将插槽连接到信号
targetDetected
targetLost
QNearFieldManager::isAvailable
方法报告NFC可用(Qt 5.5没有),但从未触发信号
targetDetected
/
targetLost

以下是我的测试应用程序代码:

#include <QLabel>
#include <QVBoxLayout>

#include <QNearFieldManager>
#include <QNearFieldTarget>

#include <QDebug>

#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() << "NFC not available";
    }

    nfc_->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() << "NFC target detection could not be started";
    }
}

Window::~Window()
{
    nfc_->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";
}
但是,这也会导致每次扫描目标时启动应用程序,即使应用程序已经在运行。我需要的是启动应用程序,然后等待扫描目标。我怎样才能做到这一点

更新2

下面是我尝试的完整AndroidManifest.xml文件

<?xml version="1.0"?>
<manifest package="org.qtproject.example" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
    <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --" android:theme="@android:style/Theme.Holo">
    <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="-- %%INSERT_APP_NAME%% --" android:screenOrientation="unspecified" android:launchMode="singleTop">
        <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>

        <!-- Without this, the targetDetected/targetLost signals aren't fired -->
        <intent-filter>
        <action android:name="android.nfc.action.TAG_DISCOVERED"/>
        <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>

        <meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
        <meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
        <meta-data android:name="android.app.repository" android:value="default"/>
        <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
        <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
        <!-- Deploy Qt libs as part of package -->
        <meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
        <meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
        <meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
        <!-- Run with local libs -->
        <meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
        <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
        <meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
        <meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
        <meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
        <!--  Messages maps -->
        <meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
        <meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
        <meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
        <!--  Messages maps -->

        <!-- Splash screen -->
        <!--
        <meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/>
        -->
        <!-- Splash screen -->

        <!-- Background running -->
        <!-- Warning: changing this value to true may cause unexpected crashes if the
              application still try to draw after
              "applicationStateChanged(Qt::ApplicationSuspended)"
              signal is sent! -->
        <meta-data android:name="android.app.background_running" android:value="false"/>
        <!-- Background running -->
    </activity>
    </application>
    <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="14"/>
    <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
    <uses-feature android:name="android.hardware.nfc" android:required="true"/>
    <uses-permission android:name="android.permission.NFC"/>
</manifest>

下面是答案,如果您只想找这个,请告诉我。:) 首先在onCreate()中编写

在onCreate()之外写入此onNewIntent

@覆盖
公营房屋(意向){
StackTraceElement[]arrFunctionName=Thread.currentThread().getStackTrace();
字符串strFunctionName=arrFunctionName[arrFunctionName.length-1].getMethodName();
Log.fnLogToFile(strFunctionName+“Entered”,ErrorType.INFO);
tag=intent.getParcelableExtra(NfcAdapter.EXTRA_标记);
字符串strTagData=“”;
//解析所有NDEF消息及其记录,并仅选择文本类型
Parcelable[]data=intent.getParcelableArrayExtra(NfcAdapter.EXTRA\u NDEF\u消息);
如果(数据!=null){
试一试{
对于(int i=0;i
您将在strTagData变量中获得NFC数据


清单中的权限

如果您使用的是某个制造商的NFC标签,那么移动NFC中也应该有相同的标签,那么只有它才能正确配对,因为NFC不支持全局。例如,如果索尼设备内部的NFC将仅支持其制造,并且在大多数情况下,它无法连接到其他设备,如nexus。所以,试着找到你的制造商并连接它。希望它对您有所帮助。

我相信您不希望在清单中包含这些意图过滤器。添加这些,告诉操作系统在检测到标签时启动你的应用程序(这就是它这样做的原因)。看起来你在NFC活动代码中的注册是正确的,所以问题可能是你手机中的NFC芯片品牌,以及你用来测试的标签。如果您的手机配备了Broadcom NFC芯片,并且您试图使用NXP的Mifare Classic标签,那么您将遇到问题。使用Desfire或NTAG标签可能会有所帮助。

我已经解决了这个问题

原因是,在qt处理NFC意图的地方,它只处理标记,通过过滤ACTION\u NDEF\u发现的操作(以及ACTION\u TECH\u为将报告为TECH的NDEF标记发现的操作)而不处理simple ACTION\u TAG\u发现的(尽管它在GetStartinent功能中处理它)

但我想你只是想扫描一个简单的标签来读取uid,就像我一样。因此,您需要在QtNfc.java start()函数中将发现的操作\u标记\u添加到筛选器列表中:

IntentFilter[] filters = new IntentFilter[3];
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_TAG_DISCOVERED);
filters[0].addCategory(Intent.CATEGORY_DEFAULT);
...
我认为将过滤器修改为setContext中发现的ACTION_TAG_会更正确。 最快的方法是在qt creator.pro中打开相应的分支,更正QtNfc.java,构建并替换android_armv7\lib qt文件夹中的libQt5Nfc.so(android_armv7\jar文件夹中的QtNfc.jar和QtNfc-bundled.jar将在构建过程中更新)

就是。无需在工作应用程序中修改清单

顺便说一下,这个:

<uses-permission android:name="android.permission.NFC"/>

将模块nfc添加到.pro时自动添加qt

这个

<uses-feature android:name="android.hardware.nfc" android:required="true"/>

我想没有必要。没有它也行

但如果你想在检测到标签为上面提到的Anansi时告诉android启动你的应用程序,你可以添加这个意图过滤器。但我真的建议补充一点 android:alwaysRetainTaskState=“true”android:launchMode=“singleInstance” 应用程序内活动(如)。
IntentFilter[] filters = new IntentFilter[3];
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_TAG_DISCOVERED);
filters[0].addCategory(Intent.CATEGORY_DEFAULT);
...
<uses-permission android:name="android.permission.NFC"/>
<uses-feature android:name="android.hardware.nfc" android:required="true"/>