注釈付きURL

フォーマットされた NFC データ交換フォーマット(NDEF)メッセージを読み取ります。

注釈付き URL の例では、Qt NFC を使用して NFC タグから読み取られたフォーマットされた NFC データ交換フォーマット(NDEF)メッセージの内容を表示します。NDEFメッセージは、URIレコード、オプションのimage/* MIMEレコード、および1つ以上のローカライズされたテキストレコードを含んでいる必要があります。

これは例の初期状態です:

タグがタッチされると、そのNDEF コンテンツが表示されます。以下は、テキストレコードとURIレコードを含むタグのUIです:

画面がタップされると、URLがブラウザで開かれます。

注釈付きURLクラスの定義

AnnotatedUrl クラスは、NFC タグ検出機能を提供するクラスであるQNearFieldManager をラップします。NDEF メッセージはQNearFieldManager によって読み取られ、AnnotatedUrl クラスに含まれるハンドラに転送されます。NDEF メッセージを解析した後、クラスはannotatedUrl() シグナルを発信します。UIはNDEFメッセージの内容を表示するシグナルに反応します。

class AnnotatedUrl : public QObject
{
    Q_OBJECT

public:
    explicit AnnotatedUrl(QObject *parent = 0);
    ~AnnotatedUrl();

    void startDetection();

signals:
    void annotatedUrl(const QUrl &url, const QString &title, const QPixmap &pixmap);
    void nfcStateChanged(bool enabled);
    void tagError(const QString &error);

public slots:
    void targetDetected(QNearFieldTarget *target);
    void targetLost(QNearFieldTarget *target);
    void handleMessage(const QNdefMessage &message, QNearFieldTarget *target);
    void handlePolledNdefMessage(QNdefMessage message);
    void handleAdapterStateChange(QNearFieldManager::AdapterState state);

private:
    QNearFieldManager *manager;
    QNdefFilter messageFilter;
};

注: startDetection() メソッドは、UI と NFC 関連ロジック間のすべての接続が確立されるま で、実際のタグ検出を延期するために使用されます。これは、NFC タグがタッチされるとアプリケーションが自動的に開始され る場合に重要です。このようなユースケースは現在 Android でサポートされています。

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow mainWindow;
    AnnotatedUrl annotatedUrl;

    QObject::connect(&annotatedUrl, &AnnotatedUrl::annotatedUrl,
                     &mainWindow, &MainWindow::displayAnnotatedUrl);
    QObject::connect(&annotatedUrl, &AnnotatedUrl::nfcStateChanged,
                     &mainWindow, &MainWindow::nfcStateChanged);
    QObject::connect(&annotatedUrl, &AnnotatedUrl::tagError,
                     &mainWindow, &MainWindow::showTagError);

    annotatedUrl.startDetection();
    mainWindow.show();

    return a.exec();
}

メッセージのフィルタリング

前述のように、アプリケーションは特定のフォーマットのNDEF メッセージをサ ポートします。正しいメッセージには以下のフィールドが含まれていなければなりません:

  • ヘッダーとして使用されるNDEFテキストレコードを少なくとも1つ
  • 正確に1つのNDEF URIレコード。
  • アイコンを持つオプションのMIMEレコード。

レコードの順序は厳密に指定されていない。

QNdefFilter のインスタンスがNDEFメッセージの検証に使われる。フィルターは以下のように入力される:

    messageFilter.setOrderMatch(false);
    messageFilter.appendRecord<QNdefNfcTextRecord>(1, 100);
    messageFilter.appendRecord<QNdefNfcUriRecord>(1, 1);
    messageFilter.appendRecord(QNdefRecord::Mime, "", 0, 1);

受信メッセージがフィルターにマッチしない場合、エラーメッセージが表示される:

注: NDEF Editorのサンプルアプリケーションは、正しいメッセージ構造または正しくないメッセージ構造を持つタグを作成するために使用することができる。

AnnotatedUrlハンドラの実装

QNearFieldManager によって読み取られた NFC メッセージはAnnotatedUrl::handleMessage に転送されます。

void AnnotatedUrl::handleMessage(const QNdefMessage &message, QNearFieldTarget *target)
{

まず、QNdefFilter::match ()メソッドを使ってメッセージが検証されます:

    if (!messageFilter.match(message)) {
        emit tagError("Invalid message format");
        return;
    }

メッセージのフォーマットが正しければ、解析が続行されます。

NFCメッセージは複数のNDEFレコードから構成されているため、すべてのレコードをループすることで、UIに表示する3つのパラメータ(Uri、Title、Pixmap)を抽出することができます:

    for (const QNdefRecord &record : message) {
        if (record.isRecordType<QNdefNfcTextRecord>()) {
            QNdefNfcTextRecord textRecord(record);

            title = textRecord.text();
            QLocale locale(textRecord.locale());
        } else if (record.isRecordType<QNdefNfcUriRecord>()) {
            QNdefNfcUriRecord uriRecord(record);

            url = uriRecord.uri();
        } else if (record.typeNameFormat() == QNdefRecord::Mime &&
                   record.type().startsWith("image/")) {
            pixmap = QPixmap::fromImage(QImage::fromData(record.payload()));
        }

最後に、NFC メッセージのパラメータを抽出した後、UI がそれを処理できるように、対応するシグナルが発行されます。

    }

    emit annotatedUrl(url, title, pixmap);
}

アダプタの状態処理

Android では、QNearFieldManager::adapterStateChanged() シグナルに接続することで、アダプタの状態変化を検出できます。これにより、NFC アダプタが無効になったときに検出を停止し、アダプタが再び有効に なったときに検出を再開することができます。このアプローチはAnnotatedUrl::handleAdapterStateChange スロットに実装されています。

void AnnotatedUrl::handleAdapterStateChange(QNearFieldManager::AdapterState state)
{
    if (state == QNearFieldManager::AdapterState::Online) {
        startDetection();
    } else if (state == QNearFieldManager::AdapterState::Offline) {
        manager->stopTargetDetection();
        emit nfcStateChanged(false);
    }
}

アプリケーションの自動起動

Android では、NDEF タグがタッチされたときのアプリケーションの自動起動がサポー トされています。Android マニフェスト・ファイルに必要な変更については、「Qt NFC on Android」を参照してください。

カスタム AndroidManifest.xml を導入するには、ビルドシステム側で特別な手順が必要です。

qmake でのビルド

qmakeを使用する場合は、.pro

android {
    ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android

    DISTFILES += \
        android/AndroidManifest.xml
}
CMakeを使ったビルド

CMakeを使用する場合は、CMakeLists.txt

if(ANDROID)
    set_property(TARGET annotatedurl
        APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
        ${CMAKE_CURRENT_SOURCE_DIR}/android
    )
endif()

サンプルを実行する

Qt Creator からサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳細については、Building and Running an Example を参照してください。

サンプルプロジェクト @ code.qt.io

Qt NFCも参照してください

©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。