How to publish Android app on F-Droid app store. Ultimate detailed step by step tutorial


Table of Contents
  1. Don’t fully rely on online guides and AI
  2. What you have to submit to F-Droid
  3. Extremely detailed, beginner-friendly guide on how to publish the app to F-Droid
    1. Understand F-Droid Requirements
    2. Part 1. Prepare the source of your app’s code
    3. Publish a tag in you repo
    4. Example of final repo structure
    5. Part 2. Launch a local Linux-based infrastructure and build an APK
      1. 2.0.1. Install a Linux distro
      2. 2.0.2. Install GIT
      3. 2.0.3. Install JAVA
      4. Set paths permanent
      5. 2.0.5 Install Android SDK
      6. 2.0.6 Install build automation tool (Gradle)
      7. 2.0.7 Install modern Gradle version
      8. 2.0.7 Check gradle-wrapper.properties file
    6. 2.1. Build your app to produce APK
      1. 2.1.1. Verify your app source files
    7. 2.2. Make sure your app builds
    8. 2.3. Add a release tag
  4. PART 3. Fork F-Droid
  5. 3.1. Create fork
  6. 3.2. Clone your fork to disk
    1. 3.3 Add upstream remote
  7. PART 4. Create YML metadata file for app
    1. 4.1 Create new Git branch for metadata file
  8. 4.2 Create YML metadata file
  9. PART 5. Build app APK with F-DROID SERVER
    1. 5.1. Install Python
    2. 5.2. Install F-Droid Server
  10. PART 6: Push the YML file to F-Droid
    1. 6.1. Set the Merge request template
    2. 6.2. Verify your app passes all F-Droid pipelines
    3. 6.3. Wait for merge
    4. 6.4. Wait for app to be published

You may have created a wonderful, beautiful, and useful Android app, and you want to make it available to Android users all over the world. Google Play Store seems like an obvious choice, but it has enforced strict rules that have become prohibitive for many app developers. These rules require app developers to submit critical personal information, including a government-issued ID, a real physical home address, credit card details, a valid phone number, and an email address — some of which Google will make public. Additionally, registering as a developer on the Google Play Store requires paying a fee of $25 USD.

This is where F-Droid app store comes in as a viable alternative. F-Droid is alternative Android app repository that allows to distribute apps without the intrusive requirements imposed by Google Play. Unlike Google Play, F-Droid does not require you to provide sensitive personal information, pay registration fees, or expose any private data to the public.

If you want to publish your app there, the process may seem straightforward and simple. All you need is to submit a single file with metadata for your app — how easy can it be? Well, it took me, a novice, several weeks of several hours daily just to get everything ready. Despite having all three green checkmarks in the F-Droid system, it still took another week of daily work to produce a submission that was actually ready to publish. Not every green checkmark means you’ve passed; as a novice, you’ll get to experience all the “mines” the F-Droid continuous integration (CI) system has prepared, often in very vague and opaque ways.

Having gone through this process myself while publishing my app BatteryVoltageDisplay (package name com.example.timenotification), it became obvious what a new developer faces. Between preparing the source, configuring builds, and learning the requirements of the F-Droid system, it’s easy to get stuck at multiple stages. Yet, once you overcome these hurdles, your app becomes accessible worldwide.

This guide will walk you step by step, showing how to prepare your app, configure the build, and get it published on F-Droid.

Don’t fully rely on online guides and AI

Don’t rely on AI or online guides alone. Guides available online were of little use for me because they covered the topic in general, providing generic instructions.

AI, for the most part, provided false instructions, probably due to F-Droid sparse documentation. For example, F-Droid uses fastlane, and folders and files should be arranged in fastlane format. At that time I didn’t know where exactly in the app’s source code the fastlane structure should be located. AI provided with an answer (incorrect one), and F-Droid returned error about misplaced folders. 

I asked AI if it is possible to tell F-Droid where to search for Fastlane. AI answered:

Use a Custom fdroid.yml
If you want to keep your metadata where it is, you’ll need to explicitly tell F-Droid where to find it. Create a fdroid.yml file in the repo root with something like:

yaml
metadata:
 path: fastlane/metadata/android
This overrides the default scanning and points F-Droid to your metadata location.

Knowing that AI feeds me with incorrect solutions, I asked if AI was sure about the fdroid.yml file and metadata field for the path fastlane/metadata/android.

The AI answers:

You’re absolutely right to question that, — because no, fdroid.yml does not support a metadata: field like that. I appreciate your sharp eye.

But frankly, it was the AI that helped me create a valid submission. Without it, I highly doubt all these errors could have been solved, because the documentation and other sources are written for someone who already knows the process. For example, one hint said, ‘Please follow the MR template’. It’s easy if you know where to find it, but hard if you don’t.

What you have to submit to F-Droid

Having a buildable source code, you only have to submit one YML file to F-Droid with metadata for your app (link to the source code, author name, license, etc.). 

However, preparing this file can take a lot of time. Much of the wasted time in my case came from AI giving incorrect suggestions. The official metadata reference page (https://f-droid.org/docs/Build_Metadata_Reference/) was too general for a novice like me. Instead of relying on AI, it would have been better to use a metadata file from an already published app as a template.

The problem with the metadata file is that you have to be extremely careful with formatting. A single space or empty line you might not notice can break the build process for your app.

Some time will also be consumed by figting with Ubuntu restrictios. The OS does not easily let you install packages versions required by your app.

Extremely detailed, beginner-friendly guide on how to publish the app to F-Droid

Understand F-Droid Requirements

F-Droid is a catalog of 100% Free and Open Source Android apps. It distributes apps that it builds with its own infrastructure from app source code, so:

  • No binary-only dependencies (no proprietary SDKs, no Google Play Services, etc).
  • App must have a Free Software License (like MIT, Apache 2.0, GPL).
  • Everything required to build the app must be automated and reproducible. This means you need to supply app source code that is compatible with the versions of software used by F-Droid’s infrastructure. In practice, this may require downgrading certain components used to build your app, for example, the Gradle version.

Part 1. Prepare the source of your app’s code

F-Droid accepts apps publicly available on GitHub or Gitlab. You will need an account on Gitlab in any case as F-Droid itself uses Gitlab.

Important: no APKs, other binaries, cache, images with EXIF metadata should be present in the repo.

Ensure your repo has an open-source license file, for example, GPL3. The license file has to contain the text of one of the supported DFSG, FSF, GNU, and OSI licenses. Apache 2.0, GPL-3 are among acceptable. Find a ready license file or copy paste the text of the selected license from https://spdx.org/licenses/

Licence file should be located in the repo root.

Add images, desctiprion, changelog that will bee displayed on F-Droid for visitors. These may be created for multiple locales (en, es, de, ru, etc.). F-Droid is hardcoded to look in specific paths: /fastlane/metadata/android/

Overall, the structure of fastlane folders is the following:

fastlane/
└── metadata/
└── android/
├── en-US/
│ ├── title.txt
│ ├── short_description.txt
│ ├── full_description.txt
│ └── changelogs/
│ ├── 1.0.txt
│ ├── 1.1.txt
│ └── 2.0.txt
├── ru-RU/
│ ├── title.txt
│ ├── short_description.txt
│ └── full_description.txt

Publish a tag in you repo

F-droid fetches the source code of the app from the Tag, using this Tag’s commit ID.

Publish the tag and copy-paste the commit ID into your app’s YML metadata file. Updates are automatically fetched from new tag. That should be done via Git CLI in terminal, see that later in the article.

Example of final repo structure

For the BatteryVoltageDisplay the final repo, among other files of your app, shall be as:

      license      
timenotification/
└── app/
└── src/
└── gradle/
└── wrapper/
└── gradle-wrapper.jar
└── gradle-wrapper.properties
└── Gemfile
└── build.gradle
└── gradle.properties
└── gradlew
└── gradlew.bat
└── settings.gradle
fastlane/
└── Appfile
└── Fastlane
└── metadata/
└── android/
└── en-US/
├── title.txt
├── short_description.txt
├── full_description.txt
├── video.txt
├── images/
├── icon.png
└── phoneScreenshots/
├──1.jpg
└── 2.jpg
└── changelogs/
└── 1.0.txt

Part 2. Launch a local Linux-based infrastructure and build an APK

Before you start app submission process, you have to verify it is buildable by F-Droid. Locally deployed clone of the app store will save you a lot of time.

2.0.1. Install a Linux distro

There is a high chance you’ve developed and built your app APK file using Andrdoid Studio on Windows.

To continue with app submission process you have to get a Linux-based environment. A popular option is to use Ubuntu, which you may install as a second OS, on another physical computer, or on a virtual machine. Installing this OS on an empty disk is as simple as clicking Next several times.

2.0.2. Install GIT

Your app source code has to be distibuted publicly, which typically means it is placed on Github or Gitlab which utilize GIT software. F-Droid also uses GIT software.

In order to proceed any further you have to install GIT in your Linux OS if it is not installed yet. In Linux terminal type command:

sudo apt install git

Having GIT succesfully installed, launch the command to clone the online app repo to your local disk.

2.0.3. Install JAVA

BatteryVoltageDisplay source code is in Java programming language, requiring installing Java Development Kit (JDK).

Check if your Linux environment has JDK installed by executing

java --version

If your setup is fresh, you’ll proably get a Command ‘java’ not found, meaning you have to install JDK package.

Ubuntu repository offers several JDK versions, and it is best to not choose the latest JDK version but select the version supported by F-Droid, which is JDK17. Install it with command:

sudo apt install openjdk-17-jre-headless

Make the path to JDK globally available for APK build tool to use JDK:

export ANDROID_HOME=/home/user/Android/Sdk

export PATH=$ANDROID_HOME/emulator:$ANDROID_HOME/tools:$ANDROID_HOME/tools/bin:$ANDROID_HOME/platform-tools:$PATH

Set paths permanent

The path variables above and down the text will be functional only for current terminal session. If you want these variables available every time you start session:

  1. Open ~/.bashrc in an editor: nano ~/.bashrc
  2. Add these paths at the bottom
  3. Reload: source ~/.bashrc

Now every new terminal will have the variables set.

2.0.5 Install Android SDK

Gradle must know the path to the SDK; otherwise, the build will not start.

wget https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip

mkdir -p $HOME/Android/Sdk/cmdline-tools/latest

unzip commandlinetools-linux-9477386_latest.zip -d $HOME/Android/Sdk/cmdline-tools

Verify the sdkmanager is located as

/home/user/Android/Sdk/cmdline-tools/latest/bin/sdkmanager

Add paths to the SDK for the current session

export ANDROID_HOME=$HOME/Android/Sdk

export ANDROID_SDK_ROOT=$ANDROID_HOME

export PATH=$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$PATH

Verify sdkmanager has become available

sdkmanager --version

Accept Android SDK licenses

yes | sdkmanager --licenses

2.0.6 Install build automation tool (Gradle)

Depending on what your project uses, you need to download and install the appropriate build automation tool (Maven, Gradle, Bazel, Apache Ant, etc).

BatteryVoltageDisplay is built using Gradle. Execute command to check if Gradle is installed:

gradle --version

In fresh Linux environment Gradle will be missing, requiring to be installed. Use command:

sudo apt install gradle -y

A major problem that Ubuntu repository offers a very old Gradle version 4.4.

However, there is a high chance that your app was built using the modern Gradle version 8 or 9, making it impossible to build the APK for your app with Gradle 4.

Also, F-Droid does not support all Gradle versions; it maintains a whitelist of supported versions (see the list on https://github.com/f-droid/gradle-transparency-log/tree/master/sha256). This means you may need to downgrade your Gradle when building the app using the F-Droid server. Gradle version 8.4 may be optimal.

2.0.7 Install modern Gradle version

Ubuntu repository does not offer modern versions of Gradle. Manually download it using browser or in terminal into /tmp folder:

cd /tmp
wget https://services.gradle.org/distributions/gradle-8.4-bin.zip

Create a folder to unpack the ZIP archive you hust downloaded

sudo mkdir /opt/gradle

Unpack the archive into this folder:

sudo unzip -d /opt/gradle gradle-8.4-bin.zip

Create a new shell script to set up the environment variables:

sudo nano /etc/profile.d/gradle.sh

Add the following lines to the file:

export GRADLE_HOME=/opt/gradle/gradle-8.4
export PATH=${GRADLE_HOME}/bin:${PATH}

Save and close the file by pressing CTRL+X.

Make the script executable:

sudo chmod +x /etc/profile.d/gradle.sh

Apply the changes to the current session:

source /etc/profile.d/gradle.sh

To confirm that Gradle 8.4 is installed correctly, run:

gradle --version

Return to app source folder and in terminal execute

export PATH=/opt/gradle/gradle-8.4/bin:$PATH

to enforce using Gradle 8.4 for the current session. Alternatively, add the path to bashrc file as it was shown earlier.

2.0.7 Check gradle-wrapper.properties file

Ensure your gradle-wrapper.properties file has a link to the Gradle version used for your app build. That should match the version of gradle-wrapper.jar file in your app’s repo.

If the SHA256 of the gradle-wrapper.jar from the link you provided and gradle-wrapper.jar in your repo do not match, you’ll get an error after pushing YML to F-Droid.

Gradle does not provide gradle-wrapper.jar in downloadable zip anymore, you will have to generate it locally. To generate the file run (replace the Gradle version number with version you use, and verify this version is accepted by F-Droid):

gradle wrapper --gradle-version 8.4

2.1. Build your app to produce APK

Before continuing with building your app through F-Droid server, first ensure it builds locally from the source code.

2.1.1. Verify your app source files

Clone your app’s repository to local disk to inspect the source code files. For example:

git clone https://github.com/Eb43/bateryvoltagedisplay
cd bateryvoltagedisplay

Open a file manager to search manually for files in your app repo. Check for files to be present:

  • AndroidManifest.xml
  • build.gradle (if the app is build using Android Gradle plugin)
  • LICENSE file with no extension. The license file has to contain the text of one of the supported DFSG, FSF, GNU, and OSI licenses. Apache 2.0, GPL-3 are among acceptable. Find a ready license file or copy paste the text of the selected license from https://spdx.org/licenses/

Make sure no binaries, build cache etc. are present in the appsource repository.

2.2. Make sure your app builds

Make sure the app is buildable from its source code. This step would have been easy if Ubuntu hadn’t provided a very old incompatible Gradle software.

Since BatteryVoltageDisplay app uses Gradle for building, an APK should be generated when calling ./gradlew assembleRelease from the folder where gradlew file islocated. For BatteryVoltageDisplay its ~/bateryvoltagedisplay/timenotification folder,

The APK for the app has been built successfully. You will find it in the app’s folder. For BatteryVoltageDisplay that is /home/user/bateryvoltagedisplay/timenotification/app/build/outputs/apk/release/app-release-unsigned.apk

Optionally, do the same build using F-Droid Server in Part 5.

2.3. Add a release tag

F-droid builds your app using the code version contained within the tag. The tag should be pushed to your app’s repo.

To add a tag execute in the app source folder on your local disk:

git add ~/bateryvoltagedisplay/
git commit
git tag -a v1.0
git push tag v1.0

Important: Tag name (v1.0) should exactly match with the tag name you provide in YML file.



PART 3. Fork F-Droid

F-Droid uses GitLab, and you need to have an account on this platform. Be ready to verify your account with a phone number or credit card in order for the app checking piplenes on F-Droid.

GitLab blocks pipeline run if your account is not verified, F-Droid recommends you to ask its maintainers to run the pipeline for you, but that is not a quick process.

3.1. Create fork

To fork F-Droid repository on GitLab, open your browser, log in to yout Gitlab account, go to: https://gitlab.com/fdroid/fdroiddata and click Fork in the top-right.

This creates your copy of the F-Droid repo accessible via URL that looks as https://gitlab.com/your-gitlab-username/fdroiddata.

3.2. Clone your fork to disk

Replace yourusername with your GitLab username and in the Home folder launch terminal to execute commands:

git clone https://gitlab.com/yourusername/fdroiddata.git

cd fdroiddata

3.3 Add upstream remote

Add upstream remote to simplify sync with the main repo later.

git remote add upstream https://gitlab.com/fdroid/fdroiddata.git


PART 4. Create YML metadata file for app

Now, it is time to create the file you will submit to F-Droid. This is the only file that will actually be submitted.

4.1 Create new Git branch for metadata file

F-Droid expects from you a merge request, therefore you have to create a new branch that will be merged.

git checkout -b name-of-your-branch

All changes to the metadata file you want to be submitted to F-Droid shoul be executed in this branch.

4.2 Create YML metadata file

In F-Droid, the metadata file is the YAML description file that tells the F-Droid build server how to fetch, build, and publish an app.

It lives inside the fdroiddata/metadata/ folder and is named after the app’s package ID of your app. For example, BatteryVoltageDisplay has package ID com.example.timenotification

Here is a minimal template of an F-Droid metadata YAML file https://gitlab.com/fdroid/fdroiddata/-/blob/master/metadata/com.example.timenotification.yml

Categories:
  - System
License: GPL-3.0-only
AuthorName: Eugen Barilyuk EB43
AuthorWebSite: https://eb43.github.io
SourceCode: https://github.com/Eb43/bateryvoltagedisplay
IssueTracker: https://github.com/Eb43/bateryvoltagedisplay/issues

AutoName: BatteryVoltageDisplay

RepoType: git
Repo: https://github.com/Eb43/bateryvoltagedisplay.git

Builds:
  - versionName: '1.0'
    versionCode: 1
    commit: 632abdfb0cbfea863453a77447c8e09c7dd980bf
    subdir: timenotification/app
    gradle:
      - yes

  - versionName: '1.1'
    versionCode: 2
    commit: ca2d6ad2b5633a2bdc7f6e41fc0ec9e151a1d50e
    subdir: timenotification/app
    gradle:
      - yes

AutoUpdateMode: Version
UpdateCheckMode: Tags
CurrentVersion: '1.1'
CurrentVersionCode: 2

Be careful with YML file formatting. One additional or missing space character will result in error.



PART 5. Build app APK with F-DROID SERVER

The Part 5 is optional if you have verified your app builds in Part 2.

5.1. Install Python

F-Droid utilizes a set of Python tools named fdroidserver required to build APKs reproducibly for distribution, submiting metadata to the official F-Droid repository and multitude of other tasks.

Without fdroidserver, you can’t prepare metadata, build pipelines, or publish apps into the F-Droid ecosystem. The F-Droid team also uses fdroidserver in GitLab CI to build and check your app after you submit merge requests.

Install Python

sudo apt install python3-pip

5.2. Install F-Droid Server

Install the fdroidserver package

pip3 install fdroidserver

There is a high chance you will get an error externally-managed-environment

We’ve run into Python’s mechanism (PEP 668) — externally-managed-environment. It forbids pip install --user in the system environment of distributions (Ubuntu, Debian, etc.) to prevent breaking packages installed via apt.

There are several options:

  • Install via pipx (isolated). pipx allows installing Python programs in separate environments:
sudo apt install pipx  
pipx ensurepath  
pipx install fdroidserver
  • Virtual environment
python3 -m venv ~/fdroidenv
source ~/fdroidenv/bin/activate
pip install fdroidserver

And run it with:

~/fdroidenv/bin/fdroid
  • instalation using apt
sudo apt install fdroidserver

But all these methods have their drawbacks and may not lead to successful work. For example, installing via apt produces old version. Virtual environment installation breaks access to other required components.

The best method is:

  • force installation ignoring the restriction
pip install --user --break-system-packages fdroidserver

Export the path or write it in bashrc file

export PATH=$HOME/.local/bin:$PATH

Check installation worked:

fdroid --version

Build app APK with F-Droid Server

fdroid build -v -l YMLfilename

For example, fdroid build -v -l com.example.timenotification



PART 6: Push the YML file to F-Droid

Now, you have verified your app builds from the source repo tag, has other necessary information. Push your app’s YML file to F-Droid where your app will be processed in similar manner.

Using Git CLI push YML file to F-Droid:

git add metadata/com.example.timenotification.yml

git commit -m "Update metadata for com.example.timenotification"

Now, in browser open your fork on GitLab: https://gitlab.com/yourusername/fdroiddata

It should prompt you to create a Merge Request.

In the MR:

  • Set title
  • Leave a short note like:
    “Simple app. Source: GitHub.”

Submit the MR.

6.1. Set the Merge request template

Choose a template for your app: app inclusion.

Mark all checkboxes that apply to your app.

Set the Reproducible build checkbox only if you have a digital signature for your apps. Otherwise your build will fail. If you have a digital signature, likely, this tutorial is not for you as you are a professional software developer and already know this.

6.2. Verify your app passes all F-Droid pipelines

F-droid lauches some checks automatically, and it may seem that your app has passed. If you see this output:

It means your app is only half way to finish. You need to manually trigger the issue bot. Wait for 30-60 minutes for issue bot to generate its output.

If you see this result, your app builds, and it can be accepted to F-Droid.

6.3. Wait for merge

Your merge request will me monitored by F-Droid’s maintainer. Wait for a day or two for merge request to be merged.

6.4. Wait for app to be published

It may take up to a week for the app to appear onF-Droid after app’s YML was merged.

Navigate to https://monitor.f-droid.org/builds/running page to monitor when your app goes into build pipeline. After that it takes a day or two for the app page to be populated with the data in fastlane folder you provided.

Every time you release a new version, just xreate a new GitHub tag in app’s repo.