Я пытаюсь читать теги NFC на своем телефоне Android, используя модуль NFC Qt.
В соответствии с этой страницей Qt будет поддерживать NFC на Android начиная с версии 5.6. Эта версия еще не выпущена, поэтому я построил ее из источника, следуя инструкциям на этой странице и установил ее в создателе Qt.
Первый шаг - получить работу с тегом/картой, и я застрял там. Мое тестовое приложение создает экземпляр 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";
}
Мне что-то не хватает...
ОБНОВЛЕНИЕ 1
Похоже, файл AndroidManifest.xml необходимо изменить. Я пробовал разные вещи, но никто, кажется, не производит желаемого эффекта. Я могу получить только события targetDetected
и targetLost
, когда манифест определяет фильтр-замысел следующим образом:
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
Однако это также приводит к запуску приложения при каждом сканировании цели, даже если приложение уже запущено. Мне нужно запустить приложение, а затем ждать проверки цели. Как я могу это сделать?
ОБНОВЛЕНИЕ 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>