{"id":22509485,"url":"https://github.com/kernel0x/finch","last_synced_at":"2025-04-05T12:07:54.917Z","repository":{"id":49672719,"uuid":"197173098","full_name":"kernel0x/finch","owner":"kernel0x","description":"🖥 Debug menu library for Android apps with supports network activity logging and many other useful features.","archived":false,"fork":false,"pushed_at":"2024-12-12T08:06:05.000Z","size":10363,"stargazers_count":135,"open_issues_count":1,"forks_count":11,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-29T11:10:06.018Z","etag":null,"topics":["android","android-library","debug","grpc","grpc-android","kotlin-library","library","logging","menu","network","notifications","okhttp","okhttp-interceptor","okhttp3"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kernel0x.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-07-16T10:30:14.000Z","updated_at":"2025-03-14T22:35:41.000Z","dependencies_parsed_at":"2023-12-28T19:27:55.838Z","dependency_job_id":"9c26db14-a5e8-4c8e-b13a-1590c6ce075c","html_url":"https://github.com/kernel0x/finch","commit_stats":null,"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kernel0x%2Ffinch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kernel0x%2Ffinch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kernel0x%2Ffinch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kernel0x%2Ffinch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kernel0x","download_url":"https://codeload.github.com/kernel0x/finch/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247332612,"owners_count":20921853,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","android-library","debug","grpc","grpc-android","kotlin-library","library","logging","menu","network","notifications","okhttp","okhttp-interceptor","okhttp3"],"created_at":"2024-12-07T01:29:15.366Z","updated_at":"2025-04-05T12:07:54.894Z","avatar_url":"https://github.com/kernel0x.png","language":"Kotlin","readme":"# Finch\nFinch offers a customizable debug menu for Android app development. It does not affect production code. Developers can easily add their own custom debugging features with simple steps.\n\n\u003cimg src=\"assets/finch.gif\" width=\"282\" height=\"518\"/\u003e\n\n## Gradle Dependency\n\nAdd it in your root build.gradle at the end of repositories:\n\n````java\ndependencyResolutionManagement {\n    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)\n    repositories {\n        mavenCentral()\n        maven { url 'https://jitpack.io' }\n    }\n}\n````\n\nPick a UI implementation and add the dependency:\n* **ui-activity** - The debug menu as a new screen.\n* **ui-bottom-sheet** - The debug menu as a modal bottom sheet.\n* **ui-dialog** - The debug menu as a modal dialog.\n* **ui-drawer** - The debug menu as a side navigation drawer.\n* **ui-view** - The debug menu as a view.\n* **noop** - For release build.\n\n````java\ndependencies {\n    debugImplementation 'com.github.kernel0x.finch:ui-drawer:2.3.0'\n    releaseImplementation 'com.github.kernel0x.finch:noop:2.3.0'\n    // optional only for OkHttp\n    debugImplementation 'com.github.kernel0x.finch:log-okhttp:2.3.0'\n    releaseImplementation 'com.github.kernel0x.finch:log-okhttp-noop:2.3.0'\n    // optional only for GRPC\n    debugImplementation 'com.github.kernel0x.finch:log-grpc:2.3.0'\n    releaseImplementation 'com.github.kernel0x.finch:log-grpc-noop:2.3.0'\n    // optional only for logs\n    debugImplementation 'com.github.kernel0x.finch:log:2.3.0'\n    releaseImplementation 'com.github.kernel0x.finch:log-noop:2.3.0'\n}\n````\n\n## How to works\n\nInitialize an instance of Finch (preferably in the Application's onCreate() method)\n````java\nFinch.initialize(this)\n````\nVarious customizations are set through the Configuration object.\n\nNext, you need to add which components you want to display in the debug menu. Optionally, you can additionally configure logging and interception network events (with OkHttp).\n\n### Logging\n\nTo add log messages in Debug Menu simple calling Finch.log() and add FinchLogger to Configuration object.\n\n```java\nFinch.log(\"message\")\n```\n```java\nFinch.initialize(\n    application = this,\n    configuration = Configuration(\n        logger = FinchLogger,\n        ...\n    ),\n)\n```\n\n### OkHttp\n\nAdd FinchOkHttpLogger.logger to the method addInterceptor in building OkHttp Client and add FinchOkHttpLogger to Configuration object.\n\n```java\nOkHttpClient.Builder()\n    .addInterceptor(FinchOkHttpLogger.logger as? Interceptor ?: Interceptor { it.proceed(it.request()) })\n    .build()\n```\n```java\nFinch.initialize(\n    application = this,\n    configuration = Configuration(\n        networkLoggers = listOf(FinchOkHttpLogger),\n        ...\n    ),\n)\n```\n\n### Grpc\n\nAdd FinchGrpcLogger.logger to the method intercept in building ManagedChannel and add FinchGrpcLogger to Configuration object.\n\n```java\nManagedChannelBuilder.forAddress(networkConfig.hostname, networkConfig.port)\n    .intercept(FinchGrpcLogger.logger as? ClientInterceptor ?: object : ClientInterceptor {\n        override fun \u003cReqT : Any?, RespT : Any?\u003e interceptCall(\n            method: MethodDescriptor\u003cReqT, RespT\u003e?,\n            callOptions: CallOptions?,\n            next: Channel?\n        ): ClientCall\u003cReqT, RespT\u003e {\n            return object : ForwardingClientCall.SimpleForwardingClientCall\u003cReqT, RespT\u003e(\n                next?.newCall(\n                    method,\n                    callOptions\n                )\n            ) {}\n        }\n    })\n    .build()\n```\n```java\nFinch.initialize(\n    application = this,\n    configuration = Configuration(\n        networkLoggers = listOf(FinchGrpcLogger),\n        ...\n    ),\n)\n```\n\n### Example initialize\n\nHere is a minimal example that should work for most projects\n\n```java\nFinch.initialize(\n    application = this,\n    configuration = Configuration(\n        logger = FinchLogger,\n        networkLoggers = listOf(FinchOkHttpLogger)\n    ),\n    components = arrayOf(\n        Header(\n            title = getString(R.string.app_name),\n            subtitle = BuildConfig.APPLICATION_ID,\n            text = \"${BuildConfig.BUILD_TYPE} v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})\"\n        ),\n        Padding(),\n        Label(\"Tools\", Label.Type.HEADER),\n        DesignOverlay(),\n        AnimationSpeed(),\n        ScreenCaptureToolbox(),\n        Divider(),\n        Label(\"Logs\", Label.Type.HEADER),\n        LifecycleLogs(),\n        NetworkLogs(),\n        Logs(),\n        Divider(),\n        Label(\"Other\", Label.Type.HEADER),\n        DeviceInfo(),\n        AppInfo(),\n        DeveloperOptions(),\n        ForceCrash()\n    )\n)\n```\n\n### Common cases\n\n#### Backend environment\n```java\ndata class Environment(\n    val type: Type,\n    override val title: Text = Text.CharSequence(type.name)\n) : FinchListItem\n\nenum class Type {\n    TEST,\n    PROD\n}\n```\n```java\nSingleSelectionList(\n    title = \"Backend environment\",\n    items = listOf(Environment(Type.TEST), Environment(Type.PROD)),\n    initiallySelectedItemId = Type.TEST.name,\n    isValuePersisted = true,\n    onSelectionChanged = {\n        when (it?.type) {\n            Type.TEST -\u003e {\n                ...\n            }\n\n            Type.PROD -\u003e {\n                ...\n            }\n\n            else -\u003e {\n                // nothing\n            }\n        }\n    }\n),\n```\n\n#### Feature Toggles\n```java\nfun Application.initializeDebugMenu(\n    featureManager: FeatureManager\n) {\n    val toggles = featureManager.getAll().map {\n        Switch(\n            text = it.description,\n            initialValue = it.isEnabled(),\n            isEnabled = true,\n            onValueChanged = { value -\u003e\n                featureManager.save(it.key, value)\n                if (!it.canChangedInRuntime) {\n                    Toast.makeText(this, \"Restart app to apply changes!\", Toast.LENGTH_LONG).show()\n                }\n            }\n        )\n    }\n    Finch.initialize(\n        ...\n        components = arrayOf(\n            ...\n            Divider(),\n            Label(\"Feature Toggles\", Label.Type.HEADER),\n            Switch(\n                text = \"Show\",\n                initialValue = false,\n                isEnabled = true,\n                id = \"feature_toggles\",\n                onValueChanged = {\n                    if (it) {\n                        Finch.add(\n                            components = toggles.toTypedArray(),\n                            position = Position.Below(\"feature_toggles\")\n                        )\n                    } else {\n                        toggles.forEach { item -\u003e\n                            Finch.remove(item.id)\n                        }\n                    }\n                }\n            ),\n            ...\n        )\n    )\n}\n```\n\n#### Logs\n```java\nclass LogTree : Timber.Tree() {\n    override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {\n        FinchLogger.log(message)\n    }\n}\n```\n```java\nfun Application.initializeDebugMenu() {\n    ...\n    Timber.plant(LogTree())\n    Finch.initialize(\n        application = this,\n        configuration = Configuration(\n            logger = FinchLogger,\n        ),\n        ...\n    )\n}\n```\n\n### Components\n[CheckBox](/common/src/main/java/com/kernel/finch/components/CheckBox.kt)\n[Divider](/common/src/main/java/com/kernel/finch/components/Divider.kt)\n[ItemList](/common/src/main/java/com/kernel/finch/components/ItemList.kt)\n[KeyValueList](/common/src/main/java/com/kernel/finch/components/KeyValueList.kt)\n[Label](/common/src/main/java/com/kernel/finch/components/Label.kt)\n[LongText](/common/src/main/java/com/kernel/finch/components/LongText.kt)\n[MultipleSelectionList](/common/src/main/java/com/kernel/finch/components/MultipleSelectionList.kt)\n[Padding](/common/src/main/java/com/kernel/finch/components/Padding.kt)\n[ProgressBar](/common/src/main/java/com/kernel/finch/components/ProgressBar.kt)\n[SingleSelectionList](/common/src/main/java/com/kernel/finch/components/SingleSelectionList.kt)\n[Slider](/common/src/main/java/com/kernel/finch/components/Slider.kt)\n[Switch](/common/src/main/java/com/kernel/finch/components/Switch.kt)\n[TextInput](/common/src/main/java/com/kernel/finch/components/TextInput.kt)\n[AnimationSpeed](/common/src/main/java/com/kernel/finch/components/special/AnimationSpeed.kt)\n[AppInfo](/common/src/main/java/com/kernel/finch/components/special/AppInfo.kt)\n[DesignOverlay](/common/src/main/java/com/kernel/finch/components/special/DesignOverlay.kt)\n[DeveloperOptions](/common/src/main/java/com/kernel/finch/components/special/DeveloperOptions.kt)\n[DeviceInfo](/common/src/main/java/com/kernel/finch/components/special/DeviceInfo.kt)\n[ForceCrash](/common/src/main/java/com/kernel/finch/components/special/ForceCrash.kt)\n[Header](/common/src/main/java/com/kernel/finch/components/special/Header.kt)\n[LifecycleLogs](/common/src/main/java/com/kernel/finch/components/special/LifecycleLogs.kt)\n[Logs](/common/src/main/java/com/kernel/finch/components/special/Logs.kt)\n[LoremIpsumGenerator](/common/src/main/java/com/kernel/finch/components/special/LoremIpsumGenerator.kt)\n[NetworkLogs](/common/src/main/java/com/kernel/finch/components/special/NetworkLogs.kt)\n\n### Proguard\n```java\n-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken\n-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken\n```\n\n## Releases\n\nCheckout the [Releases](https://github.com/kernel0x/finch/releases) tab for all release info.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkernel0x%2Ffinch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkernel0x%2Ffinch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkernel0x%2Ffinch/lists"}