{"id":35272571,"url":"https://github.com/tapadoo/debugmenu","last_synced_at":"2026-03-11T23:04:23.579Z","repository":{"id":322818708,"uuid":"1081135706","full_name":"Tapadoo/DebugMenu","owner":"Tapadoo","description":"A simple, modular library that adds a floating debug menu to your Android app, allowing you to view analytics events, inspect DataStore preferences, monitor logs, and create custom debugging modules.","archived":false,"fork":false,"pushed_at":"2026-03-02T16:55:08.000Z","size":24719,"stargazers_count":10,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-02T19:59:28.573Z","etag":null,"topics":["android","debug-menu","kotlin","kotlin-android","library"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Tapadoo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-22T11:09:05.000Z","updated_at":"2026-03-02T16:55:13.000Z","dependencies_parsed_at":null,"dependency_job_id":"5d2117c4-985a-4d12-ae50-a256e8f5d6e5","html_url":"https://github.com/Tapadoo/DebugMenu","commit_stats":null,"previous_names":["tapadoo/debugmenu"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/Tapadoo/DebugMenu","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tapadoo%2FDebugMenu","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tapadoo%2FDebugMenu/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tapadoo%2FDebugMenu/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tapadoo%2FDebugMenu/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Tapadoo","download_url":"https://codeload.github.com/Tapadoo/DebugMenu/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tapadoo%2FDebugMenu/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30406402,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-11T22:36:59.286Z","status":"ssl_error","status_checked_at":"2026-03-11T22:36:57.544Z","response_time":84,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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","debug-menu","kotlin","kotlin-android","library"],"created_at":"2025-12-30T12:58:59.459Z","updated_at":"2026-03-11T23:04:23.573Z","avatar_url":"https://github.com/Tapadoo.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Android Debug Menu\n\nA module-based debug menu to debug your Android application\n\nA simple, modular library that adds a floating debug menu to your Android app, allowing you to view analytics events,\ninspect DataStore preferences, monitor logs, and create custom debugging modules.\n\n### Why?\n\nCurrently, there are a couple of other debug menu libraries,\nlike [Lens-Logger](https://github.com/farhazulMullick/Lens-Logger/tree/feat/log-datastore)\nand [Beagle](https://github.com/pandulapeter/beagle), however, they were either focused on a limited set of features or\ninterfered with the LayoutInspector in Android Studio.\n\nThis library offers a lightweight, easy-to-use, and modular debug menu that you can easily integrate into your app and\ncustomise to your needs.\n\n\u003cdetails\u003e\n\u003csummary\u003eDemo\u003c/summary\u003e\n    \u003cimg src=\"https://github.com/Tapadoo/DebugMenu/blob/main/DEMO.gif\"  alt=\"DebugMenu demo\"/\u003e\n\u003cbr/\u003e\n\u003c/details\u003e\n\n## Getting Started\n\n### Installation\n\n1. Declare the library as a dependency in your app's `build.gradle`\n\n```kotin\n    implementation(\"com.github.Tapadoo:DebugMenu:\u003cversion\u003e\")\n```\n\n### Basic Usage\n\nTo use the library, you first need to add the FAB to your Activity/Composable; this changes depending on the\nproject.\n\n\u003cdetails\u003e\n\u003csummary\u003eSingle-Activity Composable App\u003c/summary\u003e\n\u003cbr/\u003e\nIf you're using a single-activity Composable, you can add the `DebugMenuOverlay` to your top-level composable.\n\n```kotlin\nsetContent {\n    AppTheme {\n        NavigationComposable()\n        // Only show the debug menu in debug builds\n        if (BuildConfig.DEBUG) {\n            DebugMenuOverlay(\n                modules = listOf(\n                    // Your Modules...\n                ),\n            )\n        }\n    }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eMulti-Activity App\u003c/summary\u003e\n\u003cbr/\u003e\nIf your project is a multi-activity navigation, you can use the `DebugMenuAttacher.attachToApplication` method to your\n`Activity.onCreate()` to attach the debug menu to your whole application. \n\nThis also has the advantage of not having to use Compose in your project.\n\n```kotlin\nclass DemoApp : Application() {\n    override fun onCreate() {\n        super.onCreate()\n        if (BuildConfig.DEBUG) {\n            DebugMenuAttacher.attachToApplication(\n                this,\n                listOf(\n                    // Your Modules...\n                )\n            )\n        }\n    }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eSingle Activity Fragment App\u003c/summary\u003e\n\u003cbr/\u003e\nIf your project is a single activity but uses Fragments for navigation, you can use the `DebugMenuAttacher.attach` method to your `Activity.onCreate()` to attach the debug menu to your whole application. \n\nThis also has the advantage of not having to use Compose in your project.\n\n```kotlin\nclass MainActivity : ComponentActivity() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        if (BuildConfig.DEBUG) {\n            DebugMenuAttacher.attach(\n                this,\n                listOf(\n                    // Your Modules...\n                )\n            )\n        }\n    }\n}\n```\n\n\u003c/details\u003e\n\n### Showing the Debug Menu\n\n\u003cdetails\u003e\n\u003csummary\u003eFAB Button\u003c/summary\u003e\nWith all the usage methods above, you can also pass a `showFab` parameter to show or hide the FAB button.\n\n```kotlin\nDebugMenuOverlay(\n    showFab = true, // \u003c-- Only open through the FAB button\n    enableShake = false, // \u003c-- Disable shake to open\n    modules = listOf(\n        // your modules...\n    )\n)\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e Shake to Open \u003c/summary\u003e\nIf you only want the menu to be opened through shake, you can pass `enableShake` to `true` and disable the FAB button.\n\n```kotlin\nDebugMenuOverlay(\n    showFab = false, // \u003c-- Disable FAB button\n    enableShake = true, // \u003c-- Enable shake to open\n    modules = listOf(\n        // your modules...\n    )\n)\n```\n\u003c/details\u003e\n\n## Integrating Modules\n\n\u003e Note: Modules determine the order in which they are displayed in the debug menu.\n\n\u003cdetails\u003e\n\u003csummary\u003eAnalytics Module\u003c/summary\u003e\n\u003cbr/\u003e\n\n**Adding Analytics Module**\n\nFirst, to show the module, you need to add the `AnalyticsModule` to your list of Modules. Then, you can use the\n`DebugAnalytics` singleton to log events.\n\n```kotlin\nDebugMenuOverlay(\n    modules = listOf(\n        AnalyticsModule(),\n        // Rest of your modules...\n    ),\n)\n```\n\n**Logging Analytics Events**\n\nMost analytics libraries have a common schema, like `event_name` and `event_properties` that usually is a map of\nkey-value pairs, you can\njust add the event to the `DebugAnalytics` singleton, and it will be logged in the debug menu.\n\n\u003e **Note:** The signature of the `logEvent` method is the same as Firebase Analytics, so if you're using Firebase\n\u003e Analytics,\n\u003e you can just call it in the same way.\n\n```kotlin\nclass AnalyticsManager {\n    fun logEvent(event: AnalyticsEvent) {\n        // create a bundle or map from an event\n        DebugAnalytics.logEvent(event.name, bundle) // \u003c-- Add the event to the DebugMenu\n        firebaseAnalytics.logEvent(event.name, bundle)\n    }\n}\n\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eDataStore Module\u003c/summary\u003e\n\u003cbr/\u003e\n\n**Adding DataStore Module**\n\nJust add the `DataStoreModule` class to your list of Modules, and pass the list of DataStores and, you're good to go. The\nUI Will automatically generate the UI for every entry.\n\n```kotlin\nDebugMenuOverlay(\n    modules = listOf(\n        DataStoreModule(\n            listOf(\n                this@MainActivity.applicationContext.demoDataStore\n            )\n        ),\n        // Rest of your modules...\n    ),\n)\n```\n\n**Exposing DataStores to the DebugMenu**\n\nMost Repositories use DataStore privately to store data, you can convert it into an extension function on top of the\n`Context` type:\n\n```kotlin\nval Context.demoDataStore: DataStore\u003cPreferences\u003e by preferencesDataStore(name = \"app_datastore_key\")\n``` \nAnd then pass it to the `DebugMenuOverlay` or `DebugMenuAttacher`\n\n```kotlin\nDebugMenuAttacher.attach(\n    this,\n    modules = listOf(\n        DataStoreModule(listOf(this@MainActivity.applicationContext.demoDataStore)),\n        // Rest of your modules...\n    ),\n)\n// or\nDebugMenuOverlay(\n    modules = listOf(\n        DataStoreModule(\n            listOf(this@MainActivity.applicationContext.demoDataStore)\n        ),\n        // Rest of your modules...\n    ),\n)\n\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eLogging Module\u003c/summary\u003e\n\u003cbr/\u003e\nThe logging module captures log messages from your app and displays them in the debug menu. \n\n**Adding the module**\n\n```kotlin\nDebugMenuAttacher.attach(\n    this,\n    modules = listOf(\n        LoggingModule(),\n        // Rest of your modules...\n    ),\n)\n// or\nDebugMenuOverlay(\n    modules = listOf(\n        LoggingModule(),\n        // Rest of your modules...\n    ),\n)\n```\n\n**Integrating Logs**\nIntegrate it by wrapping your existing logger. (Example with Timber)\n\n```kotlin\nclass DemoApp : Application() {\n    override fun onCreate() {\n        super.onCreate()\n        if (BuildConfig.DEBUG) {\n            Timber.plant(\n                object : Timber.DebugTree() {\n                    override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {\n                        super.log(priority, tag, message, t)\n                        DebugLogs.log(priority = priority, tag = \"$tag\", message = message, t = t)\n                    }\n                }\n            )\n        }\n    }\n}\n```\n\n![Debug Menu Logging Module Demo](https://github.com/Tapadoo/DebugMenu/blob/main/LOGS_DEMO.gif?raw=true)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eDynamic Module\u003c/summary\u003e\n\u003cbr/\u003e\nThe dynamic module allows you to add custom actions to the debug menu. They can either be:\n\n- Global actions: These actions are displayed in the debug menu and can be triggered from anywhere in the app.\n- Dynamic Actions: These actions are only displayed when the user is in a specific screen and get automatically removed\n  when the user navigates away from that screen.\n\n**Adding the module \u0026 Global Actions**\n\n```kotlin\nDebugMenuAttacher.attach(\n    this,\n    modules = listOf(\n        DynamicModule(\n            globalActions = listOf(\n                DynamicAction(\"Global Action 1\") {\n                    // Perform global action\n                }\n            )\n        ),\n        // Rest of your modules...\n    ),\n)\n// or\nDebugMenuOverlay(\n    modules = listOf(\n        DynamicModule(\n            globalActions = listOf(\n                DynamicAction(\"Global Action 1\") {\n                    // Perform global action\n                }\n            )\n        ),\n        // Rest of your modules...\n    )\n)\n```\n\n**Adding Dynamic Actions**\n\nThese will only be displayed when the user is in the screen where they are added, ideal for actions that are only\nrelevant to that screen.\n\nCompose:\n```kotlin\n@Composable\nfun YourScreenComposable() {\n    val lifecycleOwner = LocalLifecycleOwner.current\n    DynamicModuleActions(\n        lifecycleOwner, DynamicAction(\"Name of the action\", \"Description of the action (Optional)\") {\n            // Do something when the user clicks the action (i.e. talk to ViewModel)\n        }\n    )\n}\n```\n\nFragment/Activity:\n```kotlin\n class MyFragment : Fragment() {\n     override fun onCreate(savedInstanceState: Bundle?) {\n         super.onCreate(savedInstanceState)\n         registerDynamicModuleActions(\n             DynamicAction(\"Action 1\") { /* action 1 */ },\n         )\n     }\n }\n\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eNetwork Module\u003c/summary\u003e\nThe network module allows you to monitor network requests in the debug menu as well as copying the request body to the\nclipboard or multiple requests at once.\n\n**Adding the module**\n\n```kotlin\nDebugMenuAttacher.attach(\n    this,\n    modules = listOf(\n        NetworkModule()\n        // Rest of your modules...\n    ),\n)\n// or\nDebugMenuOverlay(\n    modules = listOf(\n        NetworkModule()\n        // Rest of your modules...\n    )\n)\n```\n\n**Intercepting Network Requests**\n\u003e Note: This library does not include out-of-the-box integration with OkHttp or any other networking library. Instead,\n\u003e you need to intercept the requests yourself and add them to the `DebugNetworkRequests` singleton.\n\n\n- OKHttp Interceptor (Example):\n```kotlin\nobject DebugMenuInterceptor : Interceptor {\n    override fun intercept(chain: Interceptor.Chain): Response {\n        val request = chain.request()\n        val startTime = System.currentTimeMillis()\n        val response = chain.proceed(request)\n        val duration = System.currentTimeMillis() - startTime\n        var responseBodyString: String? = null\n        response.body?.let { responseBody -\u003e\n            val source = responseBody.source()\n            source.request(Long.MAX_VALUE)\n            val buffer = source.buffer\n            responseBodyString = buffer.clone().readString(responseBody.contentType()?.charset() ?: Charsets.UTF_8)\n        }\n\n        val debugRequest = DebugNetworkRequest(\n            url = request.url.toString(),\n            method = request.method,\n            headers = request.headers.toMap(),\n            responseHeaders = response.headers.toMap(),\n            body = request.body?.toString() ?: \"\",\n            timestamp = startTime,\n            duration = duration,\n            isSuccessful = response.isSuccessful,\n            code = response.code,\n            error = if (!response.isSuccessful) response.message else null,\n            response = responseBodyString,\n            requestSize = request.body?.contentLength() ?: 0\n        )\n\n        DebugNetworkRequests.add(debugRequest)\n        return response\n    }\n}\n\n// Add the interceptor to your OkHttp client\n\nval okHttpClient = OkHttpClient.Builder()\n    .addInterceptor(DebugMenuInterceptor)\n    .build()\n```\n\n![Debug Menu Network Module Demo](https://github.com/Tapadoo/DebugMenu/blob/main/NETWORK_DEMO.gif?raw=true)\n\n\u003c/details\u003e\n\n### Creating your own Module\n\nYou can create custom modules to display any debugging information specific to your app. For example, a network request\nmonitor, feature flags viewer, or app configuration inspector. Just extend the `DebugMenuModule` class and implement its\nmethods.\n\n\nMade with Love by [Tapadoo](https://tapadoo.com)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftapadoo%2Fdebugmenu","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftapadoo%2Fdebugmenu","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftapadoo%2Fdebugmenu/lists"}