Warning: A new installer the WebInstaller is now available as an alpha version. The Webinstaller works on Chrome based browsers as it requires WebUSB. The EasyInstaller will be deprecated soon, hence moving forward we will not proceed with any error fixes on it

/e/OS easy-installer Build documentation

Tools required to build

The team member who developed the easy-installer used

  • Netbeans 11.3 (/!\ netbeans 11.0 doesn’t work properly with javaFX)
  • Gradle 4.10
  • OpenJFX11+: doc
  • Java JDK 11+

How to clone the project

Run this command in a terminal

git clone https://gitlab.e.foundation/e/tools/easy-installer.git

How to build

Open a terminal at the root of the project prompt: ./gradlew dist

Note: “dist” for “distribution”

Result

It will create 3 zipped artifacts, zipped together in a single archive :

  • linux-x64
  • windows-x64
  • mac

Location of the artifacts :

Zipped build : “/build/distributions/”

Unzipped build : “/build/image/”

What does this command do?

Compiled java version is provided from “buildSrc” folder. There is one version for each platform (windows, osx, linux). That will allow to have an installation free application. thanks to java 9+, it only includes required modules.

99% of the job is done by the “badass jlink plugin” (see section below). The remaining 1% consist of:

  • copying ADB
  • copying heimdall
  • copying fastboot
  • flash’s scripts

from “buildSrc” and “flash-scripts” folders into the build.

What is used to make the build ?

It uses the “badass jlink plugin”

Warning: A new installer the WebInstaller is now available as an alpha version. The Webinstaller works on Chrome based browsers as it requires WebUSB. The EasyInstaller will be deprecated soon, hence moving forward we will not proceed with any error fixes on it

Feature idea

  • Add support for a new device
    • You need to own the device
    • First step is to create configuration files for the Easy Installer
    • If necessary, create the missing scripts to be able to achieve the installation
  • make ./gradlew dist to create a build for one platform at a time depending on a param. i.e: ./gradlew dist windows or ./gradlew dist linux

How to support or add a new device ?

The easy-installer uses two configuration files for each device.

note: We are using herolte (Samsung galaxy S7) as an example here

The config files are located in “src/main/resources/yaml/” folder.

src
--main
----java
----resources
------css
------fonts
------fxml
------images
------instructions
------lang
------yaml
--------**herolte.yml**
--------**herolte_fs.yml**

1. First file: .yml

The first file “herolte.yml” defines the flashing process. The file is a YAML resource.

Structures and nodes of the file

name: herolte
flash:
    f1:
        script: wait-download
        parameters:
            heimdall_folder_path: ${HEIMDALL_FOLDER_PATH}
        codes:
            ok:
                0: ~
            ko:
                1: script_error_waitDownload_1
        output: ~
        succeed: f2
        failed: ~  
    f2:
        script: oem-unlock
        parameters:
            heimdall_folder_path: ${HEIMDALL_FOLDER_PATH}
        codes:
            ok:
                0: ~
            ko:
                10: script_error_oemUnlock_10
        output: ~
        succeed: f3
        failed: ~
...
  • Name defines the codename of the device. This value is a simple String. example: herolte for S7, hero2lte for S7 edge, dreamlte for S8, …

  • f1 is the step key (it identifies the step). The value is the step defined by following elements:

  • script contains the name of the flash-script to call. There is no extension because it is defined at runtime (this allows to use either “.sh” for linux and mac or “.bat” for windows)
  • parameters contains a map of parameters to use when the script is called. The order should be the one expected by the script. There are two types of values for a parameter:

    1. a fixed parameter which is a raw string. example: my_key: foobar
    2. a changing parameter which is defined at runtime. Then its value must be the key - in uppercase - wrapped in ‘{‘ and starts with ‘$’. example: my_key: ${MY_KEY}
  • codes contains two sub lists: ok corresponds to script’s exit when the step succeeds, and ko corresponds to script’s exit when there is an error. The codes returned by the script are always numeric value. The ko codes can be defined with an error message which will be displayed to the user if it happened.

    example: 10: script_error_oemUnlock_10.

    The error message is a key corresponding to a value in the translations file (src/main/resources/lang/traduction.properties)

  • output can be used to define a variable than must be read from the last line of the running script. example: output: ${MY_KEY} corresponds to a step where the installer should read the last line provided by the script and store it in a java variable “MY_KEY” which would be used in a later step. The value of output is always structured like a changing parameter.

  • succeed specifies the next step’s code after a success.

  • failed: defines the next step’s code to call after a failure.

Special step:

    f7:
        script: askAccount
        parameters: ~
        codes: ~
        output: ~
        succeed: f8
        failed: ~

This is the only step which is empty. There is no script “askAccount”. It is used by easy-intaller to know when to show the UI which lets the user request an invitation email to create an account. Please always add this step before the last step.

2. Second files: _fs.yml

This second file specifies extra data (which aren’t optional)

Structures and nodes of the file

sources:
   rom:
        url: https://images.ecloud.global/stable/herolte/e-latest-herolte.zip
        filePath: e-latest-herolte.zip
   twrp:         
        url: https://images.ecloud.global/stable/twrp/herolte/twrp-3.2.3-0-herolte.img
        filePath: twrp-3.2.3-0-herolte.img
flash:
    f1:
        ui:
            type: action
            title: stepTitle1On7
            instruction:
            - install_instr_turnOff
            - install_instr_startDownload
            - install_instr_acceptWarning
            stepNumber: 1/7
            titleIcon: Download.png
            instructionImg: group2.png
    f2:
        ui:
            type: load
            title: stepTitle2On7
            instruction:
            - install_instr_oemUnlock
            stepNumber: 2/7
            averageTime: 8
...

It contains two parts: sources which specifies files that need to be downloaded and flash which defines UI for the different steps.

sources

Each different files that needs to be downloaded should be specified here. Use a key to identify it : example: rom, twrp, vendor, patch, …

  • url specifies the url that points to the resource. example: url: https://path/to/the/file.extension

-filePath specifies the file’s name on the user’s computer once it has been downloaded

/!\ files must have a sha256sum to check integrity. The sha256 should be the exact filename(with extension) +”.sha256sum”. The sha256sum should be in the same folder as the target file. It will be automaticaly downloaded.

flash

Uses the exact same key as in the first file. They must be identical.

ui contains an element which defines what is displayed during the step.

There are three types of UI (user interface): action, load and askAccount

action type

It corresponds to the step where the user has to perform an action (like pressing button).

It has the following structure:

            type: action
            title: stepTitle1On7
            instruction:
            - install_instr_turnOff
            - install_instr_startDownload
            - install_instr_acceptWarning
            stepNumber: 1/7
            titleIcon: Download.png
            instructionImg: group2.png
  • title contains the translations’ key for the step’s title. The value is defined in src/main/resources/lang/traduction.properties

  • instruction are translations’ keys for the instruction at this step. Their values are defined in src/main/resources/lang/traduction.properties It is also used to identify pictures to display along with the instruction. Pictures are defined like instructions’ text but are locatd in src/main/resources/instructions/imageName.properties

  • stepNumber defines the step place in the process

  • titleIcon is displayed left to the title value

  • instructionImg is ignored and will be removed soon.

load type

            type: load
            title: stepTitle2On7
            instruction:
            - install_instr_oemUnlock
            stepNumber: 2/7
            averageTime: 8
  • title is the same as for action type

  • instruction is the same as for action type except that it must have only one instruction.

  • stepNumber is the same as for action type.

  • averageTime defines the averageTime the step is required to do its job. it is in second.

askAccount type

It’s a special type, which only contains type: askAccount. Its step key (f) should fit with the one which defines "script: askAccount" in the first file.

Good practice:

  • ’~’: is used for empty or null value.
  • defines “normal” step code with ‘f’ and a incremental number. It helps to understand the whole process.
  • defines “failure” step code with ‘e’ and a incremental number. It helps to understand the whole process.

Lets make the translation file

What is the translation file?

A translation file has extension “.properties”.

It also contains country code & local lang code before the extension and is separated by "_".

Base name is: translation.

The complete name is:

  • translation.properties for the default translation’s file. This file will be used when no translations are found in a specific language.
  • translation_xx_XX.properties It is a language specific translation’s file. i.e : translation_fr_FR.properties.

It is stored in the project and build with the App. To update translation, we need to rebuild the application.

Contents of the translation file

The content of a translation file is not limited in size.

_one row = one translation

a Row is structured with the following pattern: reference=value

  • reference is the code used to load the value.
  • value is the raw text that will be display to the user

example: trad_1_title=first title of the translation

note: if you add a space between the = and the first character of your translation, the displayed message will include this space too. But you can add a space between the reference and the = without any problem.

a. Line break

In most case, you should let the application decide to break line or not. If you really need a line break, use \n.

example: trad-example=firstline\nsecondline

Result:

firstline
secondline

How to choose reference for a translation

In order to have easy to maintain translation’s file, We’ll define reference following a defined pattern.

Each part of the pattern will be separated by "_"

  1. First part is an identifier for the UI which use the button.

  2. Second part is an element type identifier. Is it a simple label ? a title ? a button ?

  3. third part is a unique identifier

Theorical examples:

UI-1_label_uid1

UI-2_button_uid1

UI-2_button_uid2

UI-2_title_uid1

a. UI identifier

The different interface are listed below (inspired by the tab’s name in this document :

  • welcome
  • before
  • connect
  • devMode
  • ADBdebug
  • detect
  • download
  • install
  • eAccount
  • congrats
  • feedback

note: we don’t use UI with a number corresponding at the order of the interface in the whole process. Because if we want to change the process order, we’ll have to change all translation reference…

b. Element type

possible element’s type with corresponding code to use, are:

  • Main title : mTitle
  • title: title
  • subtitle : sbTitle
  • Label : lbl
  • Button : btn
  • instruction: instr

c. Unique identifier

use ‘uid’ with a simple incremental value.

The incremental value restart from 0 for each UI’s identifier and each element type.

or use a text identifier.

or no unique identifier if this is the only one element of this type

d. Real example

note: in the following example, the value describe the position or the content, but it can be anything else.

interface_mTitle_uid1=This is a main title
interface_sbTitle_uid1=this is the first subtitle
interface_sbTitle_uid2=this is the second subtitle
interface_sbTitle_uid3=this is the third subtitle
interface_lbl_version=this is the version Number
interface_lbl_uid1=this is the label below the first subtitle
interface_lbl_uid2=this is the label below the second subtitle
interface_lbl_uid3=this is the label below the third subtitle
interface_btn_uid1=this is the button to change interface