Feature toggle library for Android

Overview

FeatureToggle

Feature toggle library for Android.

Overview

FeatureToggle library allows to configure features of Android application in runtime using feature flags. Common usecases:

  • Trunk-Based Developement when developers can release application with not production ready code in main branch and hide this code behind a feature flag.
  • Safe release with new implementation of critical part of application. If critical problem found in new implementation, developers can switch to old implementation using feature flag.
  • A/B testing when feature flags used to switch between multiple feature implementations.

When using FeatureToggle library each dynamic feature in Android application must been represent as separate class or interface with multiple implementations. Each dynamic feature has Feature Flag with unique key and FeatureFactory.

Feature Flag is Kotlin class that contains one or more fields that describe feature config.

Feature Flags can be loaded from multiple FeatureFlagDataSources. FeatureFlagDataSource have priority, that used to decide from which FeatureFlagDataSource apply specific Feature Flag. Feature Flags stored in Json and in runtime represented as Koltin objects.

FeatureFactory is responsible to create feature object using provided Feature Flag object to make a decision how to create feature object.

FeatureToggle library automatically generates registries of current application feature flags and factories using annotation processors.

Quick Start

  1. Add feature manager and compiler:
implementation("com.qiwi.featuretoggle:featuretoggle-feature-manager:0.1.0")
kapt("com.qiwi.featuretoggle:featuretoggle-compiler:0.1.0")
  1. Add converter that will be used to convert feature flags from Json into Kotlin objects. Two converters are available: Jackson and Gson:
implementation("com.qiwi.featuretoggle:featuretoggle-converter-jackson:0.1.0")
//or
implementation("com.qiwi.featuretoggle:featuretoggle-converter-gson:0.1.0")
  1. For each feature add feature flag with unique key and factory:
class SampleFeature {
    //code
}

@FeatureFlag("feature_key")
class SampleFeatureFlag(
    //fields
)

@Factory
class SampleFeatureFeatureFactory : FeatureFactory<SampleFeature, SampleFeatureFlag>() {

    override fun createFeature(flag: SampleFeatureFlag): SampleFeature {
        //construct feature using flag
    }

    override fun createDefault(): AndroidInfoFeature {
        //construct default feature implementation
    }
}
  1. Create instance of FeatureManager using FeatureManager.Builder. Provide converter, necessary data sources and generated registries. Also it is recommended to fetch feature flags immediately after creation instance of FeatureManager:
val featureManager = FeatureManager.Builder(context)
    .converter(JacksonFeatureFlagConverter()) //or GsonFeatureFlagConverter()
    .logger(DebugLogger()) //optional logger
    .addDataSource(AssetsDataSource("feature_flags.json", context)) //also available additional data sources: FirebaseDataSource, AgConnectDataSource, RemoteDataSource
    .flagRegistry(FeatureFlagRegistryGenerated()) //set generated flag registry
    .factoryRegistry(FeatureFactoryRegistryGenerated()) //set generated factory registry
    .build()

featureManager.fetchFlags()
  1. Provide instance of FeatureManager using your favourite DI framework or use FeatureToggle singleton:
implementation("com.qiwi.featuretoggle:featuretoggle-feature-manager-singleton:0.1.0")
FeatureToggle.setFeatureManager(...)

FeatureToggle.featureManager().getFeature(...)
  1. Get feature from FeatureManager:
val feature = featureManager.getFeature<SampleFeature>()

It is recommended to wait with timeout for feature flags loading for example on splash screen:

class SplashScreenActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
        lifecycleScope.launchWhenCreated {
            runCatching {
                withTimeout(TIMEOUT_MILLIS) {
                    FeatureToggle.featureManager().awaitFullLoading()
                }
            }
            openMainActivity()
        }
    }

    ...
}

Assets DataSource

AssetsDataSource loads feature flags from Json file in assets folder. It is used to include default feature flag values into apk or app bundle. Default AssetsDataSource priority is 1.

Cache

Feature flags that loaded from remote data sources will be cached and used on next fetch. You can set priority of cached feature flags in FeatureManager.Builder:

FeatureManager.Builder(context)
    ...
    .cachedFlagsPriority(2)

Default cached flags priority is 2.

Remote Config DataSource

FeatureToggle supports Firebase Remote Config and AppGallery Connect Remote Configuration.

For each feature flag add remote config value with its feature flag key. Remote config value must be stored as Json string. Sample:

{
    "versionName": "12",
    "apiLevel": 31
}

Default remote config data sources priority is 4.

Usage with FirebaseDataSource:

  1. If you haven't already, add Firebase to your Android project.
  2. If you need to use Google Analytics with Remote Config, add analytics dependency:
implementation("com.google.firebase:firebase-analytics:${version}")
  1. Add FirebaseDataSource:
implementation("com.qiwi.featuretoggle:featuretoggle-datasource-firebase:0.1.0")
FeatureManager.Builder(context)
    ...
    .addDataSource(FirebaseDataSource())
  1. Add feature flags in Engage > Remote Config section in the Firebase console. Sample:

For more details about Firebase Remote Config see official docs.

Usage with AgConnectDataSource:

  1. If you haven't already, integrate the AppGallery Connect SDK.
  2. If you need to use HUAWEI Analytics with remote configuration, add analytics dependency:
implementation("com.huawei.hms:hianalytics:${version}")
  1. Add AgConnectDataSource:
implementation("com.qiwi.featuretoggle:featuretoggle-datasource-agconnect:0.1.0")
FeatureManager.Builder(context)
    ...
    .addDataSource(AgConnectDataSource())
  1. Add feature flags in Grow > Remote Configuration section in AppGallery Connect. Sample:

For more details about AppGallery Connect Remote Configuration see official docs.

Remote DataSource

FeatureToggle also have RemoteDataSource that can load feature flags from Json REST API using OkHttp library. Response Json must be in the following format:

[
    {
      "feature": "android_info",
      "versionName": "12",
      "apiLevel": 31
    }
]

Usage:

implementation("com.qiwi.featuretoggle:featuretoggle-datasource-remote:0.1.0")
FeatureManager.Builder(context)
    ...
    .addDataSource(RemoteDataSource("url"))

Default RemoteDataSource priority is 3.

Debug DataSource

If there is need to update feature flags manually (for debug purposes), use DebugDataSource:

implementation("com.qiwi.featuretoggle:featuretoggle-datasource-debug:0.1.0")
val debugDataSource = DebugDataSource()

FeatureManager.Builder(context)
    ...
    .addDataSource(debugDataSource)

...

debugDataSource.updateFeatureFlagsFromJsonString(...)

Default DebugDataSource priority is 100.

Custom DataSource

It is possible to extend FeatureToggle with custom data source:

class CustomDataSource : FeatureFlagDataSource {

    override val sourceType: FeatureFlagsSourceType ...

    override val key: String ...

    override val priority: Int ...

    override fun getFlags(
        registry: FeatureFlagRegistry,
        converter: FeatureFlagConverter,
        logger: Logger
    ): Flow<Map<String, Any>> = flow {
        ...
    }

}

Testing

If you need to use FeatureManager in unit tests, use FakeFeatureManager. It does not load flags from data sources. Instead, it uses mocked feature flags. Usage:

testImplementation("com.qiwi.featuretoggle:featuretoggle-feature-manager-test:0.1.0")
val fakeFeatureManager = FakeFeatureManager.create(FeatureFlagRegistryGenerated(), FeatureFactoryRegistryGenerated())

...

fakeFeatureManager.overrideFlag(...)

R8/Proguard

FeatureToggle modules have bundled proguard rules for its classes. However, for each feature flag class you need to add proguard rule:

-keep class com.example.SampleFeatureFlag { *; }

License

MIT License

Copyright (c) 2021 QIWI

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
You might also like...
Show worldwide headline. API/Glide library/recycler view/volley library/kotlin/xml/ chrome custom tabs
Show worldwide headline. API/Glide library/recycler view/volley library/kotlin/xml/ chrome custom tabs

Show worldwide headline. API/Glide library/recycler view/volley library/kotlin/xml/ chrome custom tabs. - you can click on headline and it will open an article of that news in the app(no need to go to chrome or any browser)

 A music picker library for React Native. Provides access to the system's UI for selecting songs from the phone's music library.
A music picker library for React Native. Provides access to the system's UI for selecting songs from the phone's music library.

Expo Music Picker A music picker library for React Native. Provides access to the system's UI for selecting songs from the phone's music library. Supp

:movie_camera: Movie discovery app showcasing Android best practices with Google's recommended architecture: MVVM + Repository + Offline support + Android Architecture Components + Paging library & Retrofit2.
:movie_camera: Movie discovery app showcasing Android best practices with Google's recommended architecture: MVVM + Repository + Offline support + Android Architecture Components + Paging library & Retrofit2.

Popular Movies Stage 1 + Stage 2 Discover the most popular and top rated movies playing. Movies data fetched using themoviedb.org API. ✨ Screenshots M

Oratio Library for Android Studio helps you simplify your Android TTS codes

Oratio Oratio is a library for Android Studio. This library is useful to a number of developers who are currently making apps using android TTS(Text-T

Android-easy-permissions-kt - EasyPermissionsKt - A lightweight Android library that abstracts all runtime permission boilerplate code to simplify the system permissions managemen
Unity-Android-SDK-Plugins - Android SDK/Library/Plugins (aar) for Unity Developers

Unity Android SDK Plugins Unity Android SDK Plugins is an Open Source project th

Spantastic - an Android library that provides a simple and Kotlin fluent API for creating Android Spannable
Spantastic - an Android library that provides a simple and Kotlin fluent API for creating Android Spannable

Spantastic is an Android library that provides a simple and Kotlin fluent API for creating Android Spannable. This library wrappers SpannableStringBuilder and add methods to easily decorate the text with multiple spans.

AndroidEssentials is an android library that creates helper functions for performing common tasks in Android

AndroidEssentials is an android library that creates helper functions for performing common tasks in Android such as managing preferences, managing files, showing alerts, showing toasts, checking user country & checking network connection of users. All the methods of the class are static and should be accessed directly from the AndroidEssentials class.

Utility Android app for generating color palettes of images using the Palette library. Written in Kotlin.
Utility Android app for generating color palettes of images using the Palette library. Written in Kotlin.

Palette Helper is a simple utility app made to generate color palettes of images using Google's fantastic Palette library. It's mostly a for-fun pet p

Releases(0.1.3)
Owner
QIWI
QIWI's open source contributions
QIWI
Twidere-Android Twidere is a powerful twitter client for Android 1.6+ 1 , which gives you a full Holo experience and nearly full Twitter's feature.

Twidere for Android Material Design ready and feature rich Twitter/Mastodon/Fanfou app for Android 4.1+. Enjoy Fediverse now! Twidere-Android is maint

Twidere Project 2.7k Jan 2, 2023
Android playground project with modularization by feature (android libraries), unit tests, MVVM & MVI.

Movies Movies is a simple project to study and play with some android components, architecture and tools for Android development. Tech Stack This proj

Christopher Elias 333 Dec 30, 2022
Awesome Kid's Drawing App. It has a click and draws feature.

CanvaKids Overview It's a kid's drawing app which is build for android users. It is built in Kotlin with some very good practices involved.

null 9 Oct 30, 2021
A project for the implementation of the car animation feature in most ride-sharing/ food delivery apps

CarAnimation This is a test project to practice the implementation of the car animation feature in most ride-sharing/ food delivery apps. Slowly build

Samurai 45 Dec 23, 2022
The simplest version of a notepad application with the feature to save pictures on a note.

PhotoNotePad Easy to write, read and organize notes with photo(s). Feature A note has... title content date color pin images Easy to write a note. Pro

seungmin shin 1 Dec 5, 2021
This app contains feature barcode and QR scanner, and video recording in-app.

BarcodeQRScannerAndVideoRecord This app contains feature barcode and QR scanner, and video recording in-app. Scanner using ML Kit and CameraX. Video R

Abdullah Fahmi 1 Dec 23, 2021
DroidFish is a feature-rich graphical chess user interface, combined with the very strong Stockfish chess engine.

Introduction DroidFish is a feature-rich graphical chess user interface, combined with the very strong Stockfish chess engine. DroidFish is primarily

Peter Österlund 233 Jan 4, 2023
Shotify aims to improve a largely forgotten about feature of the game: screenshots

A highly advanced screenshot mod. Modrinth • Curseforge Shotify aims to improve a largely forgotten about feature of the game: screenshots. Taking a s

Xander 6 Oct 24, 2022
A lightweight, feature-rich wrapper for the Telegram Bot API, providing a handy Kotlin DSL to quickly build your bot.

Kotlin Telegram Bot Kotlin based wrapper over Telegram API. Current version of the Telegram Api: 6.0 Principles Annotations Magic. The basic interacti

Jey 61 Dec 27, 2022
A News Application Shows Breaking News of the Country with a feature to save News for future Use.

A News Application Shows Breaking News of the Country with a feature to save News for future Use.You can search news on any topic.Used all latest stuffs in android like Navigation Component, MVVM Architecture, Retrofit, Room DataBase, Kotlin Corutines etc

Aman Bhatt 2 Oct 20, 2022