diff --git a/docs/android.md b/docs/android.md
new file mode 100644
index 00000000..76a372f1
--- /dev/null
+++ b/docs/android.md
@@ -0,0 +1,40 @@
+---
+title: "Home Assistant Android"
+sidebar_label: "Introduction"
+---
+
+## Welcome to the Home Assistant Android project
+
+Are you ready to make a difference in the world of smart home technology? The **Home Assistant Android app** is an open-source project that empowers users to control their smart homes seamlessly. Whether you're a developer, designer, or enthusiast, **your contributions matter**!
+
+**[Explore the GitHub repository](https://ossinsight.io/analyze/home-assistant/android#overview)** to see how far we've come and where you can help!
+
+---
+
+## Why contribute?
+
+- **Make an impact**: Improve the lives of thousands of users worldwide.
+- **Showcase your skills**: Build your portfolio by contributing to a widely recognized open-source project.
+- **Learn and grow**: Collaborate with a passionate community and enhance your technical expertise.
+- **Be part of a community**: Join a global network of developers and smart home enthusiasts.
+
+---
+
+## How you can help
+
+We welcome contributions of all kinds! Here are some ways you can get involved:
+
+- **Code contributions**: Fix bugs, add features, or improve performance.
+- **Code reviews**: Help others by reviewing their work and providing constructive feedback.
+- **Documentation**: Keep our guides clear, concise, and up-to-date.
+- **Testing**: Ensure the app works flawlessly across devices.
+- **Feedback**: Share your ideas and suggestions to make the app even better.
+
+---
+
+## Ready to get started?
+
+1. **[Check out our get started guide](android/get_started)** for step-by-step instructions.
+2. **[Join our Discord community](https://discord.gg/c5DvZ4e)**, make sure you select the developer role and head to the **[Android](https://discord.com/channels/330944238910963714/1346948551892009101)** project thread to connect with other contributors.
+
+Together, we can create something extraordinary. Let's build the future of smart homes, one contribution at a time!
diff --git a/docs/android/app_flavors.md b/docs/android/app_flavors.md
new file mode 100644
index 00000000..d46c8916
--- /dev/null
+++ b/docs/android/app_flavors.md
@@ -0,0 +1,45 @@
+---
+title: "Android flavors"
+sidebar_label: "Flavors"
+---
+
+:::info
+Only the `:app` and `:automotive` modules are affected by these flavors.
+:::
+
+## Overview
+
+The Android app is built with two flavors: `full` and `minimal`. These flavors allow us to cater to different user preferences. This document explains the differences between the flavors, their features, and the rationale behind their implementation.
+
+## App flavors
+
+### Shared code
+
+We try, as much as possible, to keep everything in the source set agnostic `main` of the flavor so that everyone can benefit from new features. We will always favor open-source solutions if we can.
+
+### Full flavor
+
+The `full` flavor uses the **Google Play Services**, enabling features such as:
+
+- Location tracking
+- Push notifications
+- Communication with Wear OS devices
+
+This flavor is the one distributed via the Google Play Store.
+
+### Minimal flavor
+
+The `minimal` flavor is designed for users who prefer or require an app without **Google Play Services**. It has the following limitations:
+
+- ❌ No location tracking for [presence detection](https://www.home-assistant.io/getting-started/presence-detection/#adding-zone-presence-detection-with-a-mobile-phone)
+- ❌ No push notifications (except when using [local notification](https://companion.home-assistant.io/docs/notifications/notification-local#requirements) over the WebSocket)
+- ❌ No communication with Wear OS devices
+- ❌ No crash reporting
+
+Despite these limitations, the `minimal` flavor allows us to offer the app to a broader audience, including users of devices without Google Play Services. If viable open-source alternatives to Google Play Services features are found, they may be considered for inclusion in the `minimal` flavor to remove these limitations.
+
+This flavor is used, for instance:
+
+- For manual downloads of the APK or through F-Droid.
+- For Meta Quest devices.
+- For the Automotive build for OEM.
diff --git a/docs/android/architecture.md b/docs/android/architecture.md
new file mode 100644
index 00000000..96bede47
--- /dev/null
+++ b/docs/android/architecture.md
@@ -0,0 +1,88 @@
+---
+title: "Android architecture"
+sidebar_label: "Architecture"
+---
+
+## Introduction
+
+The Android project for Home Assistant started in 2019. Since then, the Android ecosystem has evolved significantly, and many contributors have shaped the project. As a result, you may encounter legacy code that does not adhere to current best practices. This documentation serves as the source of truth for the app's architecture and development practices.
+
+Home Assistant has been a frontrunner in [PWA](https://en.wikipedia.org/wiki/Progressive_web_app) development, and this philosophy is reflected in the native application. The app's centerpiece is a [WebView](https://developer.android.com/reference/android/webkit/WebView), which integrates with Home Assistant's frontend. Over time, native capabilities have been added, such as background sensor data collection.
+
+## Core principles
+
+### Kotlin first
+
+The entire codebase is written in [Kotlin](https://kotlinlang.org), ensuring modern, concise, and type-safe development.
+
+### Android version support
+
+- **Target SDK**: We aim to keep up with the latest Android SDK releases and test new versions as they are released.
+- **Min SDK**: To ensure broad compatibility, the app supports Android [Lollipop](https://en.wikipedia.org/wiki/Android_Lollipop) (API 21).
+
+## Application architecture
+
+We follow Google's recommended [Android architecture](https://developer.android.com/topic/architecture) and draw inspiration from the [NowInAndroid repository](https://github.com/android/nowinandroid).
+
+### Build logic
+
+The project uses multiple Gradle modules. Shared logic is centralized in a separate Gradle project named `build-logic`, included in the main project via `includeBuild`.
+
+### Common Gradle module
+
+To share code across different applications, we use a common Gradle module named `:common`.
+
+## UI development
+
+### Native UI
+
+All new UI components are built using [Jetpack Compose](https://developer.android.com/compose), ensuring a modern and declarative approach to UI development.
+
+### Legacy UI
+
+Some legacy XML layouts, `databinding`, and `viewbinding` still exist in the app. These should be replaced with Compose as part of ongoing modernization efforts.
+
+### Theming
+
+The app uses multiple themes to support both legacy XML and Compose-based UI. All new components should use `HomeAssistantAppTheme`, which is based on [Material Design](https://developer.android.com/develop/ui/compose/components).
+
+## Key features
+
+### Dependency injection (DI)
+
+We use [Hilt](https://developer.android.com/training/dependency-injection/hilt-android) extensively for dependency injection, ensuring modular and testable code.
+
+### Concurrency
+
+All concurrency is handled using [Kotlin Coroutines](https://kotlinlang.org/docs/coroutines-overview.html), providing a structured and efficient way to manage asynchronous tasks.
+
+### Services
+
+We use [Foreground Services](https://developer.android.com/develop/background-work/services/fgs) for retrieving sensor values and uploading them to Home Assistant Core asynchronously.
+
+### WebSocket
+
+The app maintains a direct connection to Home Assistant Core's WebSocket using [OkHttp](https://square.github.io/okhttp/). This is essential for features like Assist and real-time discussions.
+
+### REST API
+
+Communication with Home Assistant's REST API is handled using [Retrofit](https://square.github.io/retrofit/), enabling seamless interaction with the backend.
+
+### Local storage
+
+- **Room**: User data is stored locally using [Room](https://developer.android.com/training/data-storage/room), which provides a robust database solution.
+- **SharedPreferences**: For app-specific settings, we use [SharedPreferences](https://developer.android.com/reference/android/content/SharedPreferences) with an abstraction layer named `LocalStorage`.
+
+### Deep linking
+
+The app supports deep linking using `homeassistant://` URLs to navigate to specific parts of the app. For more details, refer to the [user documentation](https://companion.home-assistant.io/docs/integrations/url-handler/).
+
+## Platform-specific features
+
+### Automotive
+
+The automotive application reuses the sources of the `:app` module, simplifying development.
+
+### Wear OS
+
+The Wear OS app communicates with the mobile app to retrieve credentials for the Home Assistant server and other configurations using the [Messaging API](https://developer.android.com/training/wearables/data/messages). It only works with the `full` flavor, as it requires Google Play Services. Once the initial setup is complete, all further communication is handled directly with Home Assistant through the WebSocket and the [webhook](../api/native-app-integration/sending-data) that is created for the app.
diff --git a/docs/android/best_practices.md b/docs/android/best_practices.md
new file mode 100644
index 00000000..695eb60d
--- /dev/null
+++ b/docs/android/best_practices.md
@@ -0,0 +1,119 @@
+---
+title: "Android best practices"
+sidebar_label: "Best Practices"
+---
+
+## General principles
+
+In general, we should follow standard development principles such as:
+
+- **SOLID**: Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion. Learn more with [Kotlin SOLID Principles Examples](https://medium.com/huawei-developers/kotlin-solid-principles-tutorial-examples-192bf8c049dd)
+- **KISS**: Keep It Simple, Stupid.
+- **DRY**: Don't Repeat Yourself
+- **Community guidelines**: Follow the practices showcased in the [NowInAndroid](https://github.com/android/nowinandroid) repository.
+
+## Documentation
+
+Documentation in the code should bring value and evolve with the codebase. Keep the following in mind:
+
+- **Stay up-to-date**: Documentation must be updated as the code changes.
+- **Balance comments**: Avoid over-commenting, but don’t forget to comment where necessary.
+- **Future-proof**: Ask yourself, *"Will I understand what I did in 6 months?"*
+
+:::info
+Documentation should help, not hinder.
+:::
+
+## Logging
+
+Logging is essential but should be used judiciously. As Jake Wharton says in his [Timber](https://github.com/JakeWharton/timber) library:
+
+> Every time you log in production, a puppy dies.
+
+- Avoid excessive logging in production.
+- Use structured and meaningful log messages.
+- Leverage tools like Timber to manage logging effectively.
+
+## Time and duration
+
+When working with time, date, or duration, avoid using primitive types. Instead, use strong types to prevent unit mix-ups.
+
+### ❌ Don't do this
+
+```kotlin
+const val THRESHOLD = 600000
+
+fun main() {
+ val now = System.currentTimeMillis()
+
+ if (now > THRESHOLD) {
+ // Do something
+ }
+}
+```
+
+### ✅ Do this
+
+```kotlin
+val THRESHOLD = Instant.ofEpochSecond(60)
+
+fun main() {
+ val now = Instant.now()
+
+ if (now > THRESHOLD) {
+ // Do something
+ }
+}
+```
+
+:::warning
+If you must use primitive types, ensure the variable name includes the unit (e.g., `THRESHOLD_MS` instead of `THRESHOLD`) to reduce ambiguity.
+:::
+
+- Apply the same logic to dates, durations, and timestamps.
+- For APIs that use `long` for timestamps (e.g., milliseconds vs. seconds), convert the values to a strong type as soon as possible to minimize exposure to untyped units.
+
+## Concurrency
+
+Concurrency is powerful but requires careful handling to avoid issues like memory leaks and race conditions.
+
+### Coroutine scope
+
+Tie your coroutines to an Android lifecycle (e.g., `viewModelScope` or `lifecycleScope`) to prevent memory leaks.
+
+### Concurrent access
+
+- Ensure that any references accessed outside of a coroutine are thread-safe.
+- If a reference is not safe, either make it safe or don't use it.
+- Debugging concurrency issues (e.g., race conditions) can be extremely challenging, so design carefully.
+
+For more details on race conditions, see [Race Condition](https://en.wikipedia.org/wiki/Race_condition#In_software).
+
+## Code organization
+
+### Keep your classes small
+
+- Large classes often have too many responsibilities, making them harder to review, test, and maintain.
+- Aim for small classes with proper separation of concerns and abstraction.
+
+### Keep your functions small and meaningful
+
+- Functions should be small and focused on a single responsibility.
+- A function's name should clearly describe what it does. If it’s hard to name, the function likely does too much.
+- Well-named, small functions reduce the need for documentation and make the code self-explanatory.
+
+:::note
+Naming is hard, but smaller functions make it easier to choose meaningful names.
+:::
+
+## Keep your PRs small
+
+- **Why?** Smaller PRs are easier to review, reduce delays, and minimize frustration.
+- **How?** Break down large changes into smaller, logical chunks.
+
+For more details, see [submit](submit).
+
+## Additional notes
+
+- **Testing**: Write [unit tests](testing/unit_testing) for critical functionality to ensure reliability.
+- **Code reviews**: Always review code for adherence to these best practices.
diff --git a/docs/android/ci.md b/docs/android/ci.md
new file mode 100644
index 00000000..9b9662cc
--- /dev/null
+++ b/docs/android/ci.md
@@ -0,0 +1,111 @@
+---
+title: "Android continuous integration and delivery"
+sidebar_label: "Continuous integration and delivery"
+---
+
+## Android Continuous Integration and Delivery
+
+This document outlines the Continuous Integration (CI) and Continuous Delivery (CD) processes for the Android project. We use **GitHub Actions** as our CI/CD platform, with multiple workflows configured to ensure code quality, automate builds, and streamline deployments.
+
+## Overview
+
+The main goals of our CI/CD process are:
+
+- ✅ Validate that everything is working as expected.
+- 🚨 Notify relevant people if something breaks.
+- 🚀 Enable fully automated continuous delivery of applications.
+- 🔄 Avoid duplication by extracting common code into reusable local actions under `.github/actions`.
+
+## Versioning
+
+We follow the same versioning convention as the core project, using [CalVer] (Calendar Versioning). This ensures consistency across all releases.
+
+## Workflows
+
+### On pull request
+
+When a pull request (PR) is opened or updated, the `pr.yml` workflow is triggered. Its goals are:
+
+- 🧹 Validate code compliance with our [linters](linter).
+- 🔨 Ensure the code builds successfully.
+- ✅ Run all tests to verify correctness.
+- 📦 Persist generated APKs in the GitHub Actions tab for review.
+
+If any step fails:
+
+- The CI notifies the PR owner.
+- The PR is blocked from being merged until the issues are resolved.
+- Fixes must be committed, which automatically restarts the workflow.
+
+:::note
+Only one workflow runs at a time for a given PR. If multiple commits are pushed in quick succession, the CI cancels ongoing builds and processes only the latest commit.
+:::
+
+#### Debug builds
+
+To build the application in debug on CI, we use a mock Google services file located at `/.github/mock-google-services.json`.
+
+### On push to `main`
+
+When a commit is pushed to the `main` branch, the `onPush.yml` workflow is triggered. Its goals are:
+
+- 🌐 Download translations from [Lokalise](../translations).
+- 📝 Generate release notes.
+- 🔧 Build release variants of all applications.
+- 📤 Deploy applications to Firebase.
+- 🛒 Deploy to the internal track of the Play Store.
+- 📦 Persist generated APKs in the GitHub Actions tab.
+- 🔐 Inject secrets and files required for publishing.
+
+We use [Fastlane](https://fastlane.tools/) to simplify deployment to different stores. All Fastlane configurations can be found in the `fastlane` folder.
+
+:::note
+This workflow can also be manually triggered with the `beta` flag to promote a build to the beta track on the stores.
+:::
+
+### Weekly builds
+
+Every Sunday at 4:00 AM UTC, the `weekly.yml` workflow is triggered automatically. Its goals are:
+
+- 🛠 Create a weekly GitHub pre-release.
+- 🚀 Invoke the `onPush.yml` workflow with the `beta` flag set to `true`.
+
+This ensures that a new version of the applications is pushed to the beta track on the Play Store every week.
+
+### Monthly version tags
+
+On the first day of every month, the `monthly.yml` workflow runs to create an initial version tag in the format `YYYY.MM.0`. This aligns with our [CalVer] versioning strategy.
+
+### Releases
+
+The `release.yml` workflow is triggered manually to promote the latest beta build to production. This ensures that only stable and tested builds are released to end users.
+
+#### Release on F-Droid
+
+The [F-Droid](https://f-droid.org) store builds the applications themselves when we push a GitHub release. This process uses [metadata](https://gitlab.com/fdroid/fdroiddata/-/blob/master/metadata/io.homeassistant.companion.android.minimal.yml).
+
+They use the `version_code.txt` file, which is created on every release from the `main` branch, for the app's versioning.
+
+:::warning
+We do not guarantee when the applications will be available on F-Droid after a release. You can find the app [here](https://f-droid.org/packages/io.homeassistant.companion.android.minimal/).
+:::
+
+## Summary of workflows
+
+| Workflow | Trigger | Goals |
+|-------------------|-----------------------------|----------------------------------------------------------------------|
+| `pr.yml` | On PR open or update | Lint, build, test, and persist APKs. |
+| `onPush.yml` | On push to `main` | Build, deploy, and publish to Firebase and the Play Store. |
+| `weekly.yml` | Every Sunday at 4:00 AM | Create a pre-release and push the beta build to the Play Store. |
+| `monthly.yml` | First day of the month | Create an initial version tag (`YYYY.MM.0`). |
+| `release.yml` | Manual trigger | Promote the beta build to production. |
+
+---
+
+## Notes and best practices
+
+- 🛠 Extract common code into reusable actions under `.github/actions` to avoid duplication.
+- 🕒 Be mindful of workflow triggers to avoid unnecessary resource usage.
+- 🔒 Ensure secrets and sensitive files are properly managed and injected during workflows.
+
+[CalVer]: https://calver.org/
\ No newline at end of file
diff --git a/docs/android/codestyle.md b/docs/android/codestyle.md
new file mode 100644
index 00000000..d2f06167
--- /dev/null
+++ b/docs/android/codestyle.md
@@ -0,0 +1,76 @@
+---
+title: "Android code style"
+sidebar_label: "Code style"
+---
+
+## Why enforcing code style
+
+We aim to maintain a **consistent and standard codebase**. By enforcing code style:
+
+- We reduce unnecessary comments on PRs, allowing reviewers to focus on the logic rather than formatting.
+- We ensure the code is easier to read and maintain.
+
+## Language guidelines
+
+- All code must be written in **English**.
+- Avoid typos and grammatical mistakes. While mistakes are acceptable (as many contributors are non-native speakers), reviewers are encouraged to suggest corrections.
+- Use spell checkers to assist in correcting mistakes.
+
+## KTLint formatter
+
+We use [KTLint](https://pinterest.github.io/ktlint) to enforce Kotlin code style. It is integrated into our Gradle modules and configured via the `.editorconfig` file.
+
+### Custom rules
+
+We override some KTLint rules when necessary. To enable or disable a rule:
+
+ 1. Submit a **dedicated PR** with a proper explanation of the change.
+ 2. If the change affects the codebase, create **two commits**:
+ - One for updating the rule.
+ - Another for applying the changes.
+
+:::note
+Add a comment within the `.editorconfig` file above the overridden rule explaining why it was changed. If more explanation is needed, you can link to a GitHub issue.
+:::
+
+### Running KTLint
+
+You can use KTLint through Gradle to automatically reformat your code:
+
+```bash
+./gradlew :build-logic:convention:ktlintFormat ktlintFormat
+```
+
+### CI integration
+
+If a KTLint error is detected, the CI will fail, and GitHub will report it as a comment in the PR using the generated [SARIF](tips/sarif_reports.md) report.
+
+## Yamllint
+
+We use [Yamllint](https://github.com/adrienverge/yamllint) to enforce YAML formatting. The `github` format is followed for all YAML files in the repository.
+
+### Running Yamllint
+
+Run the following command at the root of the repository to check YAML formatting:
+
+```bash
+yamllint --strict --format github .
+```
+
+:::note
+Yamllint does not reformat your code; it only reports errors that need to be fixed. Use your IDE's code formatter or fix issues manually.
+:::
+
+### CI integration
+
+If the YAML format is invalid, the CI will block the PR.
+
+## Avoid using TODOs
+
+TODOs in code tend to be forgotten over time. When someone read them later, they are often outdated or irrelevant. We recommend avoiding TODOs in your code. However, if during a review you and the reviewer agree that something needs to be addressed later, you should create a `TODO`. To properly track TODOs, always associate them with a GitHub issue.
+
+### Example
+
+```bash
+// TODO Missing feature (linked issue #404)
+```
diff --git a/docs/android/get_started.md b/docs/android/get_started.md
new file mode 100644
index 00000000..3bc34d67
--- /dev/null
+++ b/docs/android/get_started.md
@@ -0,0 +1,106 @@
+---
+title: "Android get started"
+sidebar_label: "Get started"
+---
+
+## Getting started with Home Assistant Android development
+
+Welcome to the Home Assistant Android development guide! This document will help you set up your environment, fork the repository, and build your first app.
+
+## Setting up your development environment
+
+To get started, install the latest stable version of [Android Studio](https://developer.android.com/studio). This is the only tool you need to build the applications.
+
+## Fork, clone, and create a branch
+
+### Fork the repository
+
+1. Open the [Home Assistant Android repository](https://github.com/home-assistant/android).
+2. Click **Fork** to create your own copy of the repository.
+
+:::tip
+If you encounter any issues, refer to the [GitHub documentation on forking a repository](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo).
+:::
+
+### Clone your forked repository
+
+Once you've forked the repository, clone it to your local machine using the following command:
+
+```bash
+git clone https://github.com//android.git
+```
+
+Alternatively, you can use Android Studio:
+
+1. Go to `File -> New -> Project from Version Control...`.
+2. Enter your repository URL and clone it.
+
+### Create a branch
+
+Before making any changes, create a new branch with a meaningful name that reflects the work you are doing. For example:
+
+```bash
+git checkout -b feature/add-new-feature
+```
+
+:::tip
+If you're new to Git, check out the [Git Branching Guide](https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging). You can also create branches directly in Android Studio.
+:::
+
+## Build the Home Assistant applications
+
+Once you have the repository cloned locally, you can build the app using Android Studio or the terminal.
+
+### From Android Studio
+
+1. Open the project in Android Studio.
+2. Sync the Gradle files.
+3. Click the green **Play** button in the top bar. Android Studio will automatically create an emulator and run the app for you.
+
+### From the terminal
+
+:::info
+You will need the `JAVA_HOME` environment variable set to a JDK. We are currently using the JDK 21.
+:::
+
+#### On macOS/Linux
+
+```bash
+./gradlew assembleDebug
+```
+
+#### On Windows
+
+```powershell
+gradlew.bat assembleDebug
+```
+
+## Firebase setup
+
+Firebase is used for notifications. If you don't need these features, you should use a mocked Firebase configuration.
+
+:::info
+You can still send notifications through the WebSocket without using Firebase.
+:::
+
+### Setting up a mock Firebase project
+
+If you don't need real Firebase functionality, you can use the mock configuration:
+
+1. Copy the file located at `/.github/mock-google-services.json`.
+2. Place it in the following folders:
+ - `/app`
+ - `/automotive`
+ - `/wear`
+
+### Setting up a real Firebase project
+
+Follow our [Push notification guide](tips/fcm_push_notification) for additional setup instructions.
+
+## What's next?
+
+Now that you've built the app, explore the rest of the documentation to deepen your understanding of the project. A good starting point is the [Architecture guide](architecture), which explains the general structure of the codebase.
+
+## Need help?
+
+If you get stuck, don't hesitate to ask for help! **[Join our Discord community](https://discord.gg/c5DvZ4e)**, make sure you select the developer role and head to the **[Android](https://discord.com/channels/330944238910963714/1346948551892009101)** project thread to connect with other contributors for assistance.
diff --git a/docs/android/linter.md b/docs/android/linter.md
new file mode 100644
index 00000000..29a1fe94
--- /dev/null
+++ b/docs/android/linter.md
@@ -0,0 +1,150 @@
+---
+title: "Android linter"
+sidebar_label: "Linter"
+---
+
+## What is a linter?
+
+A linter is a static code analyzer that helps identify well-known issues and potential improvements in your code. It goes beyond what a compiler does by ensuring proper usage of the language and adherence to best practices. While a compiler validates code against a grammar, a linter focuses on code quality and architecture.
+
+:::note
+Having no complaints from a linter doesn't mean everything is perfect. A review from another developer is still necessary to double-check.
+:::
+
+## Why use a linter?
+
+Using a linter ensures:
+
+- **Consistency**: Enforces a standard code style, similar to our [codestyle](codestyle).
+- **Focus**: Allows reviewers to focus on logic rather than formatting or trivial issues.
+- **Prevention**: Helps avoid crashes and bugs by catching common mistakes, such as using APIs not supported by the target Android API level.
+
+For example, failing to check the Android API version before using an unsupported API can lead to crashes.
+
+## Linters used in the project
+
+### KTLint
+
+We use [KTLint](https://pinterest.github.io/ktlint) as our Kotlin linter, integrated via [Gradle plugin](https://github.com/JLLeitschuh/ktlint-gradle). The configuration is located in the main `build.gradle.kts` file. We mostly use the default configuration but enable [SARIF](tips/sarif_reports) reports for GitHub Actions to annotate issues in pull requests.
+
+#### Ignoring an issue
+
+Always try to fix issues rather than ignoring them. If ignoring is necessary, follow these steps:
+
+1. Use the `@Suppress` annotation for specific constructs:
+ ```kotlin
+ @Suppress("trailing-comma-on-call-site")
+ fun myCallSiteExample() {
+ myFunction(
+ "value1",
+ "value2", // This trailing comma would normally cause a warning
+ )
+ }
+ ```
+
+2. For project-wide suppression, update the `.editorconfig` file as per [this guide](https://pinterest.github.io/ktlint/0.49.1/faq/#how-do-i-globally-disable-a-rule-without-editorconfig). Open a dedicated PR with an explanation for disabling the rule:
+ ```editorconfig
+ ...
+ # Allow trailing commas but do not enfoce it to follow Kotlin convention
+ ktlint_standard_trailing-comma-on-call-site = disabled
+ ij_kotlin_allow_trailing_comma_on_call_site = true
+ ktlint_standard_trailing-comma-on-declaration-site = disabled
+ ij_kotlin_allow_trailing_comma = true
+ ```
+
+#### Running KTLint locally
+
+Run the following command to check all code in the repository:
+
+```bash
+./gradlew ktlintCheck :build-logic:convention:ktlintCheck --continue
+```
+
+:::note
+Use `--continue` to get all issues across Gradle modules instead of stopping at the first failure.
+:::
+
+You can add this check to be run automatically through a git [pre-commit hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) by running this command
+
+```bash
+./gradlew addKtlintCheckGitPreCommitHook
+```
+
+### Android Linter
+
+The Android linter is enabled for all variants to ensure comprehensive checks. Its configuration is located in `build-logic/convention/src/main/kotlin/AndroidCommonConventionPlugin.kt`. SARIF reports are generated for GitHub Actions to annotate issues in pull requests.
+
+#### Ignoring an issue
+
+Follow these steps to ignore an issue:
+
+1. Use the `@Suppress` annotation for specific constructs.
+2. Add the issue to the `lint-baseline.xml` file. (See [how to](#updating-the-baseline))
+3. Disable the issue in the lint settings directly.
+
+If you disable an issue, open a dedicated PR with an explanation.
+
+#### Running the Android linter locally
+
+Run the following command:
+
+```bash
+./gradlew lintDebug --continue
+```
+
+:::note
+Use `--continue` to get all issues across Gradle modules instead of stopping at the first failure.
+:::
+
+## Managing lint rules
+
+### Changing the lint level of an issue
+
+The Android linter comes with predefined rules bundled into the Android Gradle plugin. Some libraries, like [Timber](https://github.com/JakeWharton/timber), also provide custom lint rules.
+
+To change the severity of a rule, update the Gradle configuration in `build-logic/convention/src/main/kotlin/AndroidCommonConventionPlugin.kt`:
+
+```kotlin
+lint {
+ ...
+ disable += "MissingTranslation"
+ error += "LogNotTimber"
+}
+```
+
+- **`LogNotTimber`**: Promoted from a warning to an error to enforce the usage of Timber instead of the classic logger.
+- **`MissingTranslation`**: Disabled because translations are added only during CI release builds.
+
+Changes to lint levels should be made in a PR with a clear explanation.
+
+## Baseline management
+
+### What is a baseline?
+
+The baseline is an XML file (`lint-baseline.xml`) in each Gradle module that lists ignored errors. It was created when the linter was first enabled to avoid fixing hundreds of pre-existing issues.
+
+:::note
+A great first contribution is to remove issues from the baseline by fixing them.
+:::
+
+### Updating the baseline
+
+When updating the Android Gradle Plugin, new lint issues may arise, or existing ones may change. To regenerate the baseline:
+
+```bash
+./gradlew updateLintBaseline
+```
+
+After updating, review the ignored errors to determine if they should be addressed now or later. Open a GitHub PR or issue as needed.
+
+## Extending lint rules
+
+We encourage you to propose new linter rules specific to our project. These rules can help identify misuse of APIs or enforce design patterns.
+
+## Tips for contributors
+
+- Fix lint issues rather than ignoring them whenever possible.
+- Provide clear explanations in PRs for any changes to lint configurations or baselines.
+- Use the linter locally to catch issues early and save CI resources.
+
+Happy linting! 🚀
diff --git a/docs/android/release.md b/docs/android/release.md
new file mode 100644
index 00000000..56c68539
--- /dev/null
+++ b/docs/android/release.md
@@ -0,0 +1,46 @@
+---
+title: "Android release process"
+sidebar_label: "Release process"
+---
+
+## Android release process
+
+This document outlines the steps to take an Android application from development on your machine to production for end users. It also covers the roles of CI/CD pipelines, internal testing, beta testing, and Google Play Store validation.
+
+## Release workflow: from debug to production
+
+### Development and debug builds
+
+- During development, you typically build the **debug application** on your local machine.
+- Once your changes are ready, you push a **Pull Request (PR)** to the repository.
+
+### Continuous integration (CI)
+
+- The CI system automatically:
+ - Builds the application.
+ - Runs linters and tests to ensure code quality.
+- If the PR is approved and merged into the `main` branch:
+ - The CI builds the **release application**.
+ - The release build is pushed to the **internal tester group** on both the Google Play Store and Firebase.
+
+### Internal testing
+
+- Internal testers validate the release build to ensure functionality.
+- Due to the app's complexity, not all features can be tested exhaustively during this phase.
+
+### Weekly beta releases
+
+- Every week, the latest version of the `main` branch is pushed to the **open beta** channel.
+- Open beta users help test the application in real-world scenarios and report issues.
+
+### Production release
+
+- If the beta version is stable and approved by maintainers, it is promoted to **production**, making it available to all users.
+
+## Google Play Store validation
+
+- Google validates applications when they are pushed to the **open beta** phase.
+- Validation times can vary:
+ - It may take more than a week in some cases.
+ - Since releases are weekly, the previous beta release might still be under validation when a new beta is submitted. If this happens the previous beta is removed and not validated by Google.
+- This delay does not block the release process but requires careful planning to ensure timely updates.
diff --git a/docs/android/submit.md b/docs/android/submit.md
new file mode 100644
index 00000000..de6d0199
--- /dev/null
+++ b/docs/android/submit.md
@@ -0,0 +1,76 @@
+---
+title: "Android submit contribution"
+sidebar_label: "Submit contribution"
+---
+
+## Submit your first contribution
+
+First of all, thank you for your contribution! Now it's time to get feedback and prepare your work for real users. Follow the [GitHub Documentation](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork) to create a pull request (PR) from your fork.
+
+### Checklist for submitting a PR
+
+When creating a PR, GitHub pre-fills the description with a checklist. Ensure you follow all the steps. Here's an extended checklist to help you:
+
+- **PR description**: Provide a clear and complete description of your changes.
+- **Tests**: Add all necessary tests following our [testing guidelines](testing/introduction).
+- **Documentation**: Ensure your code is properly documented.
+- **UI changes**: Include screenshots if the UI is modified.
+- **User documentation**: If user documentation needs updates, open a PR on [GitHub](https://github.com/home-assistant/companion.home-assistant).
+- **Developer documentation**: If this documentation needs updates, open a PR on [GitHub](https://github.com/home-assistant/developers.home-assistant/).
+- **Builds**: Verify that everything builds properly (app, automotive, wear) locally.
+- **Best practices**: Follow the [best practices](best_practices).
+- **Code style**: Adhere to the [code style](codestyle).
+- **Linting**: Ensure no lint issues are introduced ([linter](linter)).
+
+### Opening a draft PR
+
+If your PR isn't ready for an official review, but you'd like feedback, you can open it in **draft mode**. This is especially useful when working on CI-related changes or incomplete features.
+
+#### CI trigger
+
+If you're a new contributor, each CI run must be approved by a maintainer.
+
+:::warning
+**Avoid unnecessary CI runs**
+Running CI workflows consumes significant resources. If your work is incomplete, postpone opening the PR (even in draft mode) unless necessary. Let's be mindful of resource usage and our planet. 🌍 But it doesn't prevent you from pushing regularly to avoid losing your work.
+:::
+
+### Review process
+
+#### Who can review?
+
+Everyone can comment on your PR since it's public. We encourage contributions through reviews. Reviewing can be quicker than coding, and even a 10-minute review can be valuable.
+
+If you're not confident in **reviewing**, you can still help by:
+
+- Testing the feature by installing the APK (available in the Checks tab of the PR; you must be logged in to your GitHub account to access it).
+- Providing feedback on UI/UX.
+- Reporting crashes or bugs.
+
+#### Getting approval from a maintainer
+
+Once your PR meets the checklist requirements, wait for a maintainer to review it. Remember, maintainers are volunteers contributing in their spare time. Be respectful, patient, and kind.
+
+Feedback from maintainers will come as:
+
+- **Comments**: Suggestions or required changes in the code.
+- **Questions**: Questions about how things are working.
+
+### After receiving feedback
+
+#### Re-ask for review
+
+If you've addressed feedback and pushed changes to your PR, you can request a re-review from maintainers. Ensure the CI is green before doing so.
+
+### Merging your PR
+
+- Keep your PR up to date with the `main` branch.
+- Once everything is green and approved by a maintainer, they will merge your PR. You don't need to take any further action.
+
+### Automatic issue and PR closure
+
+Our bot marks issues/PRs as stale after **90 days** of inactivity. If there's still no activity after **7 days**, the issue/PR will be automatically closed.
+
+---
+
+Thank you for contributing to Home Assistant! 🎉
diff --git a/docs/android/targets.md b/docs/android/targets.md
new file mode 100644
index 00000000..bd06f855
--- /dev/null
+++ b/docs/android/targets.md
@@ -0,0 +1,24 @@
+---
+title: "Android targets"
+sidebar_label: "Targets"
+---
+
+## Android targets
+
+This document outlines the various Android targets supported by the Home Assistant application. Each target has its own specific requirements and considerations.
+
+## 📱 Application (main target)
+
+The main target is based on the Gradle `:app` module. It supports a **minimum API level of 21**. This is the primary application used by most users.
+
+## 🚗 Automotive
+
+The Automotive target is also based on the `:app` module but includes specific manifest entries tailored for automotive use cases. It shares the same source code as the main application and supports a **minimum API level of 29**.
+
+## 📺 TV
+
+The application can be installed on Android TV, although the navigation experience is currently suboptimal. To provide a better experience, a dedicated Gradle module and improved navigation support are needed.
+
+## ⌚ Wear OS
+
+The Wear OS target brings Home Assistant functionality to wearable devices. It supports a **minimum API level of 26**. It is a **dedicated application** however it requires the mobile application for onboarding and connecting to a server.
diff --git a/docs/android/testing/integration_testing.md b/docs/android/testing/integration_testing.md
new file mode 100644
index 00000000..9c0978f7
--- /dev/null
+++ b/docs/android/testing/integration_testing.md
@@ -0,0 +1,45 @@
+---
+title: "Android integration testing"
+sidebar_label: "Integration testing"
+---
+
+## Why perform integration testing?
+
+[Unit tests](unit_testing) are great and should be your primary choice when writing tests. However, integration testing ensures that the behavior of the application in a real Android environment is validated. Integration tests run on a real Android OS through an emulator, using the same JVM that will be used by end users.
+
+### Testing on a real JVM
+
+During development, you might only test on the latest Android OS version or your locally installed JVM, most likely JDK 21. However, keep in mind the following:
+
+- Android API 21 only partially supports [Java 8 language features](https://developer.android.com/studio/write/java8-support).
+- Android uses a dedicated [runtime](https://source.android.com/docs/core/runtime) that is different from the one used in your development environment (which is typically used to execute unit tests).
+
+#### Concrete example
+
+Consider the [Jackson library](https://github.com/FasterXML/jackson). Starting from version 2.14, it requires a minimum Android version of 26. Unfortunately, this error only arises at runtime, meaning the only way to catch it is through instrumentation tests or a crash reported by a user. You can see a concrete example of this issue in this [PR](https://github.com/home-assistant/android/pull/5108).
+
+### UI or no UI?
+
+Integration tests do not always involve displaying a UI. They are also used to test [foreground services](https://developer.android.com/develop/background-work/services/fgs), where no UI is displayed. In these cases, we only verify the data and the interaction with the system.
+
+### Testing with the corresponding Home Assistant Core version
+
+:::note
+These tests are currently under development
+:::
+
+We aim to run integration tests against the latest version of Home Assistant Core. This ensures that the current code works seamlessly with the core version in a straightforward manner.
+
+### Testing without Home Assistant Core
+
+Most of our tests should not depend on Home Assistant Core to avoid introducing additional sources of error. These tests are designed to validate the behavior of the screen during user interactions. For this, we use the [Espresso](https://developer.android.com/training/testing/espresso) framework.
+
+In this scenario, interactions with the core can be replaced using mocks with [mockk](https://mockk.io/) or, even better, fake objects to control the behavior.
+
+## Flakiness in Android emulators
+
+Android emulators are notoriously unreliable. Occasionally, a platform may fail for unknown reasons. The only solution is to restart the job. Note that only maintainers can re-run a job.
+
+## Testing on Android 5 (API 21)
+
+If your tests require the WebView, you may need to follow these [tips for the Lollipop emulator](../tips/lollipop_emulator.md).
diff --git a/docs/android/testing/introduction.md b/docs/android/testing/introduction.md
new file mode 100644
index 00000000..474d65c1
--- /dev/null
+++ b/docs/android/testing/introduction.md
@@ -0,0 +1,58 @@
+---
+title: "Android testing"
+sidebar_label: "Introduction"
+---
+
+## Why do we write tests?
+
+Testing is an essential part of software development. While there are different kinds of tests, each serving a unique purpose, they all exist for the same fundamental reason: humans make mistakes. Tests are designed to catch these mistakes as early as possible in the development process.
+
+By identifying issues before they reach production, we save our users from frustration and ourselves from spending time debugging. Writing tests may feel like extra effort at first, but the value becomes clear when a test catches an issue before it impacts the end user.
+
+### Benefits of writing tests
+
+- **Early issue detection**: Catch bugs before they reach production.
+- **Improved code quality**: Tests encourage better design and maintainability.
+- **Time savings**: Debugging production issues is far more time-consuming than resolving issues during development.
+- **User satisfaction**: Fewer bugs in production lead to a better user experience.
+
+## How to write effective tests
+
+To ensure clarity and maintainability, test functions should always (when possible) be written as descriptive sentences. Ideally, they should follow the [GIVEN-WHEN-THEN](https://en.wikipedia.org/wiki/Given-When-Then) structure. This approach makes tests easier to understand at a glance, even for complex scenarios.
+
+Example of a well-named test:
+
+```kotlin
+@Test
+fun `Given a user with Home Assistant when they open the app then they see the default dashboard`() {
+ // Test implementation here
+}
+```
+
+### Why use GIVEN-WHEN-THEN?
+
+- **GIVEN**: Describes the initial context or setup.
+- **WHEN**: Specifies the action or event being tested.
+- **THEN**: Defines the expected outcome or result.
+
+This structure ensures that tests are both readable and self-explanatory, making it easier for developers to understand the purpose of the test without diving into the implementation.
+
+## Types of tests
+
+While this document focuses on Android testing, it’s important to understand the different types of tests and their purposes:
+
+1. **Unit tests**: Validate individual components or functions in isolation.
+2. **Integration tests**: Ensure that different parts of the application work together as expected.
+3. **UI tests**: Verify the user interface and user interactions.
+4. **End-to-End tests**: Test the entire application flow from start to finish.
+
+Each type of test has its place in the development process, and a well-tested application often includes a combination of all these types.
+
+## Best practices for writing tests
+
+- **Keep tests small and focused**: Each test should validate a single behavior or scenario.
+- **Use descriptive names**: Test names should clearly describe what is being tested and the expected outcome.
+- **Avoid dependencies**: Tests should be independent of each other to ensure reliability.
+- **Mock external dependencies**: Use mocks or fakes to isolate the code under test.
+
+By following these guidelines, you can write tests that are both effective and maintainable.
diff --git a/docs/android/testing/screenshot_testing.md b/docs/android/testing/screenshot_testing.md
new file mode 100644
index 00000000..9c5f540c
--- /dev/null
+++ b/docs/android/testing/screenshot_testing.md
@@ -0,0 +1,69 @@
+---
+title: "Android screenshot testing"
+sidebar_label: "Screenshot testing"
+---
+
+## Why do we perform screenshot testing?
+
+Screenshot testing is used to verify that the current UI matches the reference UI stored in the repository. By doing this, we can ensure that any changes impacting the UI are intentional and validated. The scope of these tests is limited to the UI.
+
+We should test on various device shapes and sizes, ranging from small screens (e.g., Wear OS devices) to large screens (e.g., 55" TVs).
+
+### Benefits of screenshot testing
+
+- **UI Consistency**: Ensures that the UI remains consistent across updates.
+- **Library Updates**: Validates that updates to UI libraries do not introduce unintended changes.
+- **Broad Device Coverage**: Tests across multiple screen sizes and shapes to ensure compatibility.
+
+### Real-world example
+
+Screenshot testing has proven useful when using beta versions of libraries, such as the Wear Compose library, where changes in the library could impact the UI.
+
+## Compose screenshot testing
+
+We use the [Compose Preview Screenshot Testing](https://developer.android.com/studio/preview/compose-screenshot-testing) framework to assert that the UI does not change unexpectedly.
+
+### Advantages of compose screenshot testing
+
+- **No emulator required**: These tests do not require an emulator, making them less resource-intensive and significantly faster than [integration tests](integration_testing).
+- **Fast feedback**: Developers can quickly verify UI changes without waiting for emulator boot times.
+
+### Reference screenshots
+
+The reference screenshots are stored under `src/debug/screenshotTest/reference` in each Gradle module. To update the reference screenshots, run the following command:
+
+```bash
+./gradlew updateDebugScreenshotTest
+```
+
+### CI integration
+
+Our [CI pipeline](../ci) verifies the test reports for any errors. If discrepancies are found, the CI blocks the pull request until the issues are resolved.
+
+## Avoiding duplication in Compose previews
+
+To avoid duplicating Compose previews in your tests, ensure that you reuse existing composables and preview annotations wherever possible. This reduces redundancy and ensures consistency between previews and tests.
+
+## Configuring annotations for tests
+
+When writing screenshot tests, use appropriate configuration annotations to define the device size, theme, and other parameters. This ensures that the tests accurately reflect the intended UI.
+
+## Handling threshold updates
+
+Screenshot tests can fail when run on different operating systems due to subtle differences in rendering, such as antialiasing. This issue is discussed in detail in this [Google issue tracker](https://issuetracker.google.com/issues/348590914).
+
+### Current approach
+
+- We aim to keep the threshold as low as possible to avoid masking real issues.
+- If your tests fail due to minor rendering differences, you may need to adjust the threshold.
+
+To adjust the threshold, update the configuration in your test file to allow for slight variations while still catching significant changes.
+
+## Best practices for screenshot testing
+
+- **Test across devices**: Ensure your tests cover a range of screen sizes and shapes.
+- **Keep reference screenshots updated**: Regularly update reference screenshots to reflect intentional UI changes, and explain the changes in your PR.
+- **Minimize thresholds**: Use the smallest possible threshold to avoid hiding real issues.
+- **Reuse previews**: Avoid duplicating Compose previews by reusing existing composables and annotations.
+
+By following these practices, you can ensure that your UI remains consistent and reliable across updates and device configurations.
diff --git a/docs/android/testing/unit_testing.md b/docs/android/testing/unit_testing.md
new file mode 100644
index 00000000..1e8d183b
--- /dev/null
+++ b/docs/android/testing/unit_testing.md
@@ -0,0 +1,78 @@
+---
+title: "Android unit testing"
+sidebar_label: "Unit tests"
+---
+
+## Why do we perform unit testing?
+
+Unit testing helps you build your features with confidence and ensures that your code behaves as expected. It should be a tool to assist development, not a burden. [Test-Driven Development (TDD)](https://en.wikipedia.org/wiki/Test-driven_development) is a well-known methodology where tests are written before or alongside the actual code. This approach allows you to quickly validate your code without waiting for the entire application to run.
+
+:::info
+Don't write tests just for the sake of writing tests. Tests should either help you during development or assist future developers in maintaining the codebase.
+:::
+
+Unit tests focus on testing **your code**. Avoid testing the behavior of external libraries unless absolutely necessary. If you find yourself testing a library's behavior, consider contributing to that library instead and add the test there.
+
+:::note
+There are exceptions to this rule. Sometimes, we add tests to ensure that the behavior of a library doesn't change over time. In such cases, explicitly document the reason for the test.
+:::
+
+## Testing the public interface
+
+Focus on testing the **public API** of your classes rather than every single function. Writing tests for all functions, especially small ones, can lead to an overwhelming number of tests that are difficult to maintain. By concentrating on the public interface, you ensure that your tests remain relevant and resilient to internal changes.
+
+When you need to access private parts of a class for testing, consider using the [VisibleForTesting](https://developer.android.com/reference/kotlin/androidx/annotation/VisibleForTesting) annotation. This annotation allows you to expose private methods or properties for testing purposes only. The [linter](../linter) ensures that this exposure is limited to the test scope.
+
+:::note
+Avoid using `VisibleForTesting` unless absolutely necessary. It’s better to design your code in a way that doesn’t require exposing private members.
+:::
+
+## Test frameworks and mocking
+
+The project is configured to use [JUnit 5](https://junit.org/junit5/), which should be your primary testing framework.
+
+### Mocking
+
+When writing unit tests, you often need to isolate the code under test by mocking its dependencies. The project uses [MockK](https://mockk.io/). Use this tool to create mocks or fakes for external dependencies, ensuring that your tests remain focused on the behavior of your code.
+
+## Testing with Android APIs
+
+For cases where your code interacts with Android APIs that cannot be mocked or faked properly, the project includes [Robolectric](https://robolectric.org/). Robolectric allows you to run Android-specific tests in a JVM environment, avoiding the need for an emulator.
+
+### When to use Robolectric
+
+- Use Robolectric when testing Android APIs that are difficult to mock or fake.
+- Prefer Robolectric over instrumentation tests whenever possible, as instrumentation tests require more resources and are more complex to set up.
+
+### Caveats
+
+- Robolectric does not work with JUnit 5 (follow the [issue](https://github.com/robolectric/robolectric/issues/3477)). To address this, the project includes a dependency on JUnit 4 for tests that require Robolectric.
+- Ensure that the code you are testing does not depend on the state of the Android API, as this can lead to unreliable tests. If that is the case, consider writing an [instrumented test](integration_testing).
+
+## Best practices for unit testing
+
+- **Write tests alongside code**: Writing tests as you develop ensures that your code is testable and reduces the risk of bugs.
+- **Focus on behavior**: Test the behavior of your code, not its implementation details.
+- **Keep tests small and focused**: Each test should validate a single behavior or scenario.
+- **Use descriptive test names**: Test names should clearly describe the scenario being tested and the expected outcome.
+- **Mock external dependencies**: Use mocks or fakes to isolate the code under test.
+- **Avoid over-testing**: Don’t write tests for trivial methods or internal implementation details unless they are critical to the functionality.
+
+## Example: writing a unit test
+
+Here’s an example of a well-structured unit test using JUnit 5 and MockK:
+
+```kotlin
+@Test
+fun `Given a valid user ID when fetching user details then return user data`() {
+ // Given
+ val userId = "12345"
+ val expectedUser = User(id = userId, name = "John Doe")
+ every { userRepository.getUser(userId) } returns expectedUser
+
+ // When
+ val result = userService.getUserDetails(userId)
+
+ // Then
+ assertEquals(expectedUser, result)
+}
diff --git a/docs/android/tips/compose_101.md b/docs/android/tips/compose_101.md
new file mode 100644
index 00000000..7799c1a1
--- /dev/null
+++ b/docs/android/tips/compose_101.md
@@ -0,0 +1,74 @@
+---
+title: "Jetpack Compose 101"
+sidebar_label: "Jetpack Compose 101"
+---
+
+## How to create a new screen in the existing app and iterate quickly
+
+To create a new screen in the app and iterate quickly, follow these steps:
+
+1. **Extract the Compose UI screen**:
+ Create a dedicated Kotlin file for your Compose UI screen. Use the `@Preview` annotation to enable preview capabilities within the IDE. This also makes the screen compatible with [screenshot testing](../testing/screenshot_testing).
+
+2. **Leverage hot reload**:
+ After the first build of the app, navigate to your screen. Jetpack Compose provides hot reload capabilities out of the box, allowing you to see changes in real-time. However, note that there are some limitations, such as not being able to reload changes to certain structural elements.
+
+3. **Use previews effectively**:
+ Use multiple `@Preview` annotations to test your screen in different configurations (e.g., light/dark mode, different screen sizes). This helps ensure your UI adapts well to various scenarios.
+
+## Theme/Design system
+
+We use a custom Compose theme, `io.homeassistant.companion.android.util.compose.HomeAssistantAppTheme`, which is based on [Material Design 2](https://m2.material.io/). You must use this theme to ensure consistency with the application's overall UI.
+
+### Key points
+
+- **Material Design 2**: The theme adheres to Material Design 2 principles, ensuring a cohesive look and feel.
+- **Custom components**: If you need to create custom components, ensure they align with the existing theme and design system.
+- **Dark mode support**: The theme supports both light and dark modes. Test your screen in both modes to ensure proper styling.
+
+## Best practices for working with Jetpack Compose
+
+- **Keep UI code modular**: Break down your UI into small, reusable composables. This improves readability and makes testing easier.
+- **Use state hoisting**: Follow the [state hoisting pattern](https://developer.android.com/jetpack/compose/state#state-hoisting) to manage state effectively. This ensures that your composables remain stateless and reusable.
+- **Test with previews**: Use `@Preview` annotations to test your composables in isolation. Add parameters to simulate different states and configurations.
+- **Follow accessibility guidelines**: Ensure your UI is accessible by providing meaningful content descriptions and testing with accessibility tools.
+- **Use style**: Apply appropriate styling to text components.
+
+## Example: creating a new screen
+
+Here’s an example of how to create a new Compose screen with a preview:
+
+```kotlin
+// filepath: /path/to/your/screen/MyNewScreen.kt
+
+@Composable
+fun MyNewScreen(
+ title: String,
+ onButtonClick: () -> Unit
+) {
+ HomeAssistantAppTheme {
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(16.dp),
+ verticalArrangement = Arrangement.Center,
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Text(text = title, style = MaterialTheme.typography.h4)
+ Spacer(modifier = Modifier.height(16.dp))
+ Button(onClick = onButtonClick) {
+ Text(text = "Click Me")
+ }
+ }
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+fun MyNewScreenPreview() {
+ MyNewScreen(
+ title = "Welcome to Home Assistant",
+ onButtonClick = {}
+ )
+}
+```
diff --git a/docs/android/tips/dependencies.md b/docs/android/tips/dependencies.md
new file mode 100644
index 00000000..2064d863
--- /dev/null
+++ b/docs/android/tips/dependencies.md
@@ -0,0 +1,67 @@
+---
+title: "Android dependencies"
+sidebar_label: "Dependencies"
+---
+
+## Version catalog
+
+We use the [version catalog](https://docs.gradle.org/current/userguide/version_catalogs.html) to manage all libraries directly used in the project. This is the **only allowed method** for adding dependencies. Adding a dependency outside of the catalog is strictly forbidden to maintain consistency and traceability.
+
+### Benefits of using a version catalog
+
+- **Centralized management**: All dependencies are defined in one place (`gradle/libs.versions.toml`), making it easier to track and update them.
+- **Consistency**: Ensures that all modules use the same versions of shared dependencies.
+- **Simplified updates**: Makes it easier to update dependencies across the entire project.
+
+## Managing dependencies and lockfiles
+
+This project utilizes Gradle's [dependency locking](https://docs.gradle.org/current/userguide/dependency_locking.html) feature to ensure consistent and reproducible builds by tracking the precise versions of all libraries used.
+
+### Why use dependency locking
+
+- **Reproducible builds**: Ensures that builds are consistent across different environments by locking the exact versions of all dependencies.
+- **Avoids surprises**: Prevents unexpected updates to transitive dependencies that could break the build.
+
+### Updating dependencies and lockfiles
+
+When adding or updating a dependency in `gradle/libs.versions.toml`, it's crucial to also update the corresponding lockfiles. The lockfiles capture the exact versions of all direct and transitive dependencies.
+
+To update the lockfiles, run the following command from the project root:
+
+```bash
+./gradlew alldependencies --write-locks
+```
+
+This command resolves all dependencies and updates the gradle.lockfile in each module.
+
+:::info
+If the version catalog is updated but the lockfiles are not updated, the CI pipeline will fail.
+:::
+
+## Automated dependency updates with Renovate
+
+To streamline dependency management, we've integrated [Renovate](https://docs.renovatebot.com/) into the repository. Renovate automatically creates pull requests to update dependencies and the lockfiles.
+
+### How Renovate works
+
+- **Automated updates**: Renovate scans the project for outdated dependencies and creates pull requests to update them.
+- **Lockfile updates**: Renovate ensures that lockfiles are updated alongside the dependencies.
+- **Custom configuration**: Renovate is configured to respect the project's versioning policies and update strategies.
+
+:::note
+Renovate is configured to wait 3 days after a new release of a library is published before opening a pull request. This delay allows early adopters to identify and report any obvious issues.
+:::
+
+### Benefits of using Renovate
+
+- **Saves time**: Automates the tedious process of checking for and updating dependencies.
+- **Reduces risk**: Ensures that updates are applied consistently and tested through the CI pipeline.
+- **Improves security**: Keeps dependencies up-to-date, reducing the risk of vulnerabilities.
+
+## Using non-stable versions
+
+While we aim to stay up to date with the libraries we use, we prioritize stability. Therefore, we avoid using `alpha`, `beta`, `rc`, or other non-stable versions.
+
+:::note
+In very specific cases, we have agreed on a PR to use an `alpha` version to access new features. However, this comes with the cost of addressing issues after each update, as the API is not stable. A notable example is the `wear-compose-material` library.
+:::
diff --git a/docs/android/tips/fcm_push_notification.md b/docs/android/tips/fcm_push_notification.md
new file mode 100644
index 00000000..b68d612d
--- /dev/null
+++ b/docs/android/tips/fcm_push_notification.md
@@ -0,0 +1,48 @@
+---
+title: "Android FCM push notifications"
+sidebar_label: "FCM push notifications"
+---
+
+## FCM push notifications setup
+
+:::note
+Setting up Firebase Cloud Messaging (FCM) can be complex. Unless you specifically need it, consider using notifications through the WebSocket instead for development.
+:::
+
+If you want your own FCM setup for push notifications, follow these steps:
+
+1. **Create a Firebase project**
+ Go to the [Firebase Console](https://console.firebase.google.com) and create a new Firebase project.
+
+2. **Add Android apps to the Firebase project**
+ Add the following package names as Android apps in your Firebase project:
+ - `io.homeassistant.companion.android`
+ - `io.homeassistant.companion.android.debug`
+ - `io.homeassistant.companion.android.minimal`
+ - `io.homeassistant.companion.android.minimal.debug`
+
+3. **Deploy the push notification service**
+ Visit the [mobile-apps-fcm-push repository](https://github.com/home-assistant/mobile-apps-fcm-push) and deploy the service to your Firebase project.
+
+4. **Set the push notification URL**
+ Once you have the `androidV1` URL for the deployed service, add it to your `${GRADLE_USER_HOME}/gradle.properties` file. For example:
+
+ ```properties
+ homeAssistantAndroidPushUrl=https://mydomain.cloudfunctions.net/androidV1
+ ```
+
+ Optionally, you can also define the rate limit function URL:
+
+ ```properties
+ homeAssistantAndroidRateLimitUrl=https://mydomain.cloudfunctions.net/checkRateLimits
+ ```
+
+5. **Download and place the `google-services.json` File**
+ Download the `google-services.json` file from your Firebase project and place it in the following folders:
+ - `/app`
+ - `/automotive`
+ - `/wear`
+
+:::note
+The `google-services.json` file must include client IDs for all the package names listed above. Without this, FCM push notifications will not work (only WebSocket notifications will function).
+:::
diff --git a/docs/android/tips/leak_canary.md b/docs/android/tips/leak_canary.md
new file mode 100644
index 00000000..960dcff6
--- /dev/null
+++ b/docs/android/tips/leak_canary.md
@@ -0,0 +1,38 @@
+---
+title: "LeakCanary 🐤"
+sidebar_label: "LeakCanary"
+---
+
+## How to disable LeakCanary in debug builds
+
+[LeakCanary](https://square.github.io/leakcanary/) is a powerful tool for detecting memory leaks in Android applications. However, there are scenarios where you might want to disable it, such as when preparing a debug build for performance testing or when it's not needed.
+
+### Disabling LeakCanary via Gradle command
+
+You can disable LeakCanary manually by passing the `-PnoLeakCanary` flag in the Gradle command. For example:
+
+```bash
+./gradlew app:assembleFullDebug -PnoLeakCanary
+```
+
+This flag ensures that LeakCanary is excluded from the build.
+
+### Disabling LeakCanary via properties file
+
+Alternatively, you can disable LeakCanary by setting the noLeakCanary property in the gradle.properties file. This can be done at either the project level or the home level.
+
+```properties
+noLeakCanary=true
+```
+
+::::warning
+If you disable LeakCanary, you need to update the lockfile; otherwise, Gradle will complain about an issue with the dependencies.
+
+[How to update lockfiles](dependencies#updating-dependencies-and-lockfiles).
+::::
+
+## Best practices for using LeakCanary
+
+- **Regularly monitor memory leaks**: Use LeakCanary during development to identify and fix memory leaks early.
+- **Document known leaks**: If a memory leak is caused by a third-party library and cannot be fixed immediately, document it for future reference.
+- **Report leaks**: If a leak is reported by LeakCanary, open a GitHub issue.
diff --git a/docs/android/tips/lollipop_emulator.md b/docs/android/tips/lollipop_emulator.md
new file mode 100644
index 00000000..e904d536
--- /dev/null
+++ b/docs/android/tips/lollipop_emulator.md
@@ -0,0 +1,12 @@
+---
+title: "Test on lollipop emulator"
+sidebar_label: "Lollipop emulator"
+---
+
+## Overview
+
+To test the app on an Android emulator running Lollipop (Android API 21), you need to update the outdated WebView to ensure compatibility. Without this update, the WebView will crash.
+
+## Updating the WebView
+
+To update the WebView, download the latest WebView APK and follow the instructions provided in this [StackOverflow post](https://stackoverflow.com/a/79514205/3289338).
diff --git a/docs/android/tips/sarif_reports.md b/docs/android/tips/sarif_reports.md
new file mode 100644
index 00000000..1a5299eb
--- /dev/null
+++ b/docs/android/tips/sarif_reports.md
@@ -0,0 +1,29 @@
+---
+title: "SARIF reports"
+sidebar_label: "SARIF reports"
+---
+
+## Overview
+
+SARIF (Static Analysis Results Interchange Format) reports are used in GitHub Actions to notify about issues found by linters or code style tools. This guide explains how SARIF reports are handled in our project and how we merge multiple reports into one for compatibility with GitHub Actions.
+
+## Why SARIF reports?
+
+GitHub Actions supports SARIF reports for code scanning, making it easier to identify and address issues directly in pull requests or the repository's security tab. Learn more about SARIF in the [GitHub documentation](https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning).
+
+## Handling multiple SARIF reports
+
+### The problem
+
+In our project, we use multiple Gradle modules. When running tasks that generate SARIF reports, each module produces its own report. However, GitHub Actions no longer supports processing multiple SARIF reports in a single workflow run.
+
+### The solution
+
+To address this, we use a custom Python script to merge all SARIF reports into a single file. This ensures compatibility with GitHub Actions.
+
+The script for merging SARIF reports is located at `.github/scripts/merge_sarif.py`. Follow these steps to use it:
+
+1. **Generate SARIF reports**
+2. Run `python3 .github/scripts/merge_sarif.py`
+
+You will have a new SARIF file at the root level of the repository.
diff --git a/docusaurus.config.js b/docusaurus.config.js
index ee92d7df..8ec02bee 100644
--- a/docusaurus.config.js
+++ b/docusaurus.config.js
@@ -33,6 +33,7 @@ module.exports = {
{ to: "docs/operating-system", label: "Operating System" },
{ to: "docs/voice/overview", label: "Voice" },
{ to: "docs/translations", label: "Translations" },
+ { to: "docs/android", label: "Android" },
],
},
{ to: "docs/misc", label: "Misc", position: "left" },
diff --git a/sidebars.js b/sidebars.js
index 08995c45..a0398bac 100644
--- a/sidebars.js
+++ b/sidebars.js
@@ -321,4 +321,40 @@ module.exports = {
],
},
],
+ Android: [
+ "android",
+ "android/get_started",
+ "android/architecture",
+ "android/targets",
+ "android/app_flavors",
+ {
+ type: "category",
+ label: "Testing",
+ items: [
+ "android/testing/introduction",
+ "android/testing/unit_testing",
+ "android/testing/screenshot_testing",
+ "android/testing/integration_testing",
+ ],
+ },
+ {
+ type: "category",
+ label: "Tips",
+ items: [
+ "android/tips/compose_101",
+ "android/tips/dependencies",
+ "android/tips/leak_canary",
+ "android/tips/lollipop_emulator",
+ "android/tips/fcm_push_notification",
+ "android/tips/sarif_reports",
+ ],
+ },
+ "android/best_practices",
+ "android/ci",
+ "android/codestyle",
+ "android/linter",
+ "android/submit",
+ "android/release",
+ "translations",
+ ]
};
diff --git a/src/pages/index.js b/src/pages/index.js
index fcee6d82..8399dd31 100644
--- a/src/pages/index.js
+++ b/src/pages/index.js
@@ -31,6 +31,12 @@ const features = [
{" "}
Explains how to develop the user interface of Home Assistant.
+
+
+ Android.
+ {" "}
+ Explains how to contribute to the Android companion app.
+
>
),
},
@@ -62,6 +68,11 @@ const features = [
Home Assistant Frontend
+
+
+ Home Assistant Android
+
+
>
),