Session uses standard Gradle/Android project structure.
Ensure the following are set up on your machine:
- Android Studio (recommended) or the Android SDK command-line tools
- JDK 17 or later
- The following packages installed via the Android SDK Manager:
- Android SDK Build Tools (see
buildToolsVersioninbuild.gradle) - SDK Platform matching the
compileSdkVersioninbuild.gradle - Android Support Repository
- Android SDK Build Tools (see
Android Studio is the recommended development environment.
- Open Android Studio. On a new installation the Quickstart panel will appear. If you have open projects, close them via File > Close Project to return to the Quickstart panel.
- Choose Get from Version Control and paste the repository URL:
https://github.com/session-foundation/session-android.git - The default Gradle sync and build configuration should work out of the box.
The project has three product flavors:
| Flavor | Description |
|---|---|
play |
Google Play Store build |
fdroid |
F-Droid build (no proprietary dependencies) |
huawei |
Huawei AppGallery build (HMS push) |
To build a specific flavor manually, run the corresponding Gradle task, for example:
./gradlew assemblePlayDebug
./gradlew assembleFdroidDebug
./gradlew assembleHuaweiDebug -PhuaweiThe -Phuawei flag is required for Huawei builds to include the HMS dependencies. If building
in Android Studio, add -Phuawei under
Preferences > Build, Execution, Deployment > Gradle-Android Compiler > Command-line Options.
The build is standard Gradle — build-and-release.py is a convenience wrapper and is not
required if you only need to produce a signed APK. Pass the signing credentials directly as
Gradle properties:
./gradlew \
-PSESSION_STORE_FILE='/path/to/keystore.jks' \
-PSESSION_STORE_PASSWORD='<keystore-password>' \
-PSESSION_KEY_ALIAS='<key-alias>' \
-PSESSION_KEY_PASSWORD='<key-password>' \
assembleFdroidReleaseThe keystore file can be recreated from release-creds.toml — the keystore field in each
section is the JKS file base64-encoded, so it can be decoded back to a .jks file using any
standard base64 tool.
Quick checklist
- Create a
release/MAJOR.MINOR.PATCHbranch frommaster- Merge
devinto the release branch (full release), or cherry-pick the relevant patch commits- Bump the version code
- Create a GitHub release draft for the version (e.g.
1.23.4) in this repository- Obtain
release-creds.tomlfrom a project maintainer and place it in the project root- Run
./scripts/build-and-release.pyfrom the release branch- Upload the AAB bundle to the Play Store
- Review and merge the automated F-Droid PR in
session-foundation/session-fdroid- Review and publish the GitHub release draft
Steps 6–9 are explained in detail below. Steps 4 and 5 must be completed before running the script — if no release draft exists the artifact upload is silently skipped, and without the credentials file the script will exit immediately.
| Branch | Purpose |
|---|---|
master |
Represents production — always reflects what is live |
dev |
Integration branch for ongoing development |
release/MAJOR.MINOR.PATCH |
Short-lived branch used to prepare and build a release |
To start a release:
git checkout master
git checkout -b release/1.23.4For a full release, merge dev into the release branch:
git merge devFor a patch release, cherry-pick only the relevant commits:
git cherry-pick <commit>...Once the branch is ready, bump the version code in app/build.gradle (the versionCode and
versionName fields), commit the change, then proceed with the steps below.
- uv — the script uses
uv runto manage its Python dependencies (fdroidserver) automatically - gh — GitHub CLI, authenticated and with access to
session-foundation/session-androidandsession-foundation/session-fdroid - Android SDK — either
ANDROID_HOMEset in the environment, orsdk.dirdefined inlocal.properties. This would have been set up for you if you have opened the project in Android Studio.
The script requires a release-creds.toml file in the project root. This file is not
committed to the repository — ask a project maintainer for it. Its structure is:
[build.play]
keystore = "<base64-encoded JKS keystore>"
keystore_password = "<password>"
key_alias = "<alias>"
key_password = "<password>"
[build.huawei]
keystore = "<base64-encoded JKS keystore>"
keystore_password = "<password>"
key_alias = "<alias>"
key_password = "<password>"
[fdroid]
keystore = "<base64-encoded PKCS12 keystore>"
keystore_password = "<password>"
key_alias = "<alias>"
key_password = "<password>"From the project root, run:
./scripts/build-and-release.pyThis performs a full build and release. The built artifacts are placed under where they suppose to be according to standard Android project layout.
| Flag | Description |
|---|---|
--build-only |
Build all flavors but skip the F-Droid PR and GitHub release upload steps |
--build-type |
Gradle build type to use (default: release) |
For example, to perform builds without publishing anything:
./scripts/build-and-release.py --build-only- Play build — assembles split APKs and an AAB bundle for the
playflavor, signed with the Play keystore. - F-Droid build — assembles split APKs for the
fdroidflavor. - F-Droid repo update (skipped with
--build-only) — see FDROID_RELEASE.md for a full explanation of the architecture and manual steps:- Clones
session-foundation/session-fdroidintobuild/fdroidrepoif not already present. - Creates a
release/<version>branch. - Copies the new APKs into the repo, pruning old versions (keeps the latest four releases).
- Regenerates repository metadata using
fdroid update. - Commits and opens a pull request against
masterfor human review and merge.
- Clones
- Huawei build — assembles a universal APK for the
huaweiflavor. - GitHub release upload (skipped with
--build-only):- Looks for a release draft in this repository matching the version name.
- If found, uploads the Play split APKs, the AAB bundle, and the Huawei APKs to it.
- If no draft exists, this step is skipped (no error).
Code contributions should be submitted via GitHub as pull requests from feature branches, as explained here.