This guide will help you set up your development environment and get started with contributing to the Thunderbird for Android project.
Before you begin, ensure you have the following installed:
- Java Development Kit (JDK) - Version 21 or higher (Temurin OpenJDK recommended)
- Android Studio - Latest stable version recommended
- Git - For version control
- Gradle - Use the Gradle wrapper included in this repo (
./gradlew); no separate install required - Android SDK & command-line tools – Installed and managed via Android Studio SDK Manager
All contributions happen through a personal fork of the repository.
- If you haven’t forked the project yet, see the Contribution Workflow for step-by-step instructions.
- Once you have a fork, clone it to your machine and open it in Android Studio.
- Go to the Thunderbird for Android repository
- Click the Fork button in the top-right corner
- Create a fork under your GitHub account
- Open Android Studio
- Select Open an Existing Project
- Navigate to the cloned repository and open it
- Wait for project sync and indexing
For the best development experience, we recommend the following settings:
- Recommended plugins:
- Kotlin Multiplatform (usually bundled; if not, install from the JetBrains Marketplace)
- Select the app module (e.g.,
app-thunderbirdorapp-k9mail) in the Run/Debug Configuration dropdown - Select build variant you want to work with (Debug/Release) from Build Variants window
- Click the Build button or press
Ctrl+F9(Windows/Linux) orCmd+F9(macOS)
A Gradle wrapper is included in the project, so you can build the project from the command line without installing
Gradle globally. Run the following commands from the root of the project, where ./gradlew is the Gradle wrapper script
and the command to build runs tests and other checks, while assemble only compiles the code and packages the APK.
# Build all variants
./gradlew assemble
./gradlew build
# Build debug or release variant
./gradlew assembleDebug
./gradlew assembleRelease
# Build a specific app module
./gradlew :app-thunderbird:assembleDebug
./gradlew :app-k9mail:assembleDebug
# Build a specific library/feature module
./gradlew :module-name:buildReplace module-name with the actual name of the module you want to build.
- Set up an Android Virtual Device (AVD) in Android Studio with a recent API level with Google APIs image.
- Select the AVD from the device dropdown.
- Click the Run button or press
Shift+F10(Windows/Linux) orCtrl+R(macOS)
- Enable Developer Options and USB Debugging on your device
- Connect your device to your computer via USB and confirm trust dialog if prompted
- Select your device from the device dropdown and click Run
# Run all tests across modules
./gradlew test
# Run unit tests for a specific module
./gradlew :module-name:test
# Run instrumented tests (device/emulator required)
./gradlew connectedAndroidTestSee the Testing Guide for details.
Maintaining high code quality is essential for the long-term sustainability of the Thunderbird for Android project. The project uses several tools and practices to ensure code quality:
- Static Analysis Tools: Android Lint, Detekt, and Spotless
- Code Style Guidelines: Kotlin style guide and project-specific conventions
- Testing: Unit tests, integration tests, and UI tests
- Code Reviews: Peer review process for all code changes
- Continuous Integration: Automated checks for build success, tests, and code quality
To run the basic code quality checks:
# Run lint checks
./gradlew lint
# Run detekt
./gradlew detekt
# Check code formatting
./gradlew spotlessCheck
# Apply code formatting fixes
./gradlew spotlessApplySee the Code Quality Guide for more details.
- Set breakpoints in your code by clicking in the gutter next to the line numbers
- Start debugging by clicking the Debug button or pressing
Shift+F9(Windows/Linux) orCtrl+D(macOS) - Use the debugger controls to step through code, inspect variables, and evaluate expressions
See the Android Studio Debugger Guide for a detailed description.
Use the project's core logging API net.thunderbird.core.logging.Logger, which is provided via dependency injection
(Koin). Avoid logging personally identifiable information (PII).
Example with DI (Koin):
private const val TAG = "ExampleActivity"
class ExampleActivity : ComponentActivity() {
private val logger: Logger by inject()
fun doSomething() {
logger.debug(tag = TAG) { "Debug message" }
try {
// Some code that might throw an exception
} catch (exception: Exception) {
logger.error(tag = TAG, throwable = exception) { "An error occurred" }
}
}
}Use Android Studio's built-in Android Profiler to monitor:
- CPU usage
- Memory allocation
- Network activity
For performance-sensitive code, also consider Baseline Profiles or Macrobenchmark tests.