# Kotlin multiplatform / multi-format reflectionless serialization

[![Kotlin Stable](https://kotl.in/badges/stable.svg)](https://kotlinlang.org/docs/components-stability.html)
[![JetBrains official project](https://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0)
[![TeamCity build](https://img.shields.io/teamcity/http/teamcity.jetbrains.com/s/KotlinTools_KotlinxSerialization_Ko.svg)](https://teamcity.jetbrains.com/viewType.html?buildTypeId=KotlinTools_KotlinxSerialization_Ko&guest=1)
[![Kotlin](https://img.shields.io/badge/kotlin-2.0.0-blue.svg?logo=kotlin)](http://kotlinlang.org)
[![Maven Central](https://img.shields.io/maven-central/v/org.jetbrains.kotlinx/kotlinx-serialization-core/1.7.0)](https://central.sonatype.com/artifact/org.jetbrains.kotlinx/kotlinx-serialization-core/1.7.0)
[![KDoc link](https://img.shields.io/badge/API_reference-KDoc-blue)](https://kotlinlang.org/api/kotlinx.serialization/)
[![Slack channel](https://img.shields.io/badge/chat-slack-blue.svg?logo=slack)](https://kotlinlang.slack.com/messages/serialization/)

Kotlin serialization consists of a compiler plugin, that generates visitor code for serializable classes,
 runtime library with core serialization API and support libraries with various serialization formats.

* Supports Kotlin classes marked as `@Serializable` and standard collections.
* Provides [JSON](formats/README.md#JSON), [Protobuf](formats/README.md#ProtoBuf), [CBOR](formats/README.md#CBOR), [Hocon](formats/README.md#HOCON) and [Properties](formats/README.md#properties) formats.
* Complete multiplatform support: JVM, JS and Native.

## Table of contents

* [Introduction and references](#introduction-and-references)
* [Setup](#setup)
  * [Gradle](#gradle)
    * [1) Setting up the serialization plugin](#1-setting-up-the-serialization-plugin)
    * [2) Dependency on the JSON library](#2-dependency-on-the-json-library)
  * [Android](#android)
  * [Multiplatform (Common, JS, Native)](#multiplatform-common-js-native)
  * [Maven](#maven)
  * [Bazel](#bazel)

* **Additional links**
  * [Kotlin Serialization Guide](docs/serialization-guide.md)
  * [Full API reference](https://kotlinlang.org/api/kotlinx.serialization/)
  * [Submitting issues and PRs](CONTRIBUTING.md)
  * [Building this library](docs/building.md)

## Introduction and references

Here is a small example.

```kotlin
import kotlinx.serialization.*
import kotlinx.serialization.json.*

@Serializable
data class Project(val name: String, val language: String)

fun main() {
    // Serializing objects
    val data = Project("kotlinx.serialization", "Kotlin")
    val string = Json.encodeToString(data)
    println(string) // {"name":"kotlinx.serialization","language":"Kotlin"}
    // Deserializing back into objects
    val obj = Json.decodeFromString<Project>(string)
    println(obj) // Project(name=kotlinx.serialization, language=Kotlin)
}
```

> You can get the full code [here](guide/example/example-readme-01.kt).

**Read the [Kotlin Serialization Guide](docs/serialization-guide.md) for all details.**

You can find auto-generated documentation website on [kotlinlang.org](https://kotlinlang.org/api/kotlinx.serialization/).

## Setup

[New versions](https://plugins.gradle.org/plugin/org.jetbrains.kotlin.plugin.serialization) of the serialization plugin are released in tandem with each new Kotlin compiler version.

Using Kotlin Serialization requires Kotlin compiler `1.4.0` or higher.
Make sure you have the corresponding Kotlin plugin installed in the IDE, no additional plugins for IDE are required.

### Gradle

To set up kotlinx.serialization, you have to do two things:
1) Add the **[serialization plugin](#1-setting-up-the-serialization-plugin)**.
2) Add the **[serialization library dependency](#2-dependency-on-the-json-library)**.

#### 1) Setting up the serialization plugin

You can set up the serialization plugin with the Kotlin plugin using the
[Gradle plugins DSL](https://docs.gradle.org/current/userguide/plugins.html#sec:plugins_block):

Kotlin DSL:

```kotlin
plugins {
    kotlin("jvm") version "2.0.0" // or kotlin("multiplatform") or any other kotlin plugin
    kotlin("plugin.serialization") version "2.0.0"
}
```

Groovy DSL:

```gradle
plugins {
    id 'org.jetbrains.kotlin.multiplatform' version '2.0.0'
    id 'org.jetbrains.kotlin.plugin.serialization' version '2.0.0'
}
```

> Kotlin versions before 1.4.0 are not supported by the stable release of Kotlin serialization.

  Using apply plugin (the old way)

First, you have to add the serialization plugin to your classpath as the other [compiler plugins](https://kotlinlang.org/docs/reference/compiler-plugins.html):

Kotlin DSL:

```kotlin
buildscript {
    repositories { mavenCentral() }

    dependencies {
        val kotlinVersion = "2.0.0"
        classpath(kotlin("gradle-plugin", version = kotlinVersion))
        classpath(kotlin("serialization", version = kotlinVersion))
    }
}
```

Groovy DSL:

```gradle
buildscript {
    ext.kotlin_version = '2.0.0'
    repositories { mavenCentral() }

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
    }
}
```

Then you can `apply plugin` (example in Groovy):

```gradle
apply plugin: 'kotlin' // or 'kotlin-multiplatform' for multiplatform projects
apply plugin: 'kotlinx-serialization'
```

#### 2) Dependency on the JSON library

After setting up the plugin, you have to add a dependency on the serialization library.
Note that while the plugin has version the same as the compiler one, runtime library has different coordinates, repository and versioning.

Kotlin DSL:

```kotlin
repositories {
    mavenCentral()
}

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.0")
}
```

Groovy DSL:

```gradle
repositories {
    mavenCentral()
}

dependencies {
    implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.0"
}
```

>We also provide `kotlinx-serialization-core` artifact that contains all serialization API but does not have a bundled serialization format with it

### Android

By default, proguard rules are supplied with the library.
[These rules](rules/common.pro) keep serializers for _all_ serializable classes that are retained after shrinking,
so you don't need additional setup.

**However, these rules do not affect serializable classes if they have named companion objects.**

If you want to serialize classes with named companion objects, you need to add and edit rules below to your `proguard-rules.pro` configuration.

Note that the rules for R8 differ depending on the [compatibility mode](https://r8.googlesource.com/r8/+/refs/heads/master/compatibility-faq.md) used.

Example of named companion rules for ProGuard and R8 compatibility mode

```proguard
# Serializer for classes with named companion objects are retrieved using `getDeclaredClasses`.
# If you have any, replace classes with those containing named companion objects.
-keepattributes InnerClasses # Needed for `getDeclaredClasses`.

-if @kotlinx.serialization.Serializable class
com.example.myapplication.HasNamedCompanion, # <-- List serializable classes with named companions.
com.example.myapplication.HasNamedCompanion2
{
    static **$* *;
}
-keepnames class <1>$$serializer { # -keepnames suffices; class is kept when serializer() is kept.
    static <1>$$serializer INSTANCE;
}
```

Example of named companion rules for R8 full mode

```proguard
# Serializer for classes with named companion objects are retrieved using `getDeclaredClasses`.
# If you have any, replace classes with those containing named companion objects.
-keepattributes InnerClasses # Needed for `getDeclaredClasses`.

-if @kotlinx.serialization.Serializable class
com.example.myapplication.HasNamedCompanion, # <-- List serializable classes with named companions.
com.example.myapplication.HasNamedCompanion2
{
    static **$* *;
}
-keepnames class <1>$$serializer { # -keepnames suffices; class is kept when serializer() is kept.
    static <1>$$serializer INSTANCE;
}

# Keep both serializer and serializable classes to save the attribute InnerClasses
-keepclasseswithmembers, allowshrinking, allowobfuscation, allowaccessmodification class
com.example.myapplication.HasNamedCompanion, # <-- List serializable classes with named companions.
com.example.myapplication.HasNamedCompanion2
{
    *;
}
```

In case you want to exclude serializable classes that are used, but never serialized at runtime,
you will need to write custom rules with narrower [class specifications](https://www.guardsquare.com/manual/configuration/usage).

### Multiplatform (Common, JS, Native)

Most of the modules are also available for Kotlin/JS and Kotlin/Native.
You can add dependency to the required module right to the common source set:
```gradle
commonMain {
    dependencies {
        // Works as common dependency as well as the platform one
        implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:$serialization_version"
    }
}
```
The same artifact coordinates can be used to depend on platform-specific artifact in platform-specific source-set.

### Maven

Ensure the proper version of Kotlin and serialization version:

```xml
<properties>
    <kotlin.version>2.0.0</kotlin.version>
    <serialization.version>1.7.0</serialization.version>
</properties>
```

Add serialization plugin to Kotlin compiler plugin:

```xml
<build>
    <plugins>
        <plugin>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-maven-plugin</artifactId>
            <version>${kotlin.version}</version>
            <executions>
                <execution>
                    <id>compile</id>
                    <phase>compile</phase>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <compilerPlugins>
                    <plugin>kotlinx-serialization</plugin>
                </compilerPlugins>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>org.jetbrains.kotlin</groupId>
                    <artifactId>kotlin-maven-serialization</artifactId>
                    <version>${kotlin.version}</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>
```

Add dependency on serialization runtime library:

```xml
<dependency>
    <groupId>org.jetbrains.kotlinx</groupId>
    <artifactId>kotlinx-serialization-json</artifactId>
    <version>${serialization.version}</version>
</dependency>
```

### Bazel

To setup the Kotlin compiler plugin for Bazel, follow [the
example](https://github.com/bazelbuild/rules_kotlin/tree/master/examples/plugin/src/serialization)
from the `rules_kotlin` repository.


# AboutLibraries

.. collects all dependency details including licenses at compile time, and offers simple APIs to visualize these in the app.
*No runtime overhead.* Strong caching. Any gradle dependency is supported.

-------

    What's included 🚀 •
    Setup 🛠 •
    Gradle API •
    SDK Docs 📖  •
    Plugin Docs 📖 •
    Migration Guide 🧬 •
    Sample App

-------

### What's included 🚀

- Kotlin Multiplatform support (including wasm)
- Lightweight multiplatform core module
  - Access all generated information
  - Build custom UIs
- Compose UI module
- Gradle Plugin
  - Generating dependency / license metadata
  - Different exports, compliance report
  - Identify possible project funding
  - License *strict mode*
- Simple and fast integration

# Screenshots

![Screenshots](https://raw.githubusercontent.com/mikepenz/AboutLibraries/develop/DEV/screenshots/Screenshots.png)

# Setup

## Latest releases 🛠

- Kotlin 2.x && Multiplatform && Compose && Plugin | [v11.2.1](https://github.com/mikepenz/AboutLibraries/tree/v11.2.1)

## Gradle Plugin

AboutLibraries v10 includes a completely redone plugin, with build cache support. It includes all dependencies as found based on the gradle configuration.

> The gradle plugin is hosted via [Gradle Plugins](https://plugins.gradle.org/plugin/com.mikepenz.aboutlibraries.plugin).

Using the plugins DSL (for single modules)

```gradle
// Root build.gradle
id 'com.mikepenz.aboutlibraries.plugin' version "${latestAboutLibsRelease}" apply false

// App build.gradle
id 'com.mikepenz.aboutlibraries.plugin'
```

Using the plugins DSL (for whole project)

```gradle
// Root build.gradle
id 'com.mikepenz.aboutlibraries.plugin' version "${latestAboutLibsRelease}"
```

Using legacy plugin application

```gradle
// Root build.gradle
classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:${latestAboutLibsRelease}"

// App build.gradle
apply plugin: 'com.mikepenz.aboutlibraries.plugin'
```

Gradle Plugin Configuration

## Gradle Plugin Configuration

It is possible to provide custom configurations / adjustments to the automatic detection. This can be done via the gradle plugin.

```groovy
aboutLibraries {
    // - If the automatic registered android tasks are disabled, a similar thing can be achieved manually
    // - `./gradlew app:exportLibraryDefinitions -PaboutLibraries.exportPath=src/main/res/raw`
    // - the resulting file can for example be added as part of the SCM
    registerAndroidTasks = false
    // Define the output file name. Modifying this will disable the automatic meta data discovery for supported platforms.
    outputFileName = "aboutlibraries.json"
    // Define the path configuration files are located in. E.g. additional libraries, licenses to add to the target .json
    // Warning: Please do not use the parent folder of a module as path, as this can result in issues. More details: https://github.com/mikepenz/AboutLibraries/issues/936
    configPath = "config"
    // Allow to enable "offline mode", will disable any network check of the plugin (including [fetchRemoteLicense] or pulling spdx license texts)
    offlineMode = false
    // Enable fetching of "remote" licenses.  Uses the API of supported source hosts
    // See https://github.com/mikepenz/AboutLibraries#special-repository-support
    fetchRemoteLicense = true
    // Enables fetching of "remote" funding information. Uses the API of supported source hosts
    // See https://github.com/mikepenz/AboutLibraries#special-repository-support
    fetchRemoteFunding = true
    // (Optional) GitHub token to raise API request limit to allow fetching more licenses
    gitHubApiToken = getLocalOrGlobalProperty("github.pat")
    // Full license text for license IDs mentioned here will be included, even if no detected dependency uses them.
    additionalLicenses = ["mit", "mpl_2_0"]
    // Allows to exclude some fields from the generated meta data field.
    excludeFields = ["developers", "funding"]
    // Enable inclusion of `platform` dependencies in the library report
    includePlatform = true
    // Define the strict mode, will fail if the project uses licenses not allowed
    // - This will only automatically fail for Android projects which have `registerAndroidTasks` enabled
    // For non Android projects, execute `exportLibraryDefinitions`
    strictMode = com.mikepenz.aboutlibraries.plugin.StrictMode.FAIL
    // Allowed set of licenses, this project will be able to use without build failure
    allowedLicenses = ["Apache-2.0", "asdkl"]
    // Enable the duplication mode, allows to merge, or link dependencies which relate
    duplicationMode = com.mikepenz.aboutlibraries.plugin.DuplicateMode.LINK
    // Configure the duplication rule, to match "duplicates" with
    duplicationRule = com.mikepenz.aboutlibraries.plugin.DuplicateRule.SIMPLE
    // Enable pretty printing for the generated JSON file
    prettyPrint = false
    // Allows to only collect dependencies of specific variants during the `collectDependencies` step.
    filterVariants = ["debug", "release"]
}
```

Full documentation of all available gradle plugin configurations: https://github.com/mikepenz/AboutLibraries/blob/develop/plugin-build/plugin/src/main/kotlin/com/mikepenz/aboutlibraries/plugin/AboutLibrariesExtension.kt

## Modify libraries / licenses

The plugin offers the ability to add additional libraries or licenses by specifying these under the `libraries` and respectively `licenses` directory, within the defined `configPath`.
This can be seen here: https://github.com/mikepenz/AboutLibraries/blob/develop/config/

### Libraries

Provide additional or modify existing libraries via a `.json` file per library.
If the `uniqueId` overlaps, a merge will occur.

```json
{
  "uniqueId": "com.mikepenz:materialdrawer",
  "developers": [
    {
      "name": "Mike Penz",
      "organisationUrl": "https://mikepenz.dev"
    }
  ],
  "description": "(Merged) The flexible, easy to use, all in one drawer library for your Android project.",
  "name": "ABC MaterialDrawer Library",
  "website": "https://github.com/mikepenz/MaterialDrawer"
}
```

### Licenses

Provide additional or modify existing licenses via a `.json` file per license.

```json
{
  "content": "This is the Android Software Development Kit License Agreement\n<br />\n1. Introduction\n<br />\n1.1 The Android Software Development Kit (referred to in the License Agreement as the \"SDK\" and specifically including the Android system files, packaged APIs, and Google APIs add-ons) is licensed to you subject to the terms of the License Agreement. The License Agreement forms a legally binding contract between you and Google in relation to your use of the SDK.\n<br />\n1.2 \"Android\" means the Android software stack for devices, as made available under the Android Open Source Project, which is located at the following URL: http://source.android.com/, as updated from time to time.\n<br />\n1.3 A \"compatible implementation\" means any Android device that (i) complies with the Android Compatibility Definition document, which can be found at the Android compatibility website (http://source.android.com/compatibility) and which may be updated from time to time; and (ii) successfully passes the Android Compatibility Test Suite (CTS).\n<br />\n1.4 \"Google\" means Google LLC, a Delaware corporation with principal place of business at 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States.\n<br />\n2. Accepting this License Agreement\n<br />\n2.1 In order to use the SDK, you must first agree to the License Agreement. You may not use the SDK if you do not accept the License Agreement.\n<br />\n2.2 By clicking to accept, you hereby agree to the terms of the License Agreement.\n<br />\n2.3 You may not use the SDK and may not accept the License Agreement if you are a person barred from receiving the SDK under the laws of the United States or other countries, including the country in which you are resident or from which you use the SDK.\n<br />\n2.4 If you are agreeing to be bound by the License Agreement on behalf of your employer or other entity, you represent and warrant that you have full legal authority to bind your employer or such entity to the License Agreement. If you do not have the requisite authority, you may not accept the License Agreement or use the SDK on behalf of your employer or other entity.\n<br />\n3. SDK License from Google\n<br />\n3.1 Subject to the terms of the License Agreement, Google grants you a limited, worldwide, royalty-free, non-assignable, non-exclusive, and non-sublicensable license to use the SDK solely to develop applications for compatible implementations of Android.\n<br />\n3.2 You may not use this SDK to develop applications for other platforms (including non-compatible implementations of Android) or to develop another SDK. You are of course free to develop applications for other platforms, including non-compatible implementations of Android, provided that this SDK is not used for that purpose.\n<br />\n3.3 You agree that Google or third parties own all legal right, title and interest in and to the SDK, including any Intellectual Property Rights that subsist in the SDK. \"Intellectual Property Rights\" means any and all rights under patent law, copyright law, trade secret law, trademark law, and any and all other proprietary rights. Google reserves all rights not expressly granted to you.\n<br />\n3.4 You may not use the SDK for any purpose not expressly permitted by the License Agreement.  Except to the extent required by applicable third party licenses, you may not copy (except for backup purposes), modify, adapt, redistribute, decompile, reverse engineer, disassemble, or create derivative works of the SDK or any part of the SDK.\n<br />\n3.5 Use, reproduction and distribution of components of the SDK licensed under an open source software license are governed solely by the terms of that open source software license and not the License Agreement.\n<br />\n3.6 You agree that the form and nature of the SDK that Google provides may change without prior notice to you and that future versions of the SDK may be incompatible with applications developed on previous versions of the SDK. You agree that Google may stop (permanently or temporarily) providing the SDK (or any features within the SDK) to you or to users generally at Google's sole discretion, without prior notice to you.\n<br />\n3.7 Nothing in the License Agreement gives you a right to use any of Google's trade names, trademarks, service marks, logos, domain names, or other distinctive brand features.\n<br />\n3.8 You agree that you will not remove, obscure, or alter any proprietary rights notices (including copyright and trademark notices) that may be affixed to or contained within the SDK.\n<br />\n4. Use of the SDK by You\n<br />\n4.1 Google agrees that it obtains no right, title or interest from you (or your licensors) under the License Agreement in or to any software applications that you develop using the SDK, including any intellectual property rights that subsist in those applications.\n<br />\n4.2 You agree to use the SDK and write applications only for purposes that are permitted by (a) the License Agreement and (b) any applicable law, regulation or generally accepted practices or guidelines in the relevant jurisdictions (including any laws regarding the export of data or software to and from the United States or other relevant countries).\n<br />\n4.3 You agree that if you use the SDK to develop applications for general public users, you will protect the privacy and legal rights of those users. If the users provide you with user names, passwords, or other login information or personal information, you must make the users aware that the information will be available to your application, and you must provide legally adequate privacy notice and protection for those users. If your application stores personal or sensitive information provided by users, it must do so securely. If the user provides your application with Google Account information, your application may only use that information to access the user's Google Account when, and for the limited purposes for which, the user has given you permission to do so.\n<br />\n4.4 You agree that you will not engage in any activity with the SDK, including the development or distribution of an application, that interferes with, disrupts, damages, or accesses in an unauthorized manner the servers, networks, or other properties or services of any third party including, but not limited to, Google or any mobile communications carrier.\n<br />\n4.5 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any data, content, or resources that you create, transmit or display through Android and/or applications for Android, and for the consequences of your actions (including any loss or damage which Google may suffer) by doing so.\n<br />\n4.6 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any breach of your obligations under the License Agreement, any applicable third party contract or Terms of Service, or any applicable law or regulation, and for the consequences (including any loss or damage which Google or any third party may suffer) of any such breach.\n<br />\n5. Your Developer Credentials\n<br />\n5.1 You agree that you are responsible for maintaining the confidentiality of any developer credentials that may be issued to you by Google or which you may choose yourself and that you will be solely responsible for all applications that are developed under your developer credentials.\n<br />\n6. Privacy and Information\n<br />\n6.1 In order to continually innovate and improve the SDK, Google may collect certain usage statistics from the software including but not limited to a unique identifier, associated IP address, version number of the software, and information on which tools and/or services in the SDK are being used and how they are being used. Before any of this information is collected, the SDK will notify you and seek your consent. If you withhold consent, the information will not be collected.\n<br />\n6.2 The data collected is examined in the aggregate to improve the SDK and is maintained in accordance with Google's Privacy Policy.\n<br />\n7. Third Party Applications\n<br />\n7.1 If you use the SDK to run applications developed by a third party or that access data, content or resources provided by a third party, you agree that Google is not responsible for those applications, data, content, or resources. You understand that all data, content or resources which you may access through such third party applications are the sole responsibility of the person from which they originated and that Google is not liable for any loss or damage that you may experience as a result of the use or access of any of those third party applications, data, content, or resources.\n<br />\n7.2 You should be aware the data, content, and resources presented to you through such a third party application may be protected by intellectual property rights which are owned by the providers (or by other persons or companies on their behalf). You may not modify, rent, lease, loan, sell, distribute or create derivative works based on these data, content, or resources (either in whole or in part) unless you have been specifically given permission to do so by the relevant owners.\n<br />\n7.3 You acknowledge that your use of such third party applications, data, content, or resources may be subject to separate terms between you and the relevant third party. In that case, the License Agreement does not affect your legal relationship with these third parties.\n<br />\n8. Using Android APIs\n<br />\n8.1 Google Data APIs\n<br />\n8.1.1 If you use any API to retrieve data from Google, you acknowledge that the data may be protected by intellectual property rights which are owned by Google or those parties that provide the data (or by other persons or companies on their behalf). Your use of any such API may be subject to additional Terms of Service. You may not modify, rent, lease, loan, sell, distribute or create derivative works based on this data (either in whole or in part) unless allowed by the relevant Terms of Service.\n<br />\n8.1.2 If you use any API to retrieve a user's data from Google, you acknowledge and agree that you shall retrieve data only with the user's explicit consent and only when, and for the limited purposes for which, the user has given you permission to do so. If you use the Android Recognition Service API, documented at the following URL: https://developer.android.com/reference/android/speech/RecognitionService, as updated from time to time, you acknowledge that the use of the API is subject to the Data Processing Addendum for Products where Google is a Data Processor, which is located at the following URL: https://privacy.google.com/businesses/gdprprocessorterms/, as updated from time to time. By clicking to accept, you hereby agree to the terms of the Data Processing Addendum for Products where Google is a Data Processor.\n<br />\n9. Terminating this License Agreement\n<br />\n9.1 The License Agreement will continue to apply until terminated by either you or Google as set out below.\n<br />\n9.2 If you want to terminate the License Agreement, you may do so by ceasing your use of the SDK and any relevant developer credentials.\n<br />\n9.3 Google may at any time, terminate the License Agreement with you if:<br />\n(A) you have breached any provision of the License Agreement; or<br />\n(B) Google is required to do so by law; or<br />\n(C) the partner with whom Google offered certain parts of SDK (such as APIs) to you has terminated its relationship with Google or ceased to offer certain parts of the SDK to you; or<br />\n(D) Google decides to no longer provide the SDK or certain parts of the SDK to users in the country in which you are resident or from which you use the service, or the provision of the SDK or certain SDK services to you by Google is, in Google's sole discretion, no longer commercially viable.<br />\n<br />\n9.4 When the License Agreement comes to an end, all of the legal rights, obligations and liabilities that you and Google have benefited from, been subject to (or which have accrued over time whilst the License Agreement has been in force) or which are expressed to continue indefinitely, shall be unaffected by this cessation, and the provisions of paragraph 14.7 shall continue to apply to such rights, obligations and liabilities indefinitely.\n<br />\n10. DISCLAIMER OF WARRANTIES\n<br />\n10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE RISK AND THAT THE SDK IS PROVIDED \"AS IS\" AND \"AS AVAILABLE\" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE.\n<br />\n10.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE.\n<br />\n10.3 GOOGLE FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.\n<br />\n11. LIMITATION OF LIABILITY\n<br />\n11.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS OF DATA, WHETHER OR NOT GOOGLE OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING.\n<br />\n12. Indemnification\n<br />\n12.1 To the maximum extent permitted by law, you agree to defend, indemnify and hold harmless Google, its affiliates and their respective directors, officers, employees and agents from and against any and all claims, actions, suits or proceedings, as well as any and all losses, liabilities, damages, costs and expenses (including reasonable attorneys fees) arising out of or accruing from (a) your use of the SDK, (b) any application you develop on the SDK that infringes any copyright, trademark, trade secret, trade dress, patent or other intellectual property right of any person or defames any person or violates their rights of publicity or privacy, and (c) any non-compliance by you with the License Agreement.\n<br />\n13. Changes to the License Agreement\n<br />\n13.1 Google may make changes to the License Agreement as it distributes new versions of the SDK. When these changes are made, Google will make a new version of the License Agreement available on the website where the SDK is made available.\n<br />\n14. General Legal Terms\n<br />\n14.1 The License Agreement constitutes the whole legal agreement between you and Google and governs your use of the SDK (excluding any services which Google may provide to you under a separate written agreement), and completely replaces any prior agreements between you and Google in relation to the SDK.\n<br />\n14.2 You agree that if Google does not exercise or enforce any legal right or remedy which is contained in the License Agreement (or which Google has the benefit of under any applicable law), this will not be taken to be a formal waiver of Google's rights and that those rights or remedies will still be available to Google.\n<br />\n14.3 If any court of law, having the jurisdiction to decide on this matter, rules that any provision of the License Agreement is invalid, then that provision will be removed from the License Agreement without affecting the rest of the License Agreement. The remaining provisions of the License Agreement will continue to be valid and enforceable.\n<br />\n14.4 You acknowledge and agree that each member of the group of companies of which Google is the parent shall be third party beneficiaries to the License Agreement and that such other companies shall be entitled to directly enforce, and rely upon, any provision of the License Agreement that confers a benefit on (or rights in favor of) them. Other than this, no other person or company shall be third party beneficiaries to the License Agreement.\n<br />\n14.5 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE.\n<br />\n14.6 The rights granted in the License Agreement may not be assigned or transferred by either you or Google without the prior written approval of the other party. Neither you nor Google shall be permitted to delegate their responsibilities or obligations under the License Agreement without the prior written approval of the other party.\n<br />\n14.7 The License Agreement, and your relationship with Google under the License Agreement, shall be governed by the laws of the State of California without regard to its conflict of laws provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located within the county of Santa Clara, California to resolve any legal matter arising from the License Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction.",
  "hash": "asdkl",
  "url": "https://developer.android.com/studio/terms.html",
  "name": "Android Software Development Kit License Agreement"
}
```

## Core-module

> The AboutLibraries Library is pushed to [Maven Central](https://search.maven.org/artifact/com.mikepenz/aboutlibraries-core).

```gradle
implementation "com.mikepenz:aboutlibraries-core:${latestAboutLibsRelease}"
```

(Advanced) Usage

## Access generated library details

To create a individual integration, access the generated library information programmatically through the core module.

```kotlin
val libs = Libs.Builder()
    .withJson(aboutLibsJson) // provide the metaData (alternative APIs available)
    .build()
val libraries = libs.libraries // retrieve all libraries defined in the metadata
val licenses = libs.licenses // retrieve all licenses defined in the metadata
for (lib in libraries) {
    Log.i("AboutLibraries", "${lib.name}")
}
```

## UI-module

```gradle
implementation "com.mikepenz:aboutlibraries-compose:${latestAboutLibsRelease}"

// Alternative Material3 based module
implementation "com.mikepenz:aboutlibraries-compose-m3:${latestAboutLibsRelease}"
```

### Usage

```kotlin
// android
LibrariesContainer(
    Modifier.fillMaxSize()
)

// compose-desktop
LibrariesContainer(useResource("aboutlibraries.json") {
    it.bufferedReader().readText()
}, Modifier.fillMaxSize())
```

Compose-jb

The core module and the compose module are Kotlin-Multiplatform projects.
Find a sample application as the `app-desktop` module. It showcases the usage to manually generate the dependency meta information and include as part of the SCM.

### Generate Dependency Information

```bash
./gradlew :app-desktop:exportLibraryDefinitions -PaboutLibraries.exportPath=src/main/resources/

# Filter exported definition by variant by passing `-PaboutLibraries.exportVariant==<VARIANT>`
./gradlew :app-wasm:exportLibraryDefinitions -PaboutLibraries.exportPath=src/main/resources/ -PaboutLibraries.exportVariant=wasmJs
./gradlew :app-wasm:exportLibraryDefinitions -PaboutLibraries.exportPath=src/main/resources/ -PaboutLibraries.exportVariant=jvm
```

### Run Demo app(s)

```
# JVM Desktop app
./gradlew :app-desktop:run

# WASM Web app
./gradlew :app-wasm:run
```

### Screenshot

![Compose-jb Screenshot](https://raw.githubusercontent.com/mikepenz/AboutLibraries/develop/DEV/screenshots/compose-jb.png)

## (Legacy) UI-module

```gradle
implementation "com.mikepenz:aboutlibraries:${latestAboutLibsRelease}"
```

Usage

### Usage

Use this library in a few different ways. Create a custom activity, including a custom style or just use its generated information. Or simply use the built-in Activity or Fragment and just pass the libs to include.

> **Note**: The new version requires the new Material3 theme as base.

#### Activity

```kotlin
LibsBuilder()
    .start(this) // start the activity
```

The activity uses a toolbar, which requires the appropriate theme. See [Style the AboutLibraries](#style-the-aboutlibraries-%EF%B8%8F) for more details

#### Fragment
```kotlin
val fragment = LibsBuilder()
    .supportFragment()
```

#### About this App UI
The `AboutLibraries` library also offers the ability to create an `About this app` screen.
Add the following .xml file (or just the strings - the key must be the same) to the project.

```xml
<resources>
    <string name="aboutLibraries_description_showIcon">true</string>
    <string name="aboutLibraries_description_showVersion">true</string>
    <string name="aboutLibraries_description_text">Place the description here :D</string>
</resources>
```
or use the builder and add following:
```kotlin
.withAboutIconShown(true)
.withAboutVersionShown(true)
.withAboutDescription("This is a small sample which can be set in the about my app description file.<br /><b>Style this with html markup :D</b>")
```

#### Style the AboutLibraries 🖌

Create a custom style for the AboutLibraries UI.

```xml
// define a custom style
<style name="CustomAboutLibrariesStyle" parent="">
    <!-- AboutLibraries specific values -->
    <item name="aboutLibrariesCardBackground">?cardBackgroundColor</item>
    <item name="aboutLibrariesDescriptionTitle">?android:textColorPrimary</item>
    <item name="aboutLibrariesDescriptionText">?android:textColorSecondary</item>
    <item name="aboutLibrariesDescriptionDivider">@color/opensource_divider</item>
    <item name="aboutLibrariesOpenSourceTitle">?android:textColorPrimary</item>
    <item name="aboutLibrariesOpenSourceText">?android:textColorSecondary</item>
    <item name="aboutLibrariesSpecialButtonText">?android:textColorPrimary</item>
    <item name="aboutLibrariesOpenSourceDivider">@color/opensource_divider</item>
</style>

// define the custom styles for the theme
<style name="SampleApp" parent="Theme.MaterialComponents.Light.NoActionBar">
    ...
    <item name="aboutLibrariesStyle">@style/CustomAboutLibrariesStyle</item>
    ...
</style>
```

## Enterprise

Since v10 of the AboutLibraries plugin it is possible to disable the automatic registration of the plugin task as part of the build system.
```
aboutLibraries {
    registerAndroidTasks = false
}
```

This is especially beneficial for enterprise environments where it is required to be in full control of the included `aboutlibraries.json`.
After disabling the integration it is possible to manually update the definitions, or do it on your CI environment.
```
./gradlew app:exportLibraryDefinitions -PaboutLibraries.exportPath=src/main/res/raw/ -PaboutLibraries.exportVariant=release
```
This generated file can be either included in your SCM, and every build will use this exact verified and approved state.
Additionally, this helps to ensure no issues occur during the apps delivery phase, as the respective file is already generated and included.

The library offers complete customisation for this behavior and location or name for the generated files can be adjusted as needed.
A full compose code example providing the `Libs` manually:

```kotlin
LibrariesContainer(
    librariesBlock = { ctx ->
        Libs.Builder().withJson(ctx, R.raw.aboutlibraries).build()
    }
)
```

## Gradle API

By default, the gradle plugin is automatically executed for Android projects, generating the library metadata where it's automatically discovered by the `ui` modules.
For other environments or for more advanced usages the plugin offers additional APIs.

```bash
# Manually generate the dependency metaData in the provided location. Allows to commit it in SCM
# Exports the metaData in `src/main/resources/` relative to the module root
./gradlew app-desktop:exportLibraryDefinitions -PaboutLibraries.exportPath=src/main/resources/
# Export only for a specific variant: `release`
./gradlew app-desktop:exportLibraryDefinitions -PaboutLibraries.exportPath=src/main/resources/ -PaboutLibraries.exportVariant=release

# Export dependencies to CLI in CSV format
./gradlew exportLibraries
./gradlew exportLibraries${Variant}

# Outputs all dependencies with name, version and their identifier
./gradlew findLibraries

# Exports all dependencies in a format helpful for compliance reports.
# By default writes `export.csv` and `export.txt` and `dependencies` folder in the root of the project.
./gradlew exportComplianceLibraries${Variant}

# List all funding options for included projects (as identified via the e.g.: GitHub API)
./gradlew fundLibraries
```

# Special repository support
| Host                          | License | Funding |
|-------------------------------|---------|---------|
| [GitHub](https://github.com/) | x       | x       |

# Disclaimer

This library uses all compile time dependencies (and their sub dependencies) as defined in the `build.gradle` file.
This could lead to dependencies which are only used during compilation (and not actually distributed in the app) to be listed or missing in the attribution screen.
It might also fail to identify licenses if the dependencies do not define it properly in their pom.xml file.

Careful optimisation and review of all licenses is recommended to really include all required dependencies. The use of the gradle commands like `findLibraries` can help doing this.

It is also important that native sub dependencies can *not* be resolved automatically as they are not included via gradle.
Additional dependencies can be provided via the plugins API to extend and provide any additional details.

# Developed By

- Mike Penz
  - [mikepenz.dev](https://mikepenz.dev) - [blog.mikepenz.dev](https://blog.mikepenz.dev) - <mikepenz@gmail.com>
  - [paypal.me/mikepenz](http://paypal.me/mikepenz)
  - [Automatic changelog generation action](https://github.com/marketplace/actions/release-changelog-builder)

# License

    Copyright 2024 Mike Penz

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.


# Dokka

[![Kotlin Beta](https://kotl.in/badges/beta.svg)](https://kotlinlang.org/docs/components-stability.html)
[![JetBrains official project](https://jb.gg/badges/official.svg)](https://github.com/JetBrains#jetbrains-on-github)
[![Maven Central](https://img.shields.io/maven-central/v/org.jetbrains.dokka/org.jetbrains.dokka.gradle.plugin?label=MavenCentral&logo=apache-maven)](https://search.maven.org/artifact/org.jetbrains.dokka/org.jetbrains.dokka.gradle.plugin)
[![Gradle Plugin](https://img.shields.io/gradle-plugin-portal/v/org.jetbrains.dokka?label=Gradle&logo=gradle)](https://plugins.gradle.org/plugin/org.jetbrains.dokka)
[![License](https://img.shields.io/github/license/Kotlin/dokka.svg)](LICENSE.txt)
[![Revved up by Develocity](https://img.shields.io/badge/Revved%20up%20by-Develocity-06A0CE?logo=Gradle&labelColor=02303A)](https://ge.jetbrains.com/scans?search.rootProjectNames=dokka)

Dokka is an API documentation engine for Kotlin.

Just like Kotlin itself, Dokka supports mixed-language projects. It understands Kotlin's
[KDoc comments](https://kotlinlang.org/docs/kotlin-doc.html#kdoc-syntax) and Java's
[Javadoc comments](https://www.oracle.com/technical-resources/articles/java/javadoc-tool.html).

Dokka can generate documentation in multiple formats, including its own modern [HTML format](#html),
multiple flavors of [Markdown](#markdown), and Java's [Javadoc HTML](#javadoc).

Some libraries that use Dokka for their API reference documentation:

* [kotlinx.coroutines](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/)
* [Bitmovin](https://cdn.bitmovin.com/player/android/3/docs/index.html)
* [Hexagon](https://hexagonkt.com/api/index.html)
* [Ktor](https://api.ktor.io/)
* [OkHttp](https://square.github.io/okhttp/5.x/okhttp/okhttp3/)
* [Gradle](https://docs.gradle.org/current/kotlin-dsl/index.html)

You can run Dokka using [Gradle](https://kotlinlang.org/docs/dokka-gradle.html),
[Maven](https://kotlinlang.org/docs/dokka-maven.html) or from the [command line](https://kotlinlang.org/docs/dokka-cli.html).
It is also [highly pluggable](https://kotlinlang.org/docs/dokka-plugins.html).

## Documentation

Comprehensive documentation for Dokka is available on [kotlinlang.org](https://kotlinlang.org/docs/dokka-introduction.html)

## Get started with Dokka

### Gradle

Kotlin DSL

Apply the Gradle plugin for Dokka in the root build script of your project:

```kotlin
plugins {
    id("org.jetbrains.dokka") version "1.9.20"
}
```

When documenting [multi-project](https://docs.gradle.org/current/userguide/multi_project_builds.html) builds, you need
to apply the Gradle plugin for Dokka within subprojects as well:

```kotlin
subprojects {
    apply(plugin = "org.jetbrains.dokka")
}
```

Groovy DSL

Apply Gradle plugin for Dokka in the root project:

```groovy
plugins {
    id 'org.jetbrains.dokka' version '1.9.20'
}
```

When documenting [multi-project](https://docs.gradle.org/current/userguide/multi_project_builds.html) builds, you need
to apply the Gradle plugin for Dokka within subprojects as well:

```groovy
subprojects {
    apply plugin: 'org.jetbrains.dokka'
}
```

To generate documentation, run the following Gradle tasks:

* `dokkaHtml` for single-project builds
* `dokkaHtmlMultiModule` for multi-project builds

By default, the output directory is set to `/build/dokka/html` and `/build/dokka/htmlMultiModule` respectively.

To learn more about the Gradle plugin for Dokka, see [documentation for Gradle](https://kotlinlang.org/docs/dokka-gradle.html).

### Maven

Add the Dokka Maven plugin to the `plugins` section of your POM file:

```xml
<build>
    <plugins>
        <plugin>
            <groupId>org.jetbrains.dokka</groupId>
            <artifactId>dokka-maven-plugin</artifactId>
            <version>1.9.20</version>
            <executions>
                <execution>
                    <phase>pre-site</phase>
                    <goals>
                        <goal>dokka</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
```

To generate documentation, run the `dokka:dokka` goal.

By default, the output directory is set to `target/dokka`.

To learn more about using Dokka with Maven, see [documentation for Maven](https://kotlinlang.org/docs/dokka-maven.html).

### CLI

It is possible to run Dokka from the command line without having to use any of the build tools, but it's more
difficult to set up and for that reason it is not covered in this section.

Please consult [documentation for the command line runner](https://kotlinlang.org/docs/dokka-cli.html)
to learn how to use it.

### Android

In addition to applying and configuring Dokka, you can apply Dokka's
[Android documentation plugin](plugins/android-documentation), which aims to improve documentation experience on the
Android platform:

Gradle Kotlin DSL

```kotlin
dependencies {
    dokkaPlugin("org.jetbrains.dokka:android-documentation-plugin:1.9.20")
}
```

Gradle Groovy DSL

```groovy
dependencies {
    dokkaPlugin 'org.jetbrains.dokka:android-documentation-plugin:1.9.20'
}
```

Maven

```xml
<plugin>
    <groupId>org.jetbrains.dokka</groupId>
    <artifactId>dokka-maven-plugin</artifactId>
    ...
    <configuration>
        <dokkaPlugins>
            <plugin>
                <groupId>org.jetbrains.dokka</groupId>
                <artifactId>android-documentation-plugin</artifactId>
                <version>1.9.20</version>
            </plugin>
        </dokkaPlugins>
    </configuration>
</plugin>
```

## Output formats

### HTML

HTML is Dokka's default and recommended output format. You can see an example of the output by browsing documentation
for [kotlinx.coroutines](https://kotlinlang.org/api/kotlinx.coroutines/).

HTML format is configurable and, among other things, allows you to modify stylesheets, add custom image assets, change
footer message and revamp the structure of the generated HTML pages through templates.

For more details and examples, see [documentation for HTML format](https://kotlinlang.org/docs/dokka-html.html).

### Markdown

Dokka is able to generate documentation in GitHub Flavored and Jekyll compatible Markdown. However, both of these
formats are still in Alpha, so you might encounter bugs and migration issues.

For more details and examples, see [documentation for Markdown formats](https://kotlinlang.org/docs/dokka-markdown.html).

### Javadoc

Dokka's Javadoc output format is a lookalike of Java's
[Javadoc HTML format](https://docs.oracle.com/en/java/javase/19/docs/api/index.html). This format is still in Alpha,
so you might encounter bugs and migration issues.

Javadoc format tries to visually mimic HTML pages generated by the Javadoc tool, but it's not a direct implementation
or an exact copy. In addition, all Kotlin signatures are translated to Java signatures.

For more details and examples, see [documentation for Javadoc format](https://kotlinlang.org/docs/dokka-javadoc.html).

## Dokka plugins

Dokka was built from the ground up to be easily extensible and highly customizable, which allows the community to
implement plugins for missing or very specific features that are not provided out of the box.

Learn more about Dokka plugins and their configuration in [Dokka plugins](https://kotlinlang.org/docs/dokka-plugins.html).

If you want to learn how to develop Dokka plugins, see
[Developer guides](https://kotlin.github.io/dokka/1.9.20/developer_guide/introduction/).

## Community

Dokka has a dedicated `#dokka` channel in [Kotlin Community Slack](https://surveys.jetbrains.com/s3/kotlin-slack-sign-up)
where you can chat about Dokka, its plugins and how to develop them, as well as get in touch with maintainers.

## Building and Contributing

See [Contributing Guidelines](CONTRIBUTING.md)


# Chucker
[![Maven Central](https://img.shields.io/maven-central/v/com.github.chuckerteam.chucker/library)](https://search.maven.org/artifact/com.github.chuckerteam.chucker/library) ![Pre Merge Checks](https://github.com/ChuckerTeam/chucker/workflows/Pre%20Merge%20Checks/badge.svg?branch=develop)  ![License](https://img.shields.io/github/license/ChuckerTeam/Chucker.svg) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-orange.svg)](http://makeapullrequest.com) [![Join the chat at https://kotlinlang.slack.com](https://img.shields.io/badge/slack-@kotlinlang/chucker-yellow.svg?logo=slack)](https://kotlinlang.slack.com/archives/CRWD6370R) [![Android Weekly](https://img.shields.io/badge/Android%20Weekly-%23375-blue.svg)](https://androidweekly.net/issues/issue-375)

_A fork of [Chuck](https://github.com/jgilfelt/chuck)_

- [Chucker](#chucker)
  - [Getting Started 👣](#getting-started-)
  - [Features 🧰](#features-)
    - [Multi-Window 🚪](#multi-window-)
  - [Configure 🎨](#configure-)
    - [Redact-Header 👮♂](#redact-header-)
    - [Decode-Body 📖](#decode-body-)
    - [Notification Permission 🔔](#notification-permission-)
  - [Migrating 🚗](#migrating-)
  - [Snapshots 📦](#snapshots-)
  - [FAQ ❓](#faq-)
- [Sponsors 💸](#sponsors-)
  - [Contributing 🤝](#contributing-)
    - [Building 🛠](#building-)
  - [Acknowledgments 🌸](#acknowledgments-)
    - [Maintainers](#maintainers)
    - [Thanks](#thanks)
    - [Libraries](#libraries)
  - [License 📄](#license-)

Chucker simplifies the inspection of **HTTP(S) requests/responses** fired by your Android App. Chucker works as an **OkHttp Interceptor** persisting all those events inside your application, and providing a UI for inspecting and sharing their content.

Apps using Chucker will display a **notification** showing a summary of ongoing HTTP activity. Tapping on the notification launches the full Chucker UI. Apps can optionally suppress the notification, and launch the Chucker UI directly from within their own interface.

## Getting Started 👣

Chucker is distributed through [Maven Central](https://search.maven.org/artifact/com.github.chuckerteam.chucker/library). To use it you need to add the following **Gradle dependency** to the `build.gradle` file of your android app module (NOT the root file).

Please note that you should add both the `library` and the `library-no-op` variant to isolate Chucker from release builds as follows:

```groovy
dependencies {
  debugImplementation "com.github.chuckerteam.chucker:library:4.0.0"
  releaseImplementation "com.github.chuckerteam.chucker:library-no-op:4.0.0"
}
```

To start using Chucker, just plug in a new `ChuckerInterceptor` to your OkHttp Client Builder:

```kotlin
val client = OkHttpClient.Builder()
                .addInterceptor(ChuckerInterceptor(context))
                .build()
```

**That's it!** 🎉 Chucker will now record all HTTP interactions made by your OkHttp client.

Historically, Chucker was distributed through JitPack.
You can find older version of Chucker here: [![JitPack](https://jitpack.io/v/ChuckerTeam/chucker.svg)](https://jitpack.io/#ChuckerTeam/chucker).

## Features 🧰

Don't forget to check the [changelog](CHANGELOG.md) to have a look at all the changes in the latest version of Chucker.

* Compatible with **OkHTTP 4**
* **API >= 21** compatible
* Easy to integrate (just 2 gradle `implementation` lines).
* Works **out of the box**, no customization needed.
* **Empty release artifact** 🧼 (no traces of Chucker in your final APK).
* Support for body text search with **highlighting** 🕵♂
* Support for showing **images** in HTTP Responses 🖼
* Support for custom decoding of HTTP bodies

### Multi-Window 🚪

The main Chucker activity is launched in its own task, allowing it to be displayed alongside the host app UI using Android 7.x multi-window support.

![Multi-Window](assets/chucker-multiwindow.gif)

## Configure 🎨

You can customize chucker providing an instance of a `ChuckerCollector`:

```kotlin
// Create the Collector
val chuckerCollector = ChuckerCollector(
        context = this,
        // Toggles visibility of the notification
        showNotification = true,
        // Allows to customize the retention period of collected data
        retentionPeriod = RetentionManager.Period.ONE_HOUR
)

// Create the Interceptor
val chuckerInterceptor = ChuckerInterceptor.Builder(context)
        // The previously created Collector
        .collector(chuckerCollector)
        // The max body content length in bytes, after this responses will be truncated.
        .maxContentLength(250_000L)
        // List of headers to replace with ** in the Chucker UI
        .redactHeaders("Auth-Token", "Bearer")
        // Read the whole response body even when the client does not consume the response completely.
        // This is useful in case of parsing errors or when the response body
        // is closed before being read like in Retrofit with Void and Unit types.
        .alwaysReadResponseBody(true)
        // Use decoder when processing request and response bodies. When multiple decoders are installed they
        // are applied in an order they were added.
        .addBodyDecoder(decoder)
        // Controls Android shortcut creation.
        .createShortcut(true)
        .build()

// Don't forget to plug the ChuckerInterceptor inside the OkHttpClient
val client = OkHttpClient.Builder()
        .addInterceptor(chuckerInterceptor)
        .build()
```

### Redact-Header 👮♂

**Warning** The data generated and stored when using Chucker may contain sensitive information such as Authorization or Cookie headers, and the contents of request and response bodies.

It is intended for **use during development**, and not in release builds or other production deployments.

You can redact headers that contain sensitive information by calling `redactHeader(String)` on the `ChuckerInterceptor`.

```kotlin
interceptor.redactHeader("Auth-Token", "User-Session");
```

### Decode-Body 📖

Chucker by default handles only plain text, Gzip compressed or Brotli compressed. If you use a binary format like, for example, Protobuf or Thrift it won't be automatically handled by Chucker. You can, however, install a custom decoder that is capable of reading data from different encodings.

```kotlin
object ProtoDecoder : BodyDecoder {
    fun decodeRequest(request: Request, body: ByteString): String? = if (request.isExpectedProtoRequest) {
        decodeProtoBody(body)
    } else {
        null
    }

    fun decodeResponse(request: Response, body: ByteString): String? = if (request.isExpectedProtoResponse) {
        decodeProtoBody(body)
    } else {
        null
    }
}
interceptorBuilder.addBodyDecoder(ProtoDecoder).build()
```

### Notification Permission 🔔

Starting with Android 13, your apps needs to request the `android.permission.POST_NOTIFICATIONS` permission to the user in order to show notifications.
As Chucker also shows notifications to show network activity you need to handle permission request depending on your app features.
Without this permission Chucker will track network activity, but there will be no notifications on devices with Android 13 and newer.

There are 2 possible cases:
1. If your app is already sending notifications, you don't need to do anything as Chucker will
show a notification as soon as the `android.permission.POST_NOTIFICATIONS` permission is granted to your app.
1. If your app does not send notifications you would need to open Chucker directly (can be done via shortcut, which is added to your app by default when Chucker is added)
and click `Allow` in the dialog with permission request. In case you don't allow this permission or dismiss that dialog by mistake, on every Chucker launch there will be
a snackbar with a button to open your app settings where you can change permissions settings. Note, you need to grant `android.permission.POST_NOTIFICATIONS` to your app in Settings as there
will be no separate app in Apps list in Settings.

## Migrating 🚗

If you're migrating **from [Chuck](https://github.com/jgilfelt/chuck) to Chucker**, please refer to this [migration guide](/docs/migrating-from-chuck.md).

If you're migrating **from Chucker v2.0 to v3.0**, please expect multiple breaking changes. You can find documentation on how to update your code on this other [migration guide](/docs/migrating-from-2.0.md).

## Snapshots 📦

Development of Chucker happens in the [`main`](https://github.com/ChuckerTeam/chucker/tree/main) branch. Every push to `main` will trigger a publishing of a `SNAPSHOT` artifact for the upcoming version. You can get those snapshots artifacts directly from Sonatype with:

```gradle
repositories {
    maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
}
dependencies {
  debugImplementation "com.github.chuckerteam.chucker:library:4.1.0-SNAPSHOT"
  releaseImplementation "com.github.chuckerteam.chucker:library-no-op:4.1.0-SNAPSHOT"
}
```

Moreover, you can still use [JitPack](https://jitpack.io/#ChuckerTeam/chucker) as it builds every branch. So the top of `main` is available here:

```gradle
repositories {
    maven { url "https://jitpack.io" }
}
dependencies {
  debugImplementation "com.github.chuckerteam.chucker:library:main-SNAPSHOT"
  releaseImplementation "com.github.chuckerteam.chucker:library-no-op:main-SNAPSHOT"
}
```

⚠ Please note that the latest snapshot might be **unstable**. Use it at your own risk ⚠

If you're looking for the **latest stable version**, you can always find it in `Releases` section.

## FAQ ❓

* Why are some of my request headers (e.g. `Content-Encoding` or `Accept-Encoding`) missing?
* Why are retries and redirects not being captured discretely?
* Why are my encoded request/response bodies not appearing as plain text?

Please refer to [this section of the OkHttp documentation](https://square.github.io/okhttp/interceptors/). You can choose to use Chucker as either an application or network interceptor, depending on your requirements.

* Why Android < 21 is no longer supported?

In order to keep up with the changes in OkHttp we decided to bump its version in `4.x` release. Chucker `3.5.x` supports Android 16+ but its active development stopped and only bug fixes and minor improvements will land on [3.x branch](https://github.com/ChuckerTeam/chucker/tree/3.x) till March 2021.

# Sponsors 💸

Chucker is maintained and improved during nights, weekends and whenever team has free time. If you use Chucker in your project, please consider sponsoring us. This will help us buy a domain for a website we will have soon and also spend some money on charity. Additionally, sponsorship will also help us understand better how valuable Chucker is for people's everyday work.

You can sponsor us by clicking `Sponsor` button.

## Contributing 🤝

We're offering support for Chucker on the [#chucker](https://kotlinlang.slack.com/archives/CRWD6370R) channel on [kotlinlang.slack.com](https://kotlinlang.slack.com/). Come and join the conversation over there.

**We're looking for contributors! Don't be shy.** 😁 Feel free to open issues/pull requests to help us improve this project.

* When reporting a new Issue, make sure to attach **Screenshots**, **Videos** or **GIFs** of the problem you are reporting.
* When submitting a new PR, make sure tests are all green. Write new tests if necessary.

Short `TODO` List for new contributors:

- Increment the test coverage.
- [Issues marked as `Help wanted`](https://github.com/ChuckerTeam/chucker/labels/help%20wanted)

### Building 🛠

In order to start working on Chucker, you need to fork the project and open it in Android Studio/IntelliJ IDEA.

Before committing we suggest you install the pre-commit hooks with the following command:

```
./gradlew installGitHook
```

This will make sure your code is validated against KtLint and Detekt before every commit.
The command will run automatically before the `clean` task, so you should have the pre-commit hook installed by then.

Before submitting a PR please run:

```
./gradlew build
```

This will build the library and will run all the verification tasks (ktlint, detekt, lint, unit tests) locally.
This will make sure your CI checks will pass.

## Acknowledgments 🌸

### Maintainers

Chucker is currently developed and maintained by the [ChuckerTeam](https://github.com/ChuckerTeam). When submitting a new PR, please ping one of:

- [@cortinico](https://github.com/cortinico)
- [@olivierperez](https://github.com/olivierperez)
- [@vbuberen](https://github.com/vbuberen)

### Thanks

Big thanks to our contributors ❤

### Libraries

Chucker uses the following open source libraries:

- [OkHttp](https://github.com/square/okhttp) - Copyright Square, Inc.
- [Gson](https://github.com/google/gson) - Copyright Google Inc.
- [Room](https://developer.android.com/topic/libraries/architecture/room) - Copyright Google Inc.

## License 📄

```
    Copyright (C) 2018-2021 Chucker Team.
    Copyright (C) 2017 Jeff Gilfelt.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
```


# :iphone: Home Assistant Companion for Android  ![Beta Deploy](https://github.com/home-assistant/android/workflows/Beta%20Deploy/badge.svg)

## Documentation
If you are looking for documentation around the companion applications check out the [Home Assistant Companion Documentation](https://companion.home-assistant.io/).  This will provide you instructions on using the applications.

## Setup App Development Environment

1. Download and install [Android Studio](https://developer.android.com/studio)

2. Download / clone this repository to a folder on your computer

3. Create a Firebase project at [Firebase Console](https://console.firebase.google.com)

4. Create four Android apps, with following package names
 - `io.homeassistant.companion.android`
 - `io.homeassistant.companion.android.debug`
 - `io.homeassistant.companion.android.minimal`
 - `io.homeassistant.companion.android.minimal.debug`

5. Now download the `google-services.json` file and put it in the project's _/app_, _/automotive_ and _/wear_ folders. This file contains the configuration of the whole project (all four applications). ([You can also use the mock services file instead of generating your own](/.github/mock-google-services.json). The file should contain client IDs for all packages listed above for debugging to work properly.  **If you do not generate your own file FCM push notification will never work, only websocket notifications will**)
6. Start Android Studio, open your source code folder and check if the Gradle build will be successful using Build/Make Module "App". You might have to install the right Android SDK via Tools/SDK Manager first.
7. Run `gradlew assembleDebug` to build all debug versions, this might take a while.
8. If the build is successful, you can run the app by doing the following: click **Run** -> **Run 'app'**.
9. Connect your phone or create a new virtual device following on screen instruction
10. :tada:

If you get stuck while setting up your own environment, you can ask questions in the **#devs_mobile_apps** channel on [Discord](https://discord.gg/c5DvZ4e).

### Push Notifications

If you want to work on push notifications or use a development build with push notifications, please go the server side code [HERE](https://github.com/home-assistant/mobile-apps-fcm-push) and deploy it to your firebase project. Once you have your androidV1 URL to the deployed service, set it in to your `${GRADLE_USER_HOME}/gradle.properties` file, e.g.:
```properties
homeAssistantAndroidPushUrl=https://mydomain.cloudfunctions.net/androidV1
```

You can also define the rate limit function URL, e.g.:
```properties
homeAssistantAndroidRateLimitUrl=https://mydomain.cloudfunctions.net/checkRateLimits
```

## App Flavors

The Android app has both a full flavor that uses Google Play Services to offer features like location tracking and notifications. There is also a minimal flavor that does not require Google Play Services and can be found in the releases section. The minimal flavor does not have location tracking or notifications.

## Building for publishing

To build the app for publishing, you will need to sign the app. To do this, do the following:
1. Create keystore containing keypair for debug application signing. In Android Studio: Menu/Build/Generate signed APK, then use a button to create new keystore. Remember the passwords and key alias. Default, the keystore must be named `release_keystore.keystore` and should be placed in the _home-assistant-Android/app_ and _home-assistant-Android/wear_ folder.
2. Set environmental variables used in `app/build.gradle.kts`:
 - `KEYSTORE_PASSWORD`
 - `KEYSTORE_ALIAS`
 - `KEYSTORE_ALIAS_PASSWORD`
 - `KEYSTORE_PATH` (if your keystore is located differently than stated above)
3. Run `gradlew build`
4. The signed APK is located in your build folder

## Testing Dev Releases

We are using [Github Actions](https://github.com/home-assistant/android/actions) to perform continuous integration both by unit testing, deploying dev releases to [Play Store Beta](https://play.google.com/apps/testing/io.homeassistant.companion.android) and final releases to the [Play Store](https://play.google.com/store/apps/details?id=io.homeassistant.companion.android) when we release. To help test out a specific feature/fixes users can find the APK on the Actions page for each pull request, this debug APK can be installed side-by-side the production or beta builds.

## Quality

We are using [ktlint](https://ktlint.github.io/) as our linter.
You can run a check locally on your machine with:
```bash
./gradlew ktlintCheck
```
This commands runs on our CI to check if your PR passes all tests. So we strongly recommend running it before committing.

To run a check with an auto-format:
```bash
./gradlew ktlintFormat
```

## Translating
The project currently uses [lokalise](https://lokalise.com/public/145814835dd655bc5ab0d0.36753359/) to translate the application.  If you are interested in helping translate go to the link and click start translating!

## Generating a release to production
* Go to the latest Pre-release and edit it
* Uncheck the Pre-release box, check the Latest release box, and click Update release
  * This should cause the `Play Publish Production` Workflow to execute and should handle the rest for Google Play
  * Some platforms, such as the Amazon App Store, need to be updated manually
  * F-Droid uses the `version_code.txt` file of the latest release to detect a new production release and build it themselves, this may take some time


#

[![Maven Central](https://img.shields.io/maven-central/v/com.badoo.reaktive/reaktive?color=blue)](https://search.maven.org/artifact/com.badoo.reaktive/reaktive)
[![Build Status](https://github.com/badoo/Reaktive/workflows/Build/badge.svg?branch=master)](https://github.com/badoo/Reaktive/actions)
[![License](https://img.shields.io/badge/License-Apache/2.0-blue.svg)](https://github.com/badoo/Reaktive/blob/master/LICENSE)
[![kotlinlang|reaktive](https://img.shields.io/badge/kotlinlang-reaktive-blue?logo=slack)](https://kotlinlang.slack.com/archives/CU05HB31A)

Kotlin multiplatform implementation of Reactive Extensions.

Should you have any questions or feedback welcome to the **Kotlin Slack channel**:
[#reaktive](https://kotlinlang.slack.com/archives/CU05HB31A)

## Setup

There are a number of modules published to Maven Central:

- `reaktive` - the main Reaktive library (multiplatform)
- `reaktive-annotations` - collection of annotations (mutiplatform)
- `reaktive-testing` - testing utilities (multiplatform)
- `utils` - some utilities like `Clock`, `AtomicReference`, `Lock`, etc. (multiplatform)
- `coroutines-interop` - Kotlin coroutines interoperability helpers (multiplatform)
- `rxjava2-interop` - RxJava v2 interoperability helpers (JVM and Android)
- `rxjava3-interop` - RxJava v3 interoperability helpers (JVM and Android)

### Configuring dependencies

```groovy
kotlin {
    sourceSets {
        commonMain {
            dependencies {
                implementation 'com.badoo.reaktive:reaktive:<version>'
                implementation 'com.badoo.reaktive:reaktive-annotations:<version>'
                implementation 'com.badoo.reaktive:coroutines-interop:<version>' // For interop with coroutines
                implementation 'com.badoo.reaktive:rxjava2-interop:<version>' // For interop with RxJava v2
                implementation 'com.badoo.reaktive:rxjava3-interop:<version>' // For interop with RxJava v3
            }
        }

        commonTest {
            dependencies {
                implementation 'com.badoo.reaktive:reaktive-testing:<version>'
            }
        }
    }
}
```

## Features:

* Multiplatform: JVM, Android, iOS, macOS, watchOS, tvOS, JavaScript, Linux X64
* Schedulers support:
  * `computationScheduler` - fixed thread pool equal to a number of cores
  * `ioScheduler` - unbound thread pool with caching policy
  * `newThreadScheduler` - creates a new thread for each unit of work
  * `singleScheduler` - executes tasks on a single shared background thread
  * `trampolineScheduler` - queues tasks and executes them on one of the participating threads
  * `mainScheduler` - executes tasks on main thread
* True multithreading for Kotlin/Native (since v2.0 only the [new memory model](https://kotlinlang.org/docs/native-memory-manager.html) is supported)
* Supported sources: `Observable`, `Maybe`, `Single`, `Completable`
* Subjects: `PublishSubject`, `BehaviorSubject`, `ReplaySubject`, `UnicastSubject`
* Interoperability with Kotlin Coroutines
  * Convert `suspend` functions to/from `Single`, `Maybe` and `Completable`
  * Convert `Flow` to/from `Observable`
  * Convert `CoroutineContext` to `Scheduler`
  * Convert `Scheduler` to `CoroutineDispatcher`
* Interoperability with RxJava2 and RxJava3
  * Conversion of sources and schedulers between Reaktive and RxJava

## Reaktive and Kotlin/Native

Since version 2.x, Reaktive only works with the [new memory model](https://kotlinlang.org/docs/native-memory-manager.html).

    Reaktive 1.x and the old (strict) memory model

The old (strict) Kotlin Native memory model and concurrency are very special. In general shared mutable state between threads is not allowed.
Since Reaktive supports multithreading in Kotlin Native, please read the following documents before using it:

* [Concurrency](https://kotlinlang.org/docs/reference/native/concurrency.html#object-transfer-and-freezing)
* [Immutability](https://kotlinlang.org/docs/reference/native/immutability.html)

Object detachment is relatively difficult to achieve and is very error-prone when the objects are created from outside and
are not fully managed by the library. This is why Reaktive prefers frozen state. Here are some hints:

* Any callback (and any captured objects) submitted to a Scheduler will be frozen
* `subscribeOn` freezes both its upstream source and downstream observer,
all the Disposables (upstream's and downstream's) are frozen as well,
all the values (including errors) are **not** frozen by the operator
* `observeOn` freezes only its downstream observer and all the values (including errors) passed through it, plus all the Disposables,
upstream source is **not** frozen by the operator
* Other operators that use scheduler (like `debounce`, `timer`, `delay`, etc.) behave same as `observeOn` in most of the cases

#### Thread local tricks to avoid freezing

Sometimes freezing is not acceptable, e.g. we might want to load some data in background and then update the UI.
Obviously UI can not be frozen. With Reaktive it is possible to achieve such a behaviour in two ways:

Use `threadLocal` operator:

```kotlin
val values = mutableListOf<Any>()
var isFinished = false

observable<Any> { emitter ->
    // Background job
}
    .subscribeOn(ioScheduler)
    .observeOn(mainScheduler)
    .threadLocal()
    .doOnBeforeNext { values += it } // Callback is not frozen, we can update the mutable list
    .doOnBeforeFinally { isFinished = true } // Callback is not frozen, we can change the flag
    .subscribe()
```

Set `isThreadLocal` flag to `true` in `subscribe` operator:

```kotlin
val values = mutableListOf<Any>()
var isComplete = false

observable<Any> { emitter ->
    // Background job
}
    .subscribeOn(ioScheduler)
    .observeOn(mainScheduler)
    .subscribe(
        isThreadLocal = true,
        onNext = { values += it }, // Callback is not frozen, we can update the mutable list
        onComplete = { isComplete = true } // Callback is not frozen, we can change the flag
    )
```

In both cases subscription (`subscribe` call) **must** be performed on the Main thread.

## Coroutines interop

This functionality is provided by the `coroutines-interop` module. Please mind some [known problems](https://github.com/Kotlin/kotlinx.coroutines/blob/native-mt/kotlin-native-sharing.md#known-problems) with multi-threaded coroutines on Kotlin/Native.

### Examples

```kotlin
val flow: Flow<Int> = observableOf(1, 2, 3).asFlow()
val observable: Observable<Int> = flowOf(1, 2, 3).asObservable()
```

```kotlin
fun doSomething() {
    singleFromCoroutine { getSomething() }
        .subscribe { println(it) }
}

suspend fun getSomething(): String {
    delay(1.seconds)
    return "something"
}
```

```kotlin
val defaultScheduler = Dispatchers.Default.asScheduler()
val computationDispatcher = computationScheduler.asCoroutineDispatcher()
```

## Subscription management with DisposableScope

Reaktive provides an easy way to manage subscriptions: [DisposableScope](https://github.com/badoo/Reaktive/blob/master/reaktive/src/commonMain/kotlin/com/badoo/reaktive/disposable/scope/DisposableScope.kt).

Take a look at the following examples:

```kotlin
val scope =
    disposableScope {
        observable.subscribeScoped(...) // Subscription will be disposed when the scope is disposed

        doOnDispose {
            // Will be called when the scope is disposed
        }

        someDisposable.scope() // `someDisposable` will be disposed when the scope is disposed
    }

// At some point later
scope.dispose()
```

```kotlin
class MyPresenter(
    private val view: MyView,
    private val longRunningAction: Completable
) : DisposableScope by DisposableScope() {

    init {
        doOnDispose {
            // Will be called when the presenter is disposed
        }
    }

    fun load() {
        view.showProgressBar()

        // Subscription will be disposed when the presenter is disposed
        longRunningAction.subscribeScoped(onComplete = view::hideProgressBar)
    }
}

class MyActivity : AppCompatActivity(), DisposableScope by DisposableScope() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        MyPresenter(...).scope()
    }

    override fun onDestroy() {
        dispose()

        super.onDestroy()
    }
}
```

## Reaktive and Swift interoperability

Please see the corresponding documentation page: [Reaktive and Swift interoperability](docs/SwiftInterop.md).

## Plugins

Reaktive provides Plugin API, something similar to [RxJava plugins](https://github.com/ReactiveX/RxJava/wiki/Plugins). The Plugin API provides a way to decorate Reaktive sources. A plugin should implement the [ReaktivePlugin](https://github.com/badoo/Reaktive/blob/master/reaktive/src/commonMain/kotlin/com/badoo/reaktive/plugin/ReaktivePlugin.kt) interface, and can be registered using the `registerReaktivePlugin` function and unregistered using the `unregisterReaktivePlugin` function.

```kotlin
object MyPlugin : ReaktivePlugin {
    override fun <T> onAssembleObservable(observable: Observable<T>): Observable<T> =
        object : Observable<T> {
            private val traceException = TraceException()

            override fun subscribe(observer: ObservableObserver<T>) {
                observable.subscribe(
                    object : ObservableObserver<T> by observer {
                        override fun onError(error: Throwable) {
                            observer.onError(error, traceException)
                        }
                    }
                )
            }
        }

    override fun <T> onAssembleSingle(single: Single<T>): Single<T> =
        TODO("Similar to onAssembleSingle")

    override fun <T> onAssembleMaybe(maybe: Maybe<T>): Maybe<T> =
        TODO("Similar to onAssembleSingle")

    override fun onAssembleCompletable(completable: Completable): Completable =
        TODO("Similar to onAssembleSingle")

    private fun ErrorCallback.onError(error: Throwable, traceException: TraceException) {
        if (error.suppressedExceptions.lastOrNull() !is TraceException) {
            error.addSuppressed(traceException)
        }
        onError(error)
    }

    private class TraceException : Exception()
}
```

## Samples:

* [MPP module](https://github.com/badoo/Reaktive/tree/master/sample-mpp-module)
* [Android app](https://github.com/badoo/Reaktive/tree/master/sample-android-app)
* [iOS app](https://github.com/badoo/Reaktive/tree/master/sample-ios-app)
* [JavaScript browser app](https://github.com/badoo/Reaktive/tree/master/sample-js-browser-app)
* [Linux x64 app](https://github.com/badoo/Reaktive/tree/master/sample-linuxx64-app)