Tutorial: Explore the Networking Downloading a File sample app

Connecting to a network and retrieving resources is a fundamental requirement of mobile computing. In this walkthrough, we're going to focus on a networking sample app that accesses a remote server and retrieves an XML file containing a list of contacts. The Networking Downloading a File sample app sends an HTTP request, retrieves an XML file containing a contact list, and displays the list of contacts in a ListView control. The Networking Downloading a File sample app also shows you how to check for network connectivity to determine what interface the device is using to make the network connection (Wi-Fi, cellular, and so on).

You will learn to:

  • Set up a custom UI to retrieve a file
  • Populate a list using an XML file
  • Use a SystemProgressToast to display download activity
  • Send an HTTP request over a network
  • Save the network reply data to the device file system
  • Retrieve the raw headers from the network reply object
  • Check for connectivity and display connectivity status in the UI
  • Determine the connection interface (Wi-Fi, cellular, and so on) that the device is using to make the connection
Screen showing the sample app used in this discussion.

Downloading the Networking Downloading a File sample app

Download the Networking Downloading a File sample app. Before we start exploring the sample app, import it into the Momentics IDE for BlackBerry and try it out. To learn how, see Importing and exporting projects.

As we explore the different areas of the app, you can follow along with the code in the Momentics IDE. The app code includes comments that provide additional information to help you understand what's happening in the code.

Exploring the UI

When you run the Networking Downloading a File sample app, you see the main screen of the app's UI. This screen displays an empty list before the Networking Downloading a File sample app tries to download the contact list from the content server. When the Networking Downloading a File sample app has successfully retrieved the contact list, it displays contact list on the main screen.

Main screen

On the main screen, you can view the status of the network connection along with the network interface, which shows you how the app is connected (for example, by Wi-Fi, cellular, and so on). There is also a toggle button that you can use to view the raw headers.

Below the connection information, you can view the contact list of names that's retrieved from the server.

Screen showing the main UI of the sample app.

The main screen is defined in the main.qml file, which is located in the assets folder of your project. The main screen UI is made up of one Page control with four Container controls. There's a root Container and three child containers. The first child container holds two Label controls and two ImageView controls. Together, they report the network status, and the connectivity interface. The second child container holds a ToggleButton that's used to view the raw headers dialog box. The third container has a ListView that displays the contact list.

Diagram of the UI layout showing the root container, status container, raw headers container, and the list container.

Let's take a closer look at the ListView that's used to display the contact list. Here's the code for the ListView.

ListView {
    objectName: "list"
    accessibility.name: "Contact list"

    // A simple data model is loaded with just a header
    // and some dummy data which will be replaced when
    // we load the real data model from our C++ code
    dataModel: XmlDataModel {
        source: "asset:///contacts_empty.xml"
    listItemComponents: [

        // The header list item displays a title along
        // with a counter that displays the number of
        // contacts in the list
        ListItemComponent {
            type: "header"
            Header {
                title: ListItemData.title
                subtitle: "Number of contacts: " + 
                    (ListItem.initialized ?
                        .childCount(ListItem.indexPath) : 0)
        // This list item displays the names of the contacts
        ListItemComponent {
            type: "contacts"
            StandardListItem {
                title: ListItemData.title

We set the data model of the ListView to our default XML file while we wait for the app to connect to the network, and retrieve the list of contact names. Notice that we define two ListItemComponent controls. One ListItemComponent is used to keep a count of the number of contacts in the list, and the other ListItemComponent is used for the list of contacts.

When the app retrieves the list of contacts from the remote server, the default (empty) XML file is replaced with a new XML file containing our contact names.

Screen showing the main UI displaying the default contact list.
Screen showing the main UI retrieving the contact list.
Screen showing the main UI displaying the contact list.

Raw header screen

You can view the raw headers without leaving the main screen. Slide the ToggleButton to view or hide the raw header information screen.

The raw headers are displayed in the RawHeaderView screen, which is defined in the RawHeaderView.qml file. The root element is a Container, and it contains an ImageView that is used to set the background image for the screen. There is also another Container that contains a Label and a TextArea, which are used to lay out and display the raw header information.

Screen showing the raw header view UI displaying the header information.

Let's take a closer look at the QML code for the raw header screen.

Container {
    topPadding: 30.0
    leftPadding: 20.0
    rightPadding: 20.0
    // Title of the screen

    Label {
        text: "Raw Request Headers"
        horizontalAlignment: HorizontalAlignment.Fill
        topMargin: 20.0
        bottomMargin: 10.0
        textStyle.fontSize: FontSize.Large
        textStyle.textAlign: TextAlign.Center
        textStyle.color: Color.White
    // Raw header information

    TextArea {
        horizontalAlignment: HorizontalAlignment.Fill
        verticalAlignment: VerticalAlignment.Fill
        topMargin: 10
        bottomMargin: 10
        editable: false

        objectName: "txaRawHeaderInfo"
        textStyle.fontSize: FontSize.Small
        textStyle.textAlign: TextAlign.Left
        textStyle.color: Color.White

Notice in the QML above that the Label is used to set the title for the raw header screen. The TextArea is used to display the raw header information.

We use C++ code in the Networking Downloading a File sample app to retrieve and display the raw header information. Retrieving and displaying the raw header information is a two-step process. First, we connect a slot to the QNetworkAccessManager::finished() signal.

// Connect to the QNetworkAccessManager finished signal
res = QObject::connect(m_pNetAccessMngr,

This signal is emitted when a pending QNetworkReply has been completed. The reply parameter contains a pointer to the reply.

Second, we use the reply pointer in our onRequestFinished() slot to retrieve and set the raw header information as the text of our TextArea control. The TextArea text is set using the underlying reference to the TextArea object in C++.

void ApplicationUI::onRequestFinished ()
    // ...

    // Update the raw headers dialog box

    QString rawHdrInfo = getRawHeaderInfo(m_pNetReply);

    // Enable the view raw header toggle


    // ...

Notice that the raw header data is retrieved and formatted using our custom function called getRawHeaderInfo(), which returns a QString with the raw header information. This function iterates through a QList containing the raw headers, and adds the header data to our QString, which then gets returned to the calling function.

// This function collects the raw headers and returns them as a
// QString object
QString ApplicationUI::getRawHeaderInfo ( QNetworkReply* reply )
    QList <QByteArray> rawHeaderList = 
    QString rawHdrs;

    foreach(QByteArray hdrName, rawHeaderList)
        QByteArray hdrValue = reply->rawHeader(hdrName);
        rawHdrs += hdrName;
        rawHdrs += " : ";
        rawHdrs += hdrValue;
        rawHdrs += "\n";

    return rawHdrs;

Set up the network request

The Networking Downloading a File sample app uses a QNetworkAccessManager to set up the network request. The QNetworkAccessManager can asynchronously send network requests, and capture the network replies in QNetworkReply objects.

Only one QNetworkAccessManager instance is required in your app. This one instance is capable of handling all of your app's network requests.

The QNetworkAccessManager creates its own thread internally to asynchronously do its job, which means that it doesn't block your application's main UI thread. This built-in multithreading keeps your app's UI from freezing during long networking operations, and makes the QNetworkAccessManager easy to use and powerful.

Since data charges could apply when retrieving resources over a cellular connection, in your production app you should show users a warning message before performing any download operations over a cellular network connection. This warning gives them a chance to opt out of the download and avoid incurring data charges on their mobile account.

To set up a QNetworkAccessManager, we call its constructor, which returns a pointer to the new QNetworkAccessManager object. The QNetworkAccessManager has a finished(QNetworkReply*) signal that returns a pointer to a QNetworkReply object. We can connect a slot to the finished(QNetworkReply*) signal, which allows our app to work with the QNetworkReply that's returned when the request has completed. The QNetworkReply object contains all of the data that's returned by the server.

Optionally, you can connect a slot to the   QIODevice::readyRead() signal; doing this allows your app to continually parse data as it arrives.

Let's examine how we set a pointer to the QNetworkAccessManager, and connect our onRequestFinished(QNetworkReply*) slot to its finished(QNetworkReply*) signal.

// ...

bool res;

// Since the variable is not used in the app,
// this is added to avoid a compiler warning

// Create a pointer to a network access manager
this->m_pNetAccessMngr = new QNetworkAccessManager(this);

// ...

// Connect to the QNetworkAccessManager finished signal
res = QObject::connect(m_pNetAccessMngr,

// ...

Send the network request

When the QNetworkAccessManager has been set up, you can create your request by instantiating a QNetworkRequest object. In the Networking Download a File sample, we use a function called sendNewRequest() to create and send our network request. Notice that this function also monitors the download progress by connecting a slot to the QNetworkReply::downloadProgress() signal. Here's the implementation for the sendNewRequest() function.

// This function creates a new network request and sends
// it to the server, and monitors download progress
void ApplicationUI::sendNewRequest ()
    // Create the network request
    QNetworkRequest request = QNetworkRequest();

    QString requestUrl = "https://developer.blackberry.com";

    bool res;

    // Send the network request
    m_pNetReply = m_pNetAccessMngr->get(request);

    if(m_pNetReply != NULL)
        // Show download progress
        res = QObject::connect(m_pNetReply,
                SIGNAL(downloadProgress(qint64, qint64)),
                SLOT(onDownloadProgress(qint64, qint64)));

When we've finished creating a QNetworkRequest, we can set its properties. The only property that's required is the URL. To set the URL, we use the QNetworkRequest::setUrl() function. This function takes one QUrl parameter, which is the URL of the server that your app is connecting to.

Now we're ready to send the network request. As you can also see in the code above, the request is sent with a single line of C++ code, as shown below.

// ...

// Send the network request
   m_pNetReply = m_pNetAccessMngr->get(request);

// ...

The call to QNetworkAccessManager::get() returns a pointer to a QNetworkReply. We use this QNetworkReply to set our m_pNetReply member variable, which is used to update our contact list.

Store the network reply

We must open a QFile to store the network reply content. The network reply content is actually the XML code that makes up our contact list. We save this XML in a file called contacts_list.xml, which we use as the data source for our ListView control.

We use a function, called openFile(), to open a file and save the reply data. This file is used to update the data model of our ListView control. Let's take a closer look at the openFile() function.

// This function opens the file to store the contact list,
// and also updates the ListView control
void ApplicationUI::openFile ()
    if (m_pFileObj->open(QIODevice::ReadWrite))
        // Write to the file using the m_pNetReply object


        // Create a temporary data model using the contents
        // of a local XML file
        XmlDataModel* pDataModel = new XmlDataModel();
        // Set the file path to the downloaded contacts list .xml file
        QUrl fileUrl = "file://" + QDir::homePath() + "/contacts_list.xml";

        // Update the ListView control with the new data model
        m_FileOpenRetries = 1;

        // The progress toast must be canceled to
        // keep it from displaying when this error
        // has occurred


        // Handle file access errors


If an error occurs while the function is trying to open the file to save the XML, the displayFileOpenRetryDialog() function is called. The displayFileOpenRetryDialog() function displays the File Error dialog box to the right, which tells the user that a file access error has occurred.

The File Error dialog box works together with the onFileOpenRetryDialogFinished() function to give the user three chances to retry the file operation. If the file operation succeeds, the app proceeds to retrieve the contact list as expected.

Screen showing the File access error dialog box.

Here's the implementation of the displayFileOpenRetryDialog() function.

void ApplicationUI::displayFileOpenRetryDialog ()
    QString btnMsg = "Retry ";
    btnMsg.append(" of 3");

    SystemDialog* fileOpenRetryDialog = 
                                new SystemDialog(btnMsg, "Cancel");
    fileOpenRetryDialog->setTitle("File Error");
    QString errMsg = 
               "Could not open the file needed for this procedure";

    bool res =

    m_RetryFileOpenIsDisplayed = true;
    m_pCurrentDialog = fileOpenRetryDialog;

Here's the implementation of the onFileOpenRetryDialogFinished() function. As you can see in the sample code shown above, this slot is connected to the File Error dialog box's finished() signal.

// The user has three tries to open the file needed to continue
// and if those retries fail, then the fatalErrorCloseApp()
// function is called to close the app
void ApplicationUI::onFileOpenRetryDialogFinished (
        bb::system::SystemUiResult::Type type )
    m_RetryFileOpenIsDisplayed = false;

    if (m_FileOpenRetries < 3 &&
        type == SystemUiResult::ConfirmButtonSelection)
        m_FileOpenRetries += 1;

        // Retry opening a file
        // Display the 'Exit the app' toast
        SystemToast* exitFileMsg = new SystemToast();

        QString exitMsg = 
               "The app could not open the necessary file needed ";
        exitMsg.append("to update the list data, and will exit");

        bool res = QObject::connect(exitFileMsg,

Each time that the app tries to open a file, one retry is counted in the member variable m_FileOpenRetries. When m_FileOpenRetries is equal to three, it means that all of the retries have failed.

When all of the file operation retries have failed, a toast is displayed to the user to let them know that the app must close. At this time, the onFileOpenDialogFinished() function calls the fatalErrorCloseApp() function to close the app.

Screen showing the file error exit toast.

Here's the implementation of the fatalErrorCloseApp() function that's used to automatically close the app.

void ApplicationUI::fatalErrorCloseApp ()

When the file is successfully open, the Networking Downloading a File sample displays the contact list.

Screen showing the contact list.

Examining the ApplicationUI class

So far, we've explored some of the important UI aspects of the Networking Downloading sample app. Now, let's look at the underlying C++ classes that support the UI, and provide the functionality for the sample app.

The source code files for these classes are located in the src folder in your project.

Let's have a look at the ApplicationUI class. This class provides the functionality for the app, and is defined in the applicationui.hpp and applicationui.cpp files. Open applicationui.hpp and examine the following areas in the code:

  • Slot functions that provide support operations for our app. For example, the app includes an openFile() function that opens a file, stores the contact list in it, and also updates the ListView data model file.
  • Pointers to UI elements that allow us to communicate with them in our C++ code.
  • Utility functions that support numerous operations and behaviors in the sample app. For example, the app includes an updateOnlineStatus() utility function that updates the connection and interface icons that are displayed in the main UI. There are also utility functions that support error handling. For example, the app includes various utility functions that allow the user to recover from a lost connection, or file I/O error.

Open applicationui.cpp. Most of the functions that are implemented in this file are straightforward; several of them, however, are worth looking at. Let's look at the waitForConnection() function.

// Waits for the device to make a connection and
// if it fails to connect, it displays the
// connection retry dialog box

void ApplicationUI::waitForConnection ()
    QTime resumeTime= QTime::currentTime().addSecs(3);

    SystemToast* waitToast = new SystemToast();
    QString waitMsg =
            "Waiting for network connection ... ";

    // Pause the app to wait for a connection

    while( QTime::currentTime() < resumeTime )
       QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

    if(m_pNetConfigMngr->isOnline() == false)

This function prevents a connection recovery dialog box from displaying when the app first starts, and the device is acquiring a connection. We create a QTime variable and use it to pause the app's execution while we wait for the device to acquire a network connection. During this pause, the app displays a toast that tells the user that it's waiting for a network connection. If the device cannot connect to a network, the app displays a connection recovery dialog box which gives the user three chances to re-establish a network connection before the app automatically closes.

Screen of the sample app showing the waiting for connection toast.
Screen of the sample app showing the fatal error toast.

Using the RawHeaderView class

We've looked at the ApplicationUI class, which provides the bulk of the functionality for our sample app. The RawHeaderView class supports the ApplicationUI class. Let's examine some important parts of the RawHeaderView class.

The RawHeaderView class supports the retrieval and display of the raw headers that are present in the QNetworkReply. Open the RawHeaderView.hpp file.

class RawHeaderView : public QObject

        Q_PROPERTY(bool visible 
                   READ visible 
                   WRITE setVisible 
                   NOTIFY visibleChanged)

        RawHeaderView ();
        virtual ~RawHeaderView (){}

        void setVisible(bool visible);
        bool visible() const;

    public Q_SLOTS:
        void show();

        void visibleChanged();

        bool m_dialogVisible;

The RawHeaderView class supports the behavior of the raw header dialog box. For example, a Q_PROPERTY that governs the visibility of the RawHeaderView dialog box is defined. There's a visibleChanged() signal that's emitted when the dialog box's visible property is changed. A slot called show() is used to display the dialog box as needed. A member variable (called m_dialogVisible) is used to keep track of whether the RawHeaderView dialog box is visible or not.

Open the RawHeaderView.cpp file.

RawHeaderView::RawHeaderView () : QObject()
    this->m_dialogVisible = false;

void RawHeaderView::setVisible(bool visible) {
    if (m_dialogVisible == visible)

    m_dialogVisible = visible;
    emit visibleChanged();

bool RawHeaderView::visible() const {
    return m_dialogVisible;

void RawHeaderView::show() {

Notice that the RawHeaderView constructor initially sets the dialog box's visible property to false. Setting its visible property to false prevents the dialog box from displaying when the app first starts.

Let's go back to the ApplicationUI class to examine how the RawHeaderView class is used in the sample app. In the ApplicationUI constructor, we create an instance of the RawHeaderView, and set a derived context from the root QmlDocument node that allows us to access it in our QML.

ApplicationUI::ApplicationUI ( bb::cascades::Application *app ) :
    // ...

    // Instantiate the raw header dialog box

    RawHeaderView *rawHeaderView = new RawHeaderView();
    // To avoid a reference error, this derived context must be
    // defined before your app calls qml->createRootObject

    qml->setContextProperty("_RawHeaderView", rawHeaderView);

    // Create root object for the UI

    AbstractPane *root = qml->createRootObject < AbstractPane >();

    // ...

To avoid a reference error, your derived context must be defined before your app calls qml->createRootObject().

In the ToggleButton control's onCheckedChanged slot, we use the _RawHeaderView derived context reference to set the visible property of the RawHeaderView screen. Setting the visible property this way keeps the RawHeaderView dialog box visible only when the ToggleButton is in the On position.

ToggleButton {
    id: rawHeaderTgl

    // ...

    onCheckedChanged: {
        _RawHeaderView.visible = rawHeaderTgl.checked

Learning more

In this document, you've explored the Networking Downloading a File sample app and learned how to retrieve an XML file containing a contact list from a remote server. You've also examined how to retrieve and manipulate the raw header data that's returned in a QNetworkReply object.

We've introduced several other concepts, such as how to monitor network connection, and discover the interface that the device is using to make a connection. Some of these concepts are interesting enough that you may want to learn more about them. Here are some additional resources that you might find useful as you develop your apps:

Last modified: 2015-03-31

Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus