# Debug Drawers and You: Adding A Debug Drawer To Your App

Said another way, how to supercharge your development workflow with a debug drawer.

As Android developers, we're constantly looking for ways to streamline our workflow.

One often-overlooked tool that can significantly boost your development process is the debug drawer.

In this post, we'll explore how to implement and leverage debug drawers to take your Android app development to the next level.

# What is a Debug Drawer?

A debug drawer is a hidden panel in your app that contains various tools and information useful during development and testing.

Think of it as a Swiss Army knife for developers – always there when you need it, but invisible to regular users.

![dd](https://github.com/JakeWharton/u2020/raw/master/u2020.gif align="left")

# Adding A Debug Drawer To Your App

The concept we are going to employ to add a debug drawer to your app is to use debug and release configurations in Gradle to include different modules depending on the build.

To add a debug drawer to your app, we will first start by creating a new module.

In this example, I'll call it `:debug-drawer`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727296471592/4b9d10b4-bf07-4974-89e8-ff956ae2ef2c.png align="center")

We are also going to want to create a no-op release implementation of this module so we can have different behaviors in debug vs. release builds.

In this example, I'll call it `:debug-drawer-release`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727296488777/800635f7-77ff-46ea-8ddf-b35c8bd2e7af.png align="center")

Lastly, we are going to create a `:debug-drawer-api` module for common configurations of our debug drawer feature.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727296500907/75aa79ff-b0a6-4784-9302-3cb338eb0297.png align="center")

In our `:app` module, I'm going to add `:debug-drawer` to the `:app` module as a dependency via the `debugImplementation` Gradle configuration.

I'm also going to add the `:debug-drawer-release` to the `:app` module as a dependency via the `releaseImplementation` Gradle configuration.

Lastly, I'm going to add `:debug-drawer-api` to the `:app` module as a dependency via the regular `implementation` Gradle configuration

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727296509617/3051e0ae-da88-4666-a46d-e334cd0731c5.png align="center")

Now comes the actual implementation of opening the debug drawer!

In this example, we will be opening the debug drawer by pressing the volume down key two times.

The main reason for this is most developers on our team use emulators, where sliding to open can be awkward.

Add the following code to the `:debug-drawer-api` module:

```kotlin
interface DebugOnlyKeyListener {
  fun onKeyDown(event: KeyEvent)
}
```

Then, we will modify the `:debug-drawer` and `:debug-drawer-release` modules to both depend on the `:debug-drawer-api` module via the `implementation` Gradle configuration.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727296704600/3ee2585d-4336-4944-b1b2-95720171ce4a.png align="center")

Now, we can move on to actually creating debug and release implementations of `DebugOnlyKeyListener`

We will create classes with the same name that implement the `DebugOnlyKeyListener`.

The one that lives under `:debug-drawer-release` will have a no-op implementation, while the one that lives under `:debug-drawer` will have an actual implementation.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727296732762/ae2eaef3-1d86-42aa-ac10-9a543fd5ccf4.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727296736556/2a438f54-f1e5-4b0e-8f3f-20ed16c97581.png align="center")

Now, let's create the actual implementation for `DebugOnlyKeyListener` in the `:debug-drawer` module!

```kotlin
import android.app.Application
import android.view.KeyEvent
import com.example.debugdrawer.debug.drawer.api.DebugOnlyKeyListener

class DebugOnlyKeyListenerImpl(val application: Application) : DebugOnlyKeyListener {
    private var count = 0

    override fun onKeyDown(event: KeyEvent) {
        if (event.isVolumeDownPressed()) {
            count++
        } else {
            count = 0
        }
        // Look for volume down twice in a row.
        if (count >= 2) {
            count = 0

            // start the debug activity
            val intent = Intent(application, DebugDrawerActivity::class.java)
            intent.flags += Intent.FLAG_ACTIVITY_NEW_TASK
            application.startActivity(intent)
        }
    }

    private fun KeyEvent.isVolumeDownPressed(): Boolean {
        return keyCode == KeyEvent.KEYCODE_VOLUME_DOWN &&
                (action == KeyEvent.ACTION_DOWN || action == KeyEvent.ACTION_UP)
    }
}
```

While a fairly trivial implementation, we are just listening for 2 consecutive volume down presses to trigger some functionality.

Now, we can add an Activity to the `:debug-drawer` module.

```kotlin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.Text

class DebugDrawerActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Text("Hello from debug drawer!")
        }
    }
}
```

```xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application>
        <activity
            android:name=".DebugDrawerActivity"
            android:launchMode="singleInstance" />
    </application>
</manifest>
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727296827184/ae9a441e-8d19-4979-81c6-2f7b13d75d2f.png align="center")

Lastly, this can all be tied together in the main Activity that you want to trigger the debug drawer from.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727296842830/a581de28-755d-48b1-9df4-bd0c045ff9f7.png align="center")

Now, to test a debug build!

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727296876905/be744eb0-e486-4e76-8af9-c6238151e57b.gif align="center")

The debug Activity correctly opens in a debug build!

Now to test a release build.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727296893085/15f82e70-0d38-45ad-927b-20e20ab4977d.gif align="center")

In a release build, nothing happens after pressing the volume down two times.

At this point, you can add any functionality you want to your `DebugDrawerActivity` like listing feature flags, modifying and viewing network requests, etc.
