app.nit, a framework for portable applications

The framework provides services to manage common needs of modern mobile applications:

  • Life-cycle
  • User interface
  • Persistence
  • Async HTTP requests
  • Package metadata
  • Compilation and packaging

The features offered by app.nit are common to all platforms, but may not be available on all devices.

Application Life-Cycle

The app.nit application life-cycle is compatible with all target platforms. It relies on the following sequence of events, represented here by their callback method name:

  1. on_create: The application is being created. You should build the UI at this time and launch services.

  2. on_resume: The app enters the active state, it is in the foreground and interactive.

  3. on_pause: The app becomes inactive and it leaves the foreground. It may still be visible in the background.

  4. on_stop: The app is completely hidden. It may then be destroyed (without warning) or go back to the active state with on_restart.

  5. on_restart: The app goes back to the inactive state. You can revert what was done by on_stop.

_app.nit_ life-cycle

Life-cycle events related to saving and restoring the application state are provided by two special callback methods:

These events are synchronized to the native platforms applications The App instance is the first to be notified of these events. Other UI elements, from the ui submodule, are notified of the same events using a simple depth first visit. So all UI elements can react separately to live-cycle events.

User Interface

The ui module defines an abstract API to build a portable graphical application. The API is composed of interactive Controls, visible Views and an active Window.

Here is a subset of the most useful controls and views:

Each control is notified of input events by callbacks to on_event. All controls have observers that are also notified of the events. So there is two ways to customize the behavior on a given event:

Usage Example

The example at examples/ui_example.nit shows off most features of ui in a minimal program. You can also take a look at the calculator (../../examples/calculator/src/calculator.nit) which is a concrete usage example.

Platform-specific UI

You can go beyond the portable UI API of app.nit by using the natives services of a platform.

The suggested approach is to use platform specific modules to customize the application on a precise platform. See the calculator example for an adaptation of the UI on Android, the interesting module is in this repository at ../../examples/calculator/src/android_calculator.nit

Persistent State with data_store

app.nit offers the submodule data_store to easily save the application state and user preferences. The service is accessible by the method App::data_store. The DataStore itself defines 2 methods:

  • []= saves and associates any serializable instances to a String key. Pass null to clear the value associated to a key.

  • [] returns the object associated to a String key. It returns null if nothing is associated to the key.

Usage Example

import app::data_store

redef class App
    var user_name: String

    redef fun on_save_state
    do
        app.data_store["first run"] = false
        app.data_store["user name"] = user_name

        super # call `on_save_state` on all attached instances of `AppComponent`
    end

    redef fun on_restore_state
    do
        var first_run = app.data_store["first run"]
        if first_run != true then
            print "It's the first run of this application"
        end

        var user_name = app.data_store["user name"]
        if user_name isa String then
            self.user_name = user_name
        else self.user_name = "Undefined"

        super
    end
end

Async HTTP request

The module http_request provides services to execute asynchronous HTTP request. The class AsyncHttpRequest hides the complex parallel logic and lets the user implement methods acting only on the UI thread. See the documentation of AsyncHttpRequest for more information and the full example at examples/http_request_example.nit.

Metadata annotations

The app.nit framework defines three annotations to customize the application package.

  • app_name takes a single argument, the visible name of the application. This name is used for launchers and window title. By default, the name of the target module.

  • app_namespace specifies the full namespace (or package name) of the application package. This value usually identify the application uniquely on application stores. It should not change once the application has benn published. By default, the namespace is org.nitlanguage.{module_name}.

  • app_version specifies the version of the application package. This annotation expects at least one argument, usually we use three version numbers: the major, minor and revision. The special function git_revision will use the prefix of the hash of the latest git commit. By default, the version is 0.1.

  • app_files tells the compiler where to find platform specific resource files associated to a module. By default, only the root of the project is searched for the folders android and ios. The android folder is used as base for the generated Android project, it can be used to specify the resource files, libs and even Java source files. The ios folder is searched for icons only.

    Each argument of app_files is a relative path to a folder containing extra android or ios folders. If there is no arguments, the parent folder of the annotated module is used. In case of name conflicts in the resource files, the files from the project root have the lowest priority, those associated to modules lower in the importation hierarchy have higher priority.

Usage Example

module my_module is
    app_name "My App"
    app_namespace "org.example.my_app"
    app_version(1, 0, git_revision)
end

Compiling and Packaging an Application

The Nit compiler detects the target platform from the importations and generates the appropriate application format and package.

Applications using only the portable services of app.nit require some special care at compilation. Such an application, let's say calculator.nit, does not depend on a specific platform and use the portable UI. The target platform must be specified to the compiler for it to produce the correct application package. There is two main ways to achieve this goal:

  • The mixin option (-m module) imports an additional module before compiling. It can be used to load platform specific implementations of the app.nit portable UI.

    # GNU/Linux version, using GTK
    nitc calculator.nit -m linux
    
    # Android version
    nitc calculator.nit -m android
    
    # iOS version
    nitc calculator.nit -m ios
    
  • A common alternative for larger projects is to use platform specific modules. Continuing with the calculator example, it is adapted for Android by the module android_calculator.nit. This module imports both calculator and android, it can then use Android specific code.

    module android_calculator
    
    import calculator
    import android

All subgroups and modules

module app

app :: app

app.nit is a framework to create cross-platform applications
module app_base

app :: app_base

Base of the app.nit framework, defines App
module assets

app :: assets

Portable services to load resources from the assets folder
module audio

app :: audio

Services to load and play Sound and Music from the assets folder
module data_store

app :: data_store

Key/value storage services
group doc

app > doc

group examples

app > examples

module http_request

app :: http_request

HTTP request services: AsyncHttpRequest and Text::http_get
module ui

app :: ui

Portable UI controls for mobiles apps
package_diagram app\> app core core app\>->core serialization serialization app\>->serialization pthreads pthreads app\>->pthreads json json app\>->json serialization->json poset poset serialization->poset meta meta serialization->meta pthreads->core ...poset ... ...poset->poset ...meta ... ...meta->meta ...json ... ...json->json android android android->app\> android\>ui\> ui android->android\>ui\> android\>ui\>->app\> app\>examples\> examples app\>examples\>->app\> gamnit gamnit gamnit->app\> gamnit->android gamnit\>flat\> flat gamnit->gamnit\>flat\> ios ios gamnit->ios linux linux gamnit->linux gamnit\>flat\>->app\> ios->app\> ios\>ui\> ui ios\>ui\>->app\> linux->app\> app app app->android egl egl egl->android glesv2 glesv2 glesv2->android app... ... app...->app egl... ... egl...->egl gamnit... ... gamnit...->gamnit glesv2... ... glesv2...->glesv2 android\>examples\>src\> src android\>examples\>src\>->android\>ui\> android\>examples\>src\>... ... android\>examples\>src\>...->android\>examples\>src\> gamnit\>depth\> depth gamnit\>depth\>->gamnit\>flat\> gamnit\>virtual_gamepad\> virtual_gamepad gamnit\>virtual_gamepad\>->gamnit\>flat\> gamnit\>depth\>... ... gamnit\>depth\>...->gamnit\>depth\> gamnit\>virtual_gamepad\>... ... gamnit\>virtual_gamepad\>...->gamnit\>virtual_gamepad\>

Ancestors

group codecs

core > codecs

Group module for all codec-related manipulations
group collection

core > collection

This module define several collection classes.
group meta

meta

Simple user-defined meta-level to manipulate types of instances as object.
group parser_base

parser_base

Simple base for hand-made parsers of all kinds
group poset

poset

Pre order sets and partial order set (ie hierarchies)
group text

core > text

All the classes and methods related to the manipulation of text entities

Parents

group core

core

Nit common library of core classes and methods
group json

json

read and write JSON formatted text
group pthreads

pthreads

POSIX Threads support
group serialization

serialization

Abstract serialization services

Children

group android

android

Android platform support and APIs
group examples

app > examples

group flat

gamnit > flat

Simple API for 2D games, built around Sprite and App::update
group gamnit

gamnit

Portable game and multimedia framework for Nit
group ios

ios

iOS support for app.nit
group linux

linux

Implementation of app.nit for the Linux platform
group ui

ios > ui

Implementation of app::ui for iOS
group ui

android > ui

Views and services to use the Android native user interface

Descendants

group bundle

android > bundle

A mapping class of String to various value types used by the
group depth

gamnit > depth

gamnit depth, a framework to create portable 3D games in Nit.
group egl

egl

Interface between rendering APIs (OpenGL, OpenGL ES, etc.) and the native windowing system.
group examples

ios > examples

group glesv2

glesv2

OpenGL graphics rendering library for embedded systems, version 2.0
group intent

android > intent

Services allowing to launch activities and start/stop services using
group notification

android > notification

Services to show notification in the Android status bar
group service

android > service

Android service support for app.nit centered around the class Service
group shared_preferences

android > shared_preferences

Services allowing to save and load datas to internal android device
group src

android > examples > src

group virtual_gamepad

gamnit > virtual_gamepad

Virtual gamepad mapped to keyboard keys for quick and dirty mobile support