This app is developed in Kotlin with Android Studio using
If you want to compile Gaai you must install Git and Android Studio. Follow these steps:
button at the top of this page.
You might need a GitHub login to be able to clone a repo.
If you plan on contributing to Gaai, you better first fork the repo in GitHub and use the URL of your fork in
Android Studio.
Under Directory choose a directory where you want the project to be stored.
Press the Clone button.The Gaai project uses Semantic Versioning. A version number has the format x.y.z, possibly with some extensions. x, y and z are incremented as follows:
Not every commit is given its own version number. Only commits that correspond with released versions are given their own version number. All other commits are candidates for the next release. As soon as a commit is officially released for the x.y.z release, the following steps are taken:
-experimental, -alpha, -beta, etc…
See Software release life cycle.
Gaai will use -beta until the achieved testing level warrants an `stable state.<x.y.z>-<c>-g<1234567>[-<branch name>][-dirty]
with
<x.y.z>: The most recent tag of the form x.y.z.<c>: the number of commits after the tag. Absent if 0.<1234567>: the first 7 digits of the git commit hash.<branch name>: name of the branch if different from master.-dirty: is added if the workspace still contains local modifications (i.e. uncommitted files).Android not only requires a versionName, but also a versionCode. The versionCode is not meant to be shown to the user. It is an internal number that Android uses to protect against downgrading. Android does not allow to install an APK with a lower versionCode than the one already installed. Using the gradle-android-git-version plugin, Gradle generates a versionCode equal to 100.000 * x + 1.000 * y + z.
The Gaai project uses the Conventional Commits specifications for writing commit messages.
Local (JUnit) tests run directly on your development PC. No emulator or mobile phone running Android is required.
Run the local tests in Android Studio as follows:
Local tests can also be run using Gradle in a shell (e.g. PowerShell in Android Studio terminal, or git bash),
see Test from the command line:
./gradlew testReleaseUnitTest or ./gradlew testDebugUnitTest
Note that there are no instrumented tests yet.
Instrumented (JUnit) tests run on an Android emulator or mobile phone.
Run the Instrumented tests in Android Studio as follows:
Instrumented tests can also be run using Gradle in a shell (e.g. PowerShell in Android Studio terminal, or git bash),
see Test from the command line:
./gradlew connectedAndroidTest
Android Studio allows to run/debug an app on a built-in emulator. For Gaai, this option is very limited because the emulator does not support BLE.
Android Studio allows to run/debug an app on a hardware device. See Run apps on a hardware device on how to do that. Using WiFi worked very fine on a Google Pixel 6 Pro. Basically you will need to enable Developer options and Wireless debugging on your phone and pair it with Android Studio.
Not all functionality is covered by local and instrumented tests (yet). Some manual testing is required. Install the app either using Android Studio or by manually installing the APK to test.
Now manually test all functionality that is described in the README.
The Local (JUnit) tests can also produce code coverage results. Run the local tests in Android Studio as follows:
Code coverage of local tests can also be generated using Gradle in a shell
(e.g. PowerShell in Android Studio terminal, or git bash),
see Test from the command line:
./gradlew testDebugUnitTest followed by ./gradlew createDebugCoverageReport.
Note that ./gradlew testReleaseUnitTest does not create Code coverage information.
Gaai uses android.util.Log for logging. The logging results are available in real time in Logcat. The use of the logging levels is loosely based on When to use the different log levels
None if the code in the be.cuypers_ghys.gaai.util package has logging statements. This code is fairly small and simple and fully tested with JUnit. Adding logging statements seems overkill.
The kotlin code is documented with KDoc.
Dokka can generate HTML documentation from it.
In order to do that, run the following command in a shell (e.g. PowerShell in Android Studio terminal, or git bash):
./gradlew dokkaGenerate. The resulting html files are generated in the app\build\documentation\html subdirectory.
Open the index.html file to start reading the documentation.
Note that this documentation targets developers, not the users of Gaai.
Once a commit on the master branch is selected to make a new release in GutHub, proceed as follows:
@Suppress but that does not always work../gradlew build in a shell (e.g. PowerShell in Android Studio terminal, or git bash).
This will also run the tests from point 1 above.
The resulting APK files are generated in the app\build\outputs\apk subdirectory.
For the GitHub release, use the one in the app\build\outputs\apk\release subdirectory.
Alternatively use the one from the latest build artifact generated by the Android CI action.-alpha if needed.app\build\outputs\apk\release subdirectory to the new release.Release APK’s must be signed. See Sign your app. Android refuses to install unsigned release APK’s. New versions of an already installed app must also be signed with the same key, otherwise the new version is refused by Android.
Gradle automatically signs release builds when ./gradlew build is ran.
That behavior is defined in the buildTypes block of the app module’s build.gradle.kts file.
The release block uses a signingConfig with the name “release”,
which is itself defined in the signingConfigs of the app module’s build.gradle.kts file.
The values storeFile, storePassword, keyAlias and keyPassword are not defined in the build.gradle.kts file.
build.gradle.kts must be pushed to the public git repo which would make the keys and passwords public.
The gaai-release.keystore file which contains the keys is for the same reason not included in Git.
Depending on the build being a local gradle build or a Github Action build, the key handling is different.
For a local build, the 4 values must be defined in a gaai-release-keystore.properties file,
located in the ANDROID_USER_HOME directory (C:\Users\<user>>\.android on Windows).
storeFile defines the location of the
keystore file.
The keystore file is of type “JKS”.
It contains a 256 bits Elliptic Curve key on the NIST P-256 elliptic curve.
This key is used with the SHA-256 with ECDSA signature algorithm to sign the APK.
All of that is done automatically by gradle.
For a Github Action build, the 4 values are stored in Github’s repository secrets. The following 4 secrets are used:
storeFile (gaai-release.keystore)storePasswordkeyAliaskeyPasswordThe keystore file can be manipulated using the command line tool keytool or with the KeyStore Explorer. The latter has a GUI.
In order to get the Base64 encoded contents of gaai-release.keystore, execute the following in Git bash:
base64 gaai-release.keystore | tr -d '\n' > gaai-release-keystore.txt
The contents of gaai-release-keystore.txt is to be put in the SIGNING_STORE_FILE Github secret.
The Keystore, signing key and passwords are not public. They are currently managed by the project maintainer, who is also responsible for backups.
./gradlew dokkaGenerate creates Html based documentation from the Kdoc documentation used for documenting the source
code.
The documentation is generated in the app\build\documentation\html directory./gradlew testReleaseUnitTest runs the local (JUnit) tests for the release build.
The Junit xml files are generated in the app\build\test-results\testReleaseUnitTest directory.
Html test result files are generated in the app\build\reports\tests\testReleaseUnitTest directory../gradlew testDebugUnitTest runs the local (JUnit) tests for the debug build.
The Junit xml files are generated in the app\build\test-results\testDebugUnitTest directory.
Html test result files are generated in the app\build\reports\tests\testDebugUnitTest directory.
In addition it performs code coverage analysis using jacoco.
The jacoco result file is written to app\build\outputs\unit_test_code_coverage\debugUnitTest\testDebugUnitTest.exec../gradlew test runs both the above../gradlew build assembles and tests the project.
The release apk files are generated in the app\build\outputs\apk\release directory../gradlew createDebugCoverageReport creates an html coverage report in app\build\reports\coverage\test\debug
based on the jacoco results in app\build\outputs\unit_test_code_coverage\debugUnitTest\testDebugUnitTest.exec.
This task is not included in ./gradlew build.The following GitHub actions are defined:
On every push to the GitHub repository, this action execute’s ./gradlew build and uploads the generated
signed APK to the build artifacts.
It also publishes the code coverage on Codecov.
Action generated by GitHub to build the project’s documentation and deploy it to GitHub-pages. It was setup as follows: