File system access

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 app 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 at the root of the working directory; they can access only the folders listed below.

The BlackBerry 10 file system

In the Momentics IDE for BlackBerry, in the Target File System Navigator view, the application working directory is indicated by the Sandboxes/<appname> directory.

Folder Description

app

read-only

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

app/native

read-only

Contains the application binary and other application resources.

app/native/assets

read-only

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

data

read-write

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

db

read-only

Contains the application's database files.

logs

read-write

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

shared

read-only

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.

shared/books

read-write

Contains eBook files that can be shared between applications.

shared/camera

read-write

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

shared/documents

read-write

Contains documents that can be shared between applications.

shared/downloads

read-write

Contains web browser downloads that can be shared between applications.

shared/Dropbox

read-write

Contains files located in the user's Dropbox account.

shared/misc

read-write

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

shared/music

read-write

Contains music files that can be shared between applications.

shared/photos

read-write

Contains photos that can be shared between applications.

shared/print

read-write

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

shared/videos

read-write

Contains videos that can be shared between applications.

shared/voice

read-write

Contains audio recordings that can be shared between applications.

sharewith

read-write

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

tmp

read-write

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.

Prerequisites

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.

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 of the files installed with your application, provides a location for you to store additional content, and provides access to a number of shared folders that are accessible to all applications. Applications cannot create new directories or files at the root of the working directory, but they can in some of its subfolders.

If you need the absolute path to a particular directory, you can retrieve it in a couple of different ways. In Cascades, the QDir::currentPath() function returns a path to the application working directory. In C, getcwd() returns the same path. The paths that these functions return have the following format: /accounts/1000/appdata/<namespace.application> .

Cascades also provides functions for retrieving the path to the app's data directory using QDir::homePath() and its tmp directory using QDir::tempPath(). To access these directories using C, you must call getcwd() to get the application working directory and use string concatenation to build the full paths yourself.

Creating new files and directories

Here's an example that shows how to create a new directory in the application working directory, create a file in the new directory, and read the file.

Not applicable

#include <QDir>
#include <QDebug>
#include <QStringList>
#include <QTextStream>
// Create a new directory called files/text in the data directory.
QDir dir; // New QDir objects default to the application working directory.
dir.mkpath("data/files/text");

// Create a file in the new directory and writes to it
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();

// Read the contents of the file and displays 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 app (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.

Because 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.

Cascades has a shortcut that you can use to retrieve the path to the assets directory. To reference items in the assets directory, append the file name of your asset to asset:///. To reference assets in C, you must use string concatenation to build the full path yourself.

Here are some examples of how to load items from the assets directory. The items need to be located at the root of the assets directory in your project.

import bb.cascades 1.0

ImageView {
    imageSource: "asset:///image.png"   
}
#include <bb/cascades/ImageView>
using namespace bb::cascades;
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 access the files in the shared/camera directory. Here's an example of how to load items from the shared directory using absolute paths:

Because 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"
}
#include <bb/cascades/Image>
using namespace bb::cascades;

#include <QDir>
#include <QString>
// 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"));

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. Here are some different examples for copying to various directories.

Copying to any of the shared directories requires the Shared files (access_shared) permission in your bar_descriptor.xml file.

Not applicable

#include <bb/cascades/Image>
using namespace bb::cascades;

#include <QDir>
#include <QFile>
#include <QString>
// Copy a JSON file from the assets directory to the data directory
QString myFile = "mydata.json";
bool ok = QFile::copy( "app/native/assets/" + myFile, "data/" + myFile);
qDebug() << "Copy of JSON file success=" << ok;

// Copy 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;

// Copy an ICS file from the assets directory to the shared directory
// using currentPath() to retrieve the application working directory
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. On the Upload tab, select the Uninstall, then install application BAR file (clean install) check box.

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

Last modified: 2014-09-30



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

comments powered by Disqus