QtのNFCモジュールを使用して、Android電話のNFCタグを読み取ろうとしています。
これによると ページ 、QtはNFC on Androidバージョン5.6以降をサポートします。このバージョンはまだリリースされていません、そのため、この page の指示に従ってソースからビルドし、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";
}
私は何かが欠けているに違いない...
UPDATE 1
AndroidManifest.xmlファイルを変更する必要があるようです。私はさまざまなことを試しましたが、どれも望ましい効果を生み出していないようです。マニフェストが次のようなインテントフィルターを定義している場合にのみ、targetDetected
イベントとtargetLost
イベントを発生させることができます。
<intent-filter>
<action Android:name="Android.nfc.action.TAG_DISCOVERED"/>
<category Android:name="Android.intent.category.DEFAULT"/>
</intent-filter>
ただし、これにより、アプリがすでに実行されている場合でも、ターゲットがスキャンされるたびにアプリが起動します。必要なのは、アプリを起動して、ターゲットがスキャンされるのを待つことです。どうすればこれを達成できますか?
UPDATE 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>
特定のメーカーのNFCタグを使用している場合、同じものがモバイルに存在する必要がありますNFCまた、現時点では正しくペアリングされますNFCはグローバルにサポートされていません。たとえば、NFC Sonyデバイス内に存在する場合、その製造のみが最大でサポートされ、ほとんどの場合、nexusなどの他のデバイスに接続できません。 。だからあなたのメーカーを見つけて接続してみてください。それがあなたを助けることを願っています。
マニフェストにこれらのインテントフィルターが必要だとは思わない。それらを追加すると、タグが検出されたときにアプリを起動するようにオペレーティングシステムに指示します(これがそうしている理由です)。 NFCイベントのコードに正しく登録しているように見えるので、おそらく問題は、携帯電話のNFCチップのブランドと組み合わせて、テストに使用しているタグを使用します。電話にBroadcom NFCチップが搭載されていて、NXPのMifare Classicタグを使用しようとすると、問題が発生します。 DesfireまたはNTAGタグを使用すると役立つ場合があります。
私はこれを解決しました。
その理由は、 QtNfc.Java ここでqtはNFCインテントを処理しますonly[〜#〜] ndef [〜#〜] ACTION_NDEF_DISCOVEREDアクションをフィルタリングすることによるタグ(およびtechとして報告するNDEFタグのACTION_TECH_DISCOVERED)withoutsimple ACTION_TAG_DISCOVERED(getStartIntent関数で処理するにもかかわらず)。
しかし、私と同じように、単純なタグをスキャンしてuidを読み取るだけだと思いました。したがって、QtNfc.Java start()関数のフィルターリストにACTION_TAG_DISCOVEREDを追加する必要があります。
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_DISCOVEREDに変更する方が正しいと思います。最速の方法は、qtcreatorで開く qtconnectivity .proで対応するブランチを修正し、QtNfc.Javaを修正してビルドし、Android_armv7\lib qtフォルダー(QtNfc.jarおよびQtNfc-bundled)のlibQt5Nfc.soを置き換えます。 Android_armv7\jarフォルダー内の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"( here など)。
これをすべてAndroid 4.4.4タブレットとndefeditorの例でテストします。targetDetected/ targetLostを完全に起動します。システム内のタグに別のデフォルトアプリケーションが存在する可能性があります(たとえば、 NFCリーダー )そしてそれはすべてのタグ検出で開きますが、ndefeditorがタグを待機している時間(ボタンの取得)ではありません。もちろん、qtの例では非NDEFタグに対して「NDEF読み取りエラー」と表示されますが、それらを検出してuidを読み取ります。まさに私が必要としていたもの。
Qt Jiraへの提案 を追加し、 パッチ を送信します。
私が理解していなかった唯一のこと-ndefeditorがAndroid 4.2で別のタブレットで作業した理由。多分それはハードウェアの側面であり、別のタブレットでAndroid常にACTION_NDEF_DISCOVEREDを意図していますか?