web-dev-qa-db-ja.com

Qt5.6を使用してNFC作業中Android

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>
56
Pat

特定のメーカーのNFCタグを使用している場合、同じものがモバイルに存在する必要がありますNFCまた、現時点では正しくペアリングされますNFCはグローバルにサポートされていません。たとえば、NFC Sonyデバイス内に存在する場合、その製造のみが最大でサポートされ、ほとんどの場合、nexusなどの他のデバイスに接続できません。 。だからあなたのメーカーを見つけて接続してみてください。それがあなたを助けることを願っています。

1
Daya Nithi

マニフェストにこれらのインテントフィルターが必要だとは思わない。それらを追加すると、タグが検出されたときにアプリを起動するようにオペレーティングシステムに指示します(これがそうしている理由です)。 NFCイベントのコードに正しく登録しているように見えるので、おそらく問題は、携帯電話のNFCチップのブランドと組み合わせて、テストに使用しているタグを使用します。電話にBroadcom NFCチップが搭載されていて、NXPのMifare Classicタグを使用しようとすると、問題が発生します。 DesfireまたはNTAGタグを使用すると役立つ場合があります。

1
Anansi

私はこれを解決しました。

その理由は、 QtNfc.Java ここでqtはNFCインテントを処理しますonly[〜#〜] ndef [〜#〜] ACTION_NDEF_DISCOVEREDアクションをフィルタリングすることによるタグ(およびtechとして報告するNDEFタグのACTION_TECH_DISCOVEREDwithoutsimple 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を意図していますか?

1
Oleg Evseev