Qt-based BB10 API Examples Documentation

Contents

NFC Share

Files:

Description

The NFC Share example allows a user to exchange content, such as messages or files with another NFC enabled device.

Overview

In this example we'll learn how to use the NfcShareManager to share data and files by tapping NFC enabled device or NFC tag.

The business logic is encapsulated in the C++ class NfcShareHandler, which is exported to QML under the name '_nfcShareHandler'.

        NfcShareHandler nfcShareHandler;

        QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(&app);
        qml->setContextProperty("_nfcShareHandler", &nfcShareHandler);

The UI

The UI allows the user to share data or files by using the NfcShareManager, this being an alternative to the BPS library used in the other NFC examples to achieve the same functionality. The page contains a TextField for data input or uses a FilePicker to select the file(s) to be shared.

NfcShareHandler

The NfcShareHandler class performs sharing of data and files over NFC, with some similarity to NfcSender, the difference being the underlying mechanism used to perform this sharing. Instead of using the Bps library, it uses the NfcShareManager to achieve the same result, but with a more convenient way. The NfcShareManager will allow sharing data to either a tag (through tag writing) or to another device (SNEP Push) behind the scenes.

    NfcShareHandler::NfcShareHandler(QObject *parent)
        : QObject(parent)
        , m_shareMode(DataShare)
        , m_fileListModel(new FileListModel(this))
        , m_systemToast(new bb::system::SystemToast(this))
        , m_nfcShareManager(new bb::system::NfcShareManager(this))
    {
        bool ok = connect(m_fileListModel, SIGNAL(changed()), this, SLOT(prepareFileShareContent()));
        Q_ASSERT(ok);

        // Connect signal for finished (success) notifications
        ok = connect(m_nfcShareManager, SIGNAL(finished(bb::system::NfcShareSuccess::Type)),
                     this, SLOT(sharingFinished(bb::system::NfcShareSuccess::Type)));
        Q_ASSERT(ok);

        // Connect signal for error notifications
        ok = connect(m_nfcShareManager, SIGNAL(error(bb::system::NfcShareError::Type)),
                     this, SLOT(sharingError(bb::system::NfcShareError::Type)));
        Q_ASSERT(ok);
    }

The constructor initializes it's member variables, including the NfcShareManager and makes the signal/slot connections.

    void NfcShareHandler::prepareDataShareContent()
    {
        if (m_data.isEmpty())
            return;

        // Prepare new data share content
        bb::system::NfcShareDataContent dataShareContent;

        // The data content needs to be stored as a QByteArray
        const QByteArray data(m_data.toUtf8());

        // We will share our data as text/plain data
        dataShareContent.setMimeType(QLatin1String("text/plain"));
        dataShareContent.setData(data);

        // Set the share content to our new data share content
        m_nfcShareManager->setShareContent(dataShareContent);
    }

Clients specify the data they want to share by creating an instance of NfcShareDataContent, populating it with data, and passing the object to NfcShareManager::setShareContent(const NfcShareDataContent &). A request must contain a valid combination of MIME type, data and URI fields.

    void NfcShareHandler::prepareFileShareContent()
    {
        // Prepare new file share content
        bb::system::NfcShareFilesContent fileShareContent;

        // Get the current list of files stored by the FileListModel
        const QList<QUrl> files = m_fileListModel->files();
        if (files.isEmpty())
            return;

        fileShareContent.setFileUrls(files);

        // Set the share content to our new file share content
        m_nfcShareManager->setShareContent(fileShareContent);
    }

Defines a request to share local files over NFC.

The files are given through the FileListModel, which is populated using FilePicker. The files you wish to share are specified by creating an instance of NfcShareFilesContent, populating it with file paths in URI form, and passing the object to NfcShareManager::setShareContent(const NfcShareFilesContent &).

Note that a request must contain at least one file to be valid.

    void NfcShareHandler::sharingFinished(bb::system::NfcShareSuccess::Type result)
    {
        // TODO: clean up - some bluetooth notifications overlap with ours
        // we will display a System Toast when a transaction has been completed successfully
        switch (result) {
            case bb::system::NfcShareSuccess::File:
                displayNotification(tr("NFC file transfer started successfully"));
                break;
            case bb::system::NfcShareSuccess::Snep:
                displayNotification(tr("NFC data was transfered successfully"));
                break;
            case bb::system::NfcShareSuccess::TagWrite:
                displayNotification(tr("NFC data was written successfully"));
                break;
            default:
                displayNotification(tr("Unknown share success"));
                break;
        }
    }

    void NfcShareHandler::sharingError(bb::system::NfcShareError::Type error)
    {
        switch (error) {
            /**
             * Unrecoverable NFC errors
             */
            case bb::system::NfcShareError::NoContentToShare:
            case bb::system::NfcShareError::Unknown:
                displayNotification(tr("Failed to share data over NFC"));
                break;
            case bb::system::NfcShareError::RegisterFileSharing:
                displayNotification(tr("Failed to prepare for file sharing"));
                break;
            case bb::system::NfcShareError::RegisterDataSharing:
                displayNotification(tr("Failed to prepare for data sharing"));
                break;
                /**
                 * Recoverable NFC errors - try again
                 */
            case bb::system::NfcShareError::MessageSize:
                displayNotification(tr("NFC Tag is too small for a shared message"));
                break;
            case bb::system::NfcShareError::TagLocked:
                displayNotification(tr("Failed to write to a locked NFC Tag"));
                break;
            case bb::system::NfcShareError::UnsupportedTagType:
                displayNotification(tr("Failed to write to a unsupported NFC Tag"));
                break;
            case bb::system::NfcShareError::DataTransferFailed: //includes REJECTED and IO ERROR
            case bb::system::NfcShareError::HandoverFailed:
            case bb::system::NfcShareError::BluetoothFileTransferFailed:
                displayNotification(tr("Failed to share data over NFC - tap again"));
                break;
            default:
                displayNotification(tr("Unknown nfc share error"));
                break;
        }
    }

    void NfcShareHandler::displayNotification(const QString& notification)
    {
        //TODO: clean - a bunch of these toasts can pile up and require the
        // user to close them all

        // Create a System Toast to display our notifications.
        // The toast will be placed in the middle center of the screen and will NOT auto dismiss
        // the user will have to click 'Ok' to dismiss the toast.
        m_systemToast->setBody(notification);
        m_systemToast->setPosition(bb::system::SystemUiPosition::MiddleCenter);

        // The modality should be set to Application, a Global Modality will prevent
        // the toast from disappearing when the application is thumbnailed.
        m_systemToast->setModality(bb::system::SystemUiModality::Application);

        bb::system::SystemUiButton* toastButton = m_systemToast->button();
        toastButton->setLabel(tr("Ok"));

        // We need to enable the button or it will auto dismiss
        toastButton->setEnabled(true);

        // Display the System Toast
        m_systemToast->show();
    }

When the share completes, either the sharingFinished() or sharingError() is invoked, depending which signal we receive. In both cases we check the types of events that are received and formulate a proper notification to be displayed using the SystemToast.

    void NfcShareHandler::setShareMode(ShareMode mode)
    {
        if (m_shareMode == mode)
            return;

        m_shareMode = mode;

        // Clear all previous set data
        //m_nfcShareManager->reset();

        // HACK: Needed in R9, since reset() does not work as supposed
        m_nfcShareManager->setShareMode(bb::system::NfcShareMode::Disabled);

        switch (m_shareMode) {
            case DataShare:
                m_nfcShareManager->setShareMode(bb::system::NfcShareMode::Data);
                prepareDataShareContent();
                break;
            case FileShare:
                m_nfcShareManager->setShareMode(bb::system::NfcShareMode::File);
                prepareFileShareContent();
                break;
        }

        emit shareModeChanged();
    }

This method allows for the switching between the different types of share modes, the modes being data or file sharing. This is done in the SegmentedControl, located in SharePage.qml, by invoking this method when the onSelectedValueChanged() slot is invoked. Once the mode has been chosen, either the prepareDataShareContent() or prepareFileShareContent() is invoked.