docs

Installation

What you need

  • An app with minSdk 23 or higher and compileSdk 35 or higher. Debug builds need minSdk 24.
  • Kotlin 2.0 or newer, if the app uses Kotlin.
  • Android Gradle Plugin 8.8 or newer.
  • A Free or Pro Buoy account key. Get one in your Buoy account.

Buoy works in Compose apps and in apps built with plain views. It brings in Jetpack Compose and OkHttp for its own screens. It also adds two permissions to builds that use it. INTERNET lets it reach Desktop and check your account. POST_NOTIFICATIONS lets the Notifications tool send test alerts. The no-op adds no permissions.

Is your app's minSdk 23? Then raise it to 24 in each build that uses Buoy. This keeps release at 23:

kotlin
androidComponents {
    beforeVariants(selector().all()) { if (it.buildType != "release") it.minSdk = 24 }
}
androidComponents {
    beforeVariants(selector().all()) { if (it.buildType != "release") it.minSdk = 24 }
}

In a Groovy build.gradle, the same lines work as they are. Your release build can stay at 23. The no-op works on 23. Java code on 23 can't use the Supplier form of BuoyBench.configure. That type needs API 24. Use the other form, or turn on core library desugaring.

Add the package

Buoy is on Maven Central. Make sure mavenCentral() is in your repositories. Then add Buoy to your app module:

kotlin
dependencies {
    debugImplementation("gg.buoy:buoy-android:0.1.0")
    releaseImplementation("gg.buoy:buoy-android-noop:0.1.0")
}
dependencies {
    debugImplementation("gg.buoy:buoy-android:0.1.0")
    releaseImplementation("gg.buoy:buoy-android-noop:0.1.0")
}

buoy-android holds every tool. buoy-android-noop has the same setup calls, and they do nothing. See Release Builds.

While Buoy is 0.x, a new minor version can break things. Pin the version you test with.

If your build checks licenses

Some apps check the license of every package they use. One common tool for this is Licensee. Buoy is not open source, so its license is a link to our terms. Add that link to your allowed list:

kotlin
licensee {
    allowUrl("https://buoy.gg/terms")
}
licensee {
    allowUrl("https://buoy.gg/terms")
}

If your build checks package hashes

Some apps list a hash for every package they trust. Gradle calls this dependency verification. Add Buoy's packages to that list when you add Buoy.

If your app ships its own copy of AndroidX

Buoy uses AndroidX. Some apps bundle their own copy of AndroidX parts under the same names. Then the build fails with "Duplicate class androidx...". Leave out your copy in debug builds, where Buoy runs.

Account key

The Quick Start reads the key from local.properties into a BuildConfig field. Any way your app gets config is fine. Keep the key out of git.

kotlin
Buoy.start(this, BuoyConfig(licenseKey = BuildConfig.BUOY_LICENSE_KEY.ifEmpty { null }))
Buoy.start(this, BuoyConfig(licenseKey = BuildConfig.BUOY_LICENSE_KEY.ifEmpty { null }))

A free account works in debug builds. A build that is not debuggable needs a Pro plan.

To skip the key, let people sign in with a code instead:

kotlin
Buoy.start(this, BuoyConfig(signIn = BuoySignInConfig()))
Buoy.start(this, BuoyConfig(signIn = BuoySignInConfig()))

Start Buoy

Call Buoy.start in Application.onCreate. It runs on the main thread. A call from another thread waits for the main thread.

Buoy starts every tool and draws its button over each screen. You don't add a view or call an install step.

Start Buoy before you build OkHttp clients and other app parts that make web calls.

Compose and views

Nothing changes between the two. Buoy draws its own layer on top of each activity. Taps that miss Buoy go to your app.

Some tools need a line in your UI code, like BuoyAsyncImage or Modifier.buoyTrackRenders. Tools lists them.

Settings

BuoyConfig takes these:

SettingWhat it does
enabledTurns Buoy off when false.
deviceNameThe name Desktop shows.
deviceIdLeave it unset. Buoy makes one id per install. A custom id must be different on each device.
socketUrlWhere Buoy Desktop is. See Physical Devices.
licenseKeyYour account key.
signInLets people sign in with a code.
telemetryOne anonymous ping a day, in debug builds only.
enableLogsPrints Buoy's own log lines.
extraDeviceInfoExtra lines for the device card in Desktop.
allProcessesStarts Buoy in every process, not just the main one.

Java code can call Buoy.start(context) or Buoy.start(context, config).

Buoy Desktop

Open Buoy Desktop and sign in. Buoy looks for it at http://localhost:42831. On the emulator, run this once:

bash
adb reverse tcp:42831 tcp:42831
adb reverse tcp:42831 tcp:42831

For a real phone, see Physical Devices.

Pick the Android device in Desktop. Then check a web call again. Being connected and seeing calls are two different checks.

Stop Buoy

A second Buoy.start gives back the running copy. It can set a new account key. It does not change the Desktop address or the device id.

Buoy.stop() takes Buoy out of the app. The button goes away and the link to Desktop closes. Each tool stops changing what the app sees. The network hook stays in your client, but it lets every call pass. Saved tool settings stay, so a later Buoy.start picks them up.