Working with the file system

The data files that you work with in your apps are stored in the file system on the device. Different file system locations have different permissions; in some areas, you can create new files to store your app data, while in others, you can only load data from existing files. If you want to access your data files using the method that works best for you, you need to understand where your data files are located in the file system.

Before you can do any work in the file system on the device, you should make yourself familiar with the working directory. The working directory is where your application is started, and is also known as the current directory and the sandbox. Access to files and folders in the working directory is governed by UNIX-style groups and permissions.

Data files that you package with your app (when you compile the app) are located in the assets folder in the file system. Your app has read-only access to this folder, which means that you can load data from files in this location, but you can't save new data in these files. When you create new data files dynamically while your app is running, they are stored in the data folder. Your app has full read-write access to this folder, so you can load and save data using files in this location.

Applications cannot create new folders or files in the working directory; they can only access the folders listed below. To access shared folders, the access_shared permission must be set in the bar-descriptor.xml file.

In addition to the ones mentioned above, here are some more folders that you should make yourself familiar with.

The BlackBerry 10 file system

Folder Description Access

app

Contains files installed with your application. These files are packaged with your .bar file.

Read-only

app/native

Contains the application binary and other application resources.

Read-only

app/native/assets

Contains application assets, such as QML files, images, and media.

Read-only

data

Contains the application's private data. This is the application's "home" directory.

Read-write

db

Contains the application's database files.

Read-only

logs

Contains system logs for an application. stderr and stdout are redirected to this directory.

Read-write

shared

Contains subfolders that contain shared data grouped by type. An application can write to subfolders of this directory only if the access_shared permission is specified.

Read-only

shared/books

Contains eBook files that can be shared among applications.

Read-write

shared/camera

Contains images taken using the Camera application that can be shared among applications.

Read-write

shared/documents

Contains documents that can be shared among applications.

Read-write

shared/downloads

Contains web browser downloads that can be shared among applications.

Read-write

shared/Dropbox

Contains files located in the user's Dropbox account.

Read-write

shared/misc

Contains files that don't belong in any other category. These files can be shared among applications.

Read-write

shared/music

Contains music files that can be shared among applications.

Read-write

shared/photos

Contains photos that can be shared among applications.

Read-write

shared/print

Contains news and print articles that can be shared among applications.

Read-write

shared/videos

Contains videos that can be shared among applications.

Read-write

shared/voice

Contains audio recordings that can be shared among applications.

Read-write

sharewith

Contains files that the application can share with other applications by using the Invocation framework.

Read-write

tmp

Contains the application's temporary working files. The application should remove these files regularly. The BlackBerry 10 OS may remove these files when the application isn't running.

Read-write

Navigating the file system

If you need to do any work in the file system, you should make yourself familiar with the Target File System Navigator view in the IDE. This view provides a clear look at the device file system and the application sandbox.

To open the Target File System Navigator in the IDE, click Window > Show View > Target File System Navigator. By default, it should open in the bottom pane, beside the Console tab.

Screen showing the filesystem navigator.

Within this view, you can explore the target and the working directories for the applications you've loaded.

When it comes to QML development, this view can come in handy. If you want to, you can edit QML directly on the target, instead of editing it in the IDE and reloading the application. Changes that you make on the target aren't propagated back to your project though, so you must ensure that you make the same changes in the project.

The working directory

The working directory (also known as the current directory or the sandbox) is the root directory for your application. It contains all the files installed with your application, provides a location for you to store additional content, and provides access to a number of shared folders accessible to all applications. Applications cannot create new directories or files at the root of the working directory, but they can in its subfolders.

If your application needs to access the working directory in any way, you can handle these interactions using the  QDir class. The QDir class provides the application with access to directory structures and their contents. A QDir is used to manipulate path names, access information regarding paths and files, and manipulate the underlying file system. You can access directories and files by using either absolute paths or relative paths.

If you need the absolute path to a directory, QDir provides some static functions that return absolute paths to a number of common directories:

  • currentPath(): Returns a path to the application's working directory.
  • homePath(): Returns a path the application's home directory (the data directory).
  • tempPath(): Returns a path to the application's temp folder (the tmp directory).

For example, calling QDir::homePath() returns the following path: "/accounts/1000/appdata/namespace.application/data".

Creating new files and directories

When working in the file system, you can change directories by using the cd() and cdUp() functions.  QDir includes the mkdir() and mkpath() functions, which allow you to create new directories (provided that you do so in a location that allows for writing).

When you create a new QDir object, it defaults to the application's working directory, so any paths that you specify should be relative to that directory. Here's how you can create a files/text directory within the data directory, and then switch to that directory.

QDir dir;
dir.mkpath("data/files/text");
dir.cd("data/files/text");

Reading and writing a file in the working directory can also be done rather easily. Here's how to create a QFile and write to it. The file is stored in the new directory, using a path relative to the application working directory.

QFile textfile("data/files/text/newfile.txt");
textfile.open(QIODevice::WriteOnly | QIODevice::Text);
QTextStream out(&textfile);
out << "This is a text file\n";
textfile.close();

And here's how to read the contents of the file and display it in the console:

if (textfile.open(QIODevice::ReadOnly | QIODevice::Text))
{
    QTextStream stream ( &textfile );
    QString line;
    do {
        line = stream.readLine();
        qDebug() << line;
    } while (!line.isNull());
}
textfile.close();

The assets directory

Any assets that you have in your application (for example, images, sounds, QML files, and so on) must be kept in the assets folder in your project. In the file system, content in the assets folder for an application can be found in the app/native/assets directory.

Since they're packaged with the application, assets are generally considered to be always available and immediately ready to be displayed, unlike other types of content that might be generated by the application or retrieved from a remote location. For more information about loading images from the assets directory, see Image assets.

Here are some basic examples of how to load images from the assets directory. Each of the images need to be stored at the root of the assets directory in your project.

QML

// An image loaded as an asset
ImageView {
    imageSource: "asset:///image.png"   
}

C++

// An image loaded as an asset
ImageView *view = ImageView::create()
    .image(QUrl("asset:///image.jpg"));

The shared directory

The shared folder contains a set of subfolders that contain shared data grouped by type.

An application only has read access in this directory, but it can read and write to subfolders if the correct permission is applied.

To give your application write access to the shared subfolders, you must set the Shared Files permission (access_shared) in your bar-descriptor.xml file.

Screen showing the Shared Files check box.

For example, if you're creating a picture viewer application, you might want to be able to access the files in the shared/camera directory.

Here are some examples of how to load an image from the shared directory using absolute paths:

C++

// Retrieve the path to the app's working directory
QString workingDir = QDir::currentPath();

// Load the image asynchronously
Image image = Image(QUrl("file://" + workingDir + 
        "/shared/camera/camera0001.jpg"));

QML

Since you can't use the functionality in QDir from QML, you must retrieve the path to the device home directory in C++ and expose it to QML using a context property.

// ApplicationUI.cpp

// Load the QML file
QmlDocument *qml = QmlDocument::create("asset:///main.qml");

// Retrieve the path to the app's working directory
QString workingDir = QDir::currentPath();

// Build the path, add it as a context property, and expose
// it to QML
QDeclarativePropertyMap* dirPaths = new QDeclarativePropertyMap;
dirPaths->insert("camera", QVariant(QString(
        "file://" + workingDir + "/shared/camera/")));
qml->setContextProperty("dirPaths", dirPaths);
// main.qml

// Load the image asynchronously
ImageView {
    imageSource: dirPaths.camera + "camera0001.jpg"
}

Copying files to a read-write directory

A common app requirement is to copy a file from the assets directory to a read-write directory so the app can modify the data. There is no convenience function for copying data from the assets directory, but you can copy files by using QFile::copy.

The following code sample copies a file from the assets directory to the data directory and reports the result using the qDebug() function.

QString myFile = "mydata.json";
bool ok = QFile::copy( "app/native/assets/" + myFile, "data/" + myFile);
qDebug() << "Copy of JSON file success=" << ok;

Here is an example of copying a database from the assets directory to the shared/misc directory:

QString myDB = "mydata.db";
bool ok = QFile::copy( "app/native/assets/" + myDB, "shared/misc/" + myDB);
qDebug() << "Copy of database file success=" << ok;

Copying to any of the shared directories requires "access_shared" permission in bar_descriptor.xml file.

The current directory is always the application working directory. You can retrieve the current directory by calling QDir::currentPath() if necessary. The following code sample copies an iCal file from the assets directory to the shared directory using QDir::currentPath() and QFile::copy():

QString filePath = QDir::currentPath() + "/app/native/assets/business.ics";
QString newPath = "/accounts/1000/shared/misc/business.ics";
qDebug() << "Result of copy: " << QFile::copy(filePath, newPath);

Copying with QFile::copy() does not overwrite an existing file. You can either use QFile::exists() to check for the file and QFile::remove() to delete it before copying, or you can change the upload settings in the Momentics IDE for BlackBerry. To change the upload settings in the Momentics IDE:

  1. On the Run menu, click Run Configurations.
  2. In the Upload tab, select "Uninstall, then install application BAR file (clean install)."

Your app is uninstalled each time you deploy your app, and you shouldn't have to check for and remove existing files manually.

Last modified: 2014-05-14



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

comments powered by Disqus