注释URL

读取格式化的NFC数据交换格式(NDEF)消息。

示例使用 Qt NFC 来显示从NFC标签中读取的特定格式化NFC数据交换格式(NDEF)消息的内容。NDEF消息应包含一个URI记录,一个可选的 image/* MIME记录,以及一个或多个本地化的文本记录。

这是示例的初始状态

如果触摸标签,其NDEF内容将显示出来。以下是包含文本记录和URI记录的标签的用户界面

当屏幕被轻触时,将在浏览器中打开URL。

注释Url类定义

AnnotatedUrl 类封装了提供NFC标签检测功能的 QNearFieldManager 类。NDEF消息由 QNearFieldManager 读取,并转发到 AnnotatedUrl 类中包含的处理程序。解析NDEF消息后,该类发出 annotatedUrl() 信号。用户界面对该信号做出反应,以显示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 文本记录,它将用作标题。
  • 确切一个 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 编辑器 示例应用程序创建具有正确或错误消息结构的标签。

注释Url处理程序实现

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、标题和图象。

    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清单文件的必要更改,请参阅Android上的Qt NFC

引入自定义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中选择示例。有关更多信息,请访问构建和运行示例

示例项目 @ code.qt.io

另请参阅 Qt NFC.

© 2024 The Qt Company Ltd. 本文档中的贡献是相应所有者的版权。本提供的文档是根据GNU自由文档许可证版本1.3的条款许可的,该许可证由自由软件基金会发布。Qt及其相关商标是世界各地的芬兰和/或其他国家的The Qt Company Ltd的商标。所有其他商标均为其各自所有者的财产。