What is packaging?

Packaging prepares and packages all files required to deploy an app onto a mobile device.

In other words, packaging involves identifying what files are needed for the app, organizing those files, and creating a package file that can be deployed to the app. The specifics are summarized in the following paragraphs.

Directories involved

When you create a mobile app, and when you prepare for packaging, there are three directory structures that you must understand and manage.
Source directory structure
There is a directory structure containing the app sources. These are your source files - 4gl files, form definition files, image files, and so on.
Target directory structure
There is a directory structure containing the compiled binary files. As part of the compilation process, the compiled binaries are placed in target directories. In Genero Studio, you specify this location with the Target directory property. You specify this property for group nodes, application nodes, and library nodes.
Root directory structure
There is a directory structure containing the files needed on the mobile device. The mobile device or platform will have rules on what structure is allowed. The top-level directory in this structure is known as the Root directory (rootdir). In Genero Studio, the Root directory is defined as a property of the Package node. All file that needs to be deployed to the mobile device must sit under the Root directory.

The goal of packaging

To package your app, start by having an inventory of all files needed to run the app on the mobile device. Some of these files will be in your source directory structure (such as image files), while others will sit in your target directory structure (the compiled binary files).

You must also define the directory structure you will need to create in the Root directory for your mobile device. This may sound complicated, but in reality it is quite simple. For both the Android and iOS devices, you can place all of the files required into a single folder. If you examine the default packaging nodes provided when you create a new BAM Mobile Project (.4pw), you see that all files end up in the directory $(ProjectDir)/bin, which is the packaging Root directory. You could build a more complex Root directory structure, however it is not necessary.

Once you have your inventory of required files and your plan for the directory structure on your device, you can build your packaging node.

In the Package node, you define the Root directory and specify which platform the package is for.

Under the Package node, you create a Directory node for each directory you need to retrieve files from. You will have multiple Directory nodes, where each Directory node serves a purpose: locating the binaries, database files, fglprofile, images and so on.
Important: It is not sufficient to physically put a file in the Root directory on disk to have it included in the final package. Any file you want to include in the package must be listed as a source file in one of the directory nodes.

The Source directory indicates where the files exist prior to packaging, the Destination directory indicates where the files will be located in the package. The Destination directory must be located within the Root directory. In the Directory node, the Included files and Excluded files properties tell which files from the Source directory to include or exclude, based on filtering criteria (such as the filename or file extension).

During the packaging process, the files are copied from the source directory to the Destination directory, if these directories differ.
Note: If you examine the default packaging nodes provided when you create a new BAM Mobile Project (.4pw), you will see many Directory nodes where both the Source and Destination directories specify $(ProjectDir)/bin. Having the Source and Destination specify the same directory allows for packaging optimization, by not requiring files to be copied from one directory to another. Files are only copied when then are moving to a different directory. You can define separate Source and Destination directories, however the packaging process would not be optimized as a complete directory copy would be required each time the package is built.

Have your program move files into a read-write (writable) directory

If you create a flat file to hold all the files required by the app, a flat file is created on the mobile device. This is what is done by the default packaging nodes when you create a new BAM Mobile Project (.4pw).

For your Android applications, this works out-of-the-box. After the package is deployed to the device, it is unpacked into a single directory on the device. This is a read-write directory, which means that any file that need to be writable (such as a database file) can be updated by the app.
Warning: If you redeploy an Android application, ALL files are overwritten, to include files such as a database file. You must take this into account as you plan your application upgrades, and handle any upgrade strategy in your app.

For your iOS applications, however, the directory created and holding the app files is a read-only directory. If there exists writable files that need to be updated by the app (such as a database file), those files must be placed into a read-write directory on the device. Moving files from the read-only directory to a read-write directory is not something handled by packaging. You must handle it within your app.

You are provided with two APIs that allow you to reference the underlying directories transparently:
  • The base.Appliation.getProgramDir() method returns the base program directory, storing your compiled files, an initial database file, and so on. On an iOS device, this is a read-only directory.
  • os.Path.pwd() defines a writable directory for holding writable files, such as an error log or the user database.

At deployment, when your application initially starts, we recommend that you copy the writable files from the application directory (using the function base.Application.getProgramDir()) to the current working directory (using the function os.Path.pwd()).

For an example, open the OfficeStoreMobile demo project, open the OrdersApp.4gl intermediate file, and look for the OrdersApp_install function. In this function, the os.Path.copy method is used to copy a database file from the read-only source directory to the read-write destination directory.

Warning: Take care that you do not use the same file name for a read-only resource and a read-write resource. Using the same name for both can lead to problems.

Create the user database in a writable directory

In addition to simply copying writable files, one of the first things your app needs to do is create the user database. This database may use the initial database file when creating the user database, or it may create one with a different schema for the user.

For an example, open the OfficeStoreMobile demo project, open the OrdersApp.4gl intermediate file, and look for the OrdersApp_install function. In this function, the os.Path.copy method is used to copy a database file from the read-only source directory to the read-write destination directory.

App initial deployment versus App upgrade

The example provided by the OrdersApp.4gl example needs to be evaluated in terms of initial installation and in terms of future upgrades to the application. This example solves how to initially place the file in the read-write directory. It does NOT cover an upgrade strategy. The developer needs to ensure that any new files need to be written to the read-write directory are written, that files that should not be overwritten are not overwritten, and that files that need to be updated or merged or replaced are handled. See Manage App updates.