This is a short guide about how to make packages for the Hildon Application Manager. It is valid for Internet Tablet OS 2006 and later, but not for the old Internet Tablet OS 2005.
The main point to take away is that the Hildon Application Manager ("AM") is a graphical frontend to the standard Debian package management infrastructure, similar to Synaptic, but aimed at a different clientele.
The AM uses the same backend tools as Synaptic, Aptitude, or apt-get (namely libapt-pkg), and it does it in the standard way without imposing any constraints: packages are installed as root and can touch the whole system, for example.
The normal way to distribute a package is therefore to put it into some repository. See the here for more information on how to setup such a repository.
This HOWTO assumes that you are familiar with making .deb
packages.
A good place to start is the Debian New Maintainers'
Guide.
You can freely alternate between the AM and apt-get, say. Changes done to the system via apt-get or dpkg are picked up by the AM without confusing it, and vice versa.
Packages made for the AM should follow a few extra rules, tho, if they want to integrate nicely. These rules are explained below.
All strings coming from the control information of a package are interpreted in UTF-8 when they are shown in the UI. If a string is not valid UTF-8, all bytes above 127 are replaced with '?' before displaying it.
The Application installer in the old Internet Tablet OS 2005 had a
funny way to use the Depends
control field in packages. Starting
with the Internet tablet OS 2006, there is nothing special about the
Depends
control field anymore. It should no longer contain maemo
.
It should now contain all the real dependencies, like
${shlibs:Depends}
, etc.
By default, the AM only shows packages in certain segments to the user. This has been done to hide the existence of the hundreds of system packages that make up the operating system itself. The AM is, at this point, not intended to let the user manage the whole system, only a smaller set of third party applications.
The AM only shows packages in the user segment. Thus, your
Section
field in the control file should be of the form
Section: user/SECTION
where SECTION is arbitrary. SECTION should be a nice capitalised, English word like "Ringtones". There is no support for localising that word yet, unfortunately.
However, there is also a predefined set of sections. If your package fits into one of these sections, you should put it there. This will avoid fragmenting the section names, and the names of these sections will be correctly localised.
The list of predefined sections and their English names is:
user/accessories Accessories user/communication Communication user/games Games user/multimedia Multimedia user/office Office user/other Other user/programming Programming user/support Support user/themes Themes user/tools Tools
Thus, if you want to put your package into the Office section, include the field
Section: user/office
in your control information. If you want to put it into "Ringtones" (which is not pre-defined), use
Section: user/Ringtones
The AM can make use of some additional fields in the control fields of
a package. These fields generally start with a Maemo-
prefix.
The way to get these fields into your .deb files is to include them
with a XB-
prefix in your debian/control file, see the Debian
Policy Manual, section
5.7.
A package can specify a pretty name for itself. This name is displayed in the UI instead of the real package name.
The pretty name is specified with the Maemo-Display-Name
field.
A package can specify a separate description to be used when it is displayed in the "Check for updates" view. This description should talk about what is new in this version of the package.
The upgrade description is specified with the
Maemo-Upgrade-Description
field. It is formatted like the normal
Description
field.
The Maemo-Display-Name
, Description
, and
Maemo-Upgrade-Description
fields can be provided in more than one
language. The Application Manager first looks for a field named
FIELD-LC
where LC
is the value of the LC_MESSAGES
environment
variable, and falls back to just FIELD
when the localized field does
not exist.
For example, when LC_MESSAGES
equals de_DE
, the Application
Manager first tries Description-de_DE
to find the short and long
descriptions of a package.
Note that this way to localize package descriptions is different from what Debian is going to use. Instead of putting all the translations into the package metadata itself, Debian will provide translations in a separate directory of a repository and only the translations for the current language will be downloaded. This is clearly the way to go for a distribution with many packages and for supporting many languages.
In the future, the Application Manager will support this way of translating package descriptions and names as well, but for now, putting everything into the metadata directly is sufficiently easier to do and we shouldn't run into scalability problems just yet.
A package can have an icon that is displayed next to its name by the
AM. Icons are included in the control information of a package as a
base64 encoded field named Maemo-Icon-26
.
The image format of the icon can be anything that is understood by GdkPixbufLoader, but is most commonly the PNG format.
The image should be 26x26 pixels with a transparent background.
Here is an example of a correctly formatted Maemo-Icon-26 field:
Maemo-Icon-26: iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABGdBTUEAAK/INwWK6QAAABl0 RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAALxSURBVHja3FZNTBNREP669J/S XYxtKRWl1JOSFBIPhkitCQeNiaKBmzdj9Ggk0ZOBxHDWixcTjV6MF+WiIB40YEyMBMGYEqQK tLS2lG7pdre0pF3WtxslgJRuD2J0kpfdTN7O976Z782sRpIk7IZR2C2TGW1cv8xaY5WuXLy8 iW5XV5fk8/kkr9e7ya/T6SSNRiOViikvbbmDDD590SusZBGYDiDwJbDud7vdvYIgIJfLYXV1 tSwhrQrSfRX6/26N/j+gkjW6ce06HE4HGEctGuj9oEwUzFYz5ubmEA6HQVEUisUi8vn8b4rd zjRbNxCZrr+3t7XTzjrnvMfdxMi7xj6OIRaPIbWcQjabVdRWKBTkrX4SZ2SjvCtKXf+tkxxD M5MetwfHj/lwwueHy+WCVqvdehdHKq7R6JvbpfNMAGiGhs1mg9ls3sS+4hodbDqCwef9mA9P 7vhhVVWV3BGUOomiaCSufEWMxNwimlweMFYbpoMfyp70J6t8xanLZgWs8Ak07N0Hau0P3qOs wIHnl5FJx2E1WlUFuXrzIS713KusRplMCoLAgl2O4N34ODQ4VRaot6cbUzMRNNQ/w/uJWXWM eH5JARkYHsLQMIe1NZEpB7Sn1uKFhkL3maO4cL5NHVAo+hkPnrzEq2HqQIf/3ICzvr7FXmeH 3qBXlslkgtFoVBS3YfbcKRRFfJpagE6vUwd0//FbjI7mkcvnGoNfg51ORx3sNju+hWYxMxsk jHlF2jJgdXU1DAaDrDx/kQAVRREJlldXo8kJoPlQ8wHSevosFgs5MmE5H0IingDP8eAzPAQC tkJakDz05Hsks+poPzwg6+Luo9chVb2O3Hilv7V6W5nO02cVX3wxjsj3CMKRBUSjUcQWY0iy SQVoi6XJaiQxubKpI02yj2xk6BoaBr0BqXRKCZpYSiCZlIXCguM4pWtvY0ypyUtt87PSIj/t pJ/JICzLKiBLySTYVArpdFrp3DuMhRZVqfvnJ+wPAQYA1hdr5EDqltYAAAAASUVORK5CYII=
A package can specify certain flags, using the Maemo-Flags
field.
Most of these flags are intended for system upgrades.
The value of the Maemo-Flags field should be a comma separated list of one or more of the following words:
reboot
Specifying this flag will reboot the device cleanly after the package has been installed. Also, all applications will be closed before installation and a suggestion is given to the user to make a backup.
system-update
Specifying this flag will tell the AM that this is a meta package that controls operating system updates. The AM will adjust some parts of its UI.
close-apps
The same as 'reboot', for compatibility. Deprecated. (In the past, a package could control individually whether to close all applications, suggest a backup, or reboot. In order to simplify the UI, the three individual choices have been reduced to only one: all of the three actions are either done together, or none is done.)
flash-and-reboot
The same as 'reboot', for compatibility. Deprecated. (In the past, the AM would run /usr/bin/flash-and-reboot after everything else has been done.)
A operation usually involves more than one package and the flags of all packages are merged.
The AM does check if there is enough space before downloading the packages files.
It does not usually check if there is enough free space before installing a package, however. Doing so on a file system implementation that is compressed and very different from the one that has been used to compute the Installed-Size of a package is quite unreliable. Also, installation can take an unknown amount of storage space temporarily. The problem thus is that the Installed-Size doesn't really talk about how much space must be free in order for the installation to succeed.
As a fix, the AM allows you to explicitly specify how much space must
be free by using the Maemo-Required-Free-Space
field. When
performing an installation or update, the values of the
Maemo-Required-Free-Space
fields of all involved packages is summed
and the AM refuses to start the operation when the root partition
doesn't have enough free space.
'Maemo-Required-Free-Space' should not include the size of the .deb package files themselves. The check whether there is enough space or not is done at two points: before downloading the packages, and before installing them.
Before downloading the packages, a check is made whether there is enough space for both the package files plus the required free space from their 'Maemo-Required-Free-Space' fields. The package files are downloaded to one of the available memory cards if necessary to ensure that enough space is available in the root filesystem afterwards.
Once the package files have been downloaded and before they are installed, the second check for the 'Maemo-Required-Free-Space' is performed.
The Hildon Application Manager has its own rules for automatically installing and removing packages in addition to the ones specified by the user. These rules are tuned to give little surprises for simple package management operations, but in turn they are not really useable for complicated things like "apt-get dist-upgrade". When designing the conflicts of your packages, you might want to take these rules into account.
Specifically, the AM will never automatically remove a user package.
If a conflict caused by installing a package could be resolved by removing a package, the AM will not do the removal but will refuse the installation request instead. If you really want to remove a package, Conflict with it, and Replace it. Then the AM will remove it in favor of your package.
When removing a package, all packages that are a direct or indirect dependency of the removed package will be considered for removal. They will in fact be removed when they are a non-user package, have been automatically installed by the AM to satisfy a dependeny, and are no longer needed.
The AM is not very smart in reporting conflicts: when your package conflicts with a non-user package, the problem report by the AM will blame the conflict on that non-user package instead of on the user packages that depend on it.
When the Application Manager runs your maintainer scripts, they have
no controlling terminal; their standard input is connected to
/dev/null. DISPLAY
is set correctly, tho.
The AM collects a transcript of the installation/uninstallation process, including the output of maintainer scripts. However, this output is hidden away in the "Log", and you should not expect users to look there and understand its contents.
Thus, you should try really hard to not fail in your maintainer scripts. This does not mean that you should ignore errors, of course, but that you should only do things that have a very high chance of succeeding. The simpler, the better.
The AM can run a script provided by your package before removing or upgrading it. That script can tell the AM to cancel the operation.
The canonical use for this feature is to warn the user when he tries
to remove or upgrade an application that is currently running. You
can use the utility maemo-application-running
to perform this test.
(See below for details.)
When uninstalling or upgrading a package named PACKAGE, the AM will run the program named
/var/lib/osso-application-installer/info/PACKAGE.checkrm
if it exists. When this program exits with code 111, the operation is cancelled. In all other cases, including when the program terminates with a signal, the operation is carried out.
The arguments given to the *.checkrm program are either
foo.checkrm remove
when the package is going to be removed, or
foo.checkrm upgrade VERSION
when it is going to be upgraded to version VERSION.
There are some utilities available that you can use in your maintainer scripts to interact with the user:
maemo-select-menu-location
maemo-select-menu-location --remove folder
When your package contains a .desktop file and consequently has an entry in the Desktop menu for this file, it can call maemo-select-menu-location in its postinst script to let the user choose a location for the entry.
The "
The way to specify a folder that is provided by the system is by giving its logical name as listed in the /etc/xdg/menus/applications.menu file, NOT by giving its English name. Example logical names are
tanafigames tanafitools tanafiutilities
If you use a folder name that does not yet exist, it is created. In that case, you should NOT use a logical name, since there will likely be no translations available for that logical name. When creating a new folder, use a plain text name in a language that is appropriate. But, try to use existing folders as much as you can.
Thus, if your package installs the file
/usr/share/applications/hildon/foo.desktop
and you want it to go to the "Utilities" menu, you would put this invokation into your postinst script:
maemo-select-menu-location foo.desktop tanafiutilities
If you want it to go into a non-existing folder, use something like
maemo-select-menu-location foo.desktop "Cute hacks"
In order to use maemo-select-menu-location in postinst, you should
include a Depends
on the "maemo-select-menu-location" package.
You might want to skip calling maemo-select-menu-location when merely upgrading as opposed to installing from scratch.
You can use the "--remove" option to remove a folder from the menu. It will only be removed when it is empty. The "folder" parameter is interpeted in the same way as the "default folder", see above.
maemo-application-running -x executable-file
maemo-application-running -d
This utility checks whether the application specified on the commandline is currently running. If it is running, it exits with code 0. If it is not running, it exits with code 1. If some error occured, it exits with code 2.
When using the -x option, the utility checks whether any process is currently executing that file, by looking into /proc/PID/exe.
When using the -d option, the utility uses the given .desktop file to find the service name of the application und queries D-BUS whether this service is currently registered. If there is no service name in the .desktop file, the utility uses the executable file as with the -x option.
[THE -d OPTION HAS NOT BEEN IMPLEMENTED YET. SORRY.]
In order to use maemo-application-running in postinst, you should
include a Depends
on the "maemo-installer-utils" package.
maemo-confirm-text [title] file
Displays the contents of FILE in a dialog with "Ok" and "Cancel" buttons. The default title of the dialog is "License agreement".
When the user clicks "Ok", this utility exits with code 0; when he clicks "Cancel", it exits with code 1; and when an error occurs, it exits with code 2.
The recommended place to call this utility is in the preinst maintainer script of a package. If the user does not agree to the license, the preinst script should fail, thus causing the installation to abort. (XXX - maybe we should recommend using something like debconf for this so that we can get the agreement for a bunch of packages with one dialog.)
(If you show a license agreement in your postinst script, it is probably not a good idea to make the postinst script fail when the user does not agree to the license terms. Instead, you could configure your application in such a way that it will ask the user to agree to the license agreement again when the application is started and refuse to run when he disagrees.)
In order to use maemo-confirm-text in postinst, you should include a
Depends
on the "maemo-installer-utils" package.
maemo-list-user-packages
Lists all packages that the user can manage with the Application installer in this format
name TAB version TAB section-field TAB installed-size NL
where 'section-field' is the value of the "Section:" field for the package.