All but React Native are in beta.
All but React Native are in beta.

You decide which builds get Buoy. Most apps use the real SDK in debug builds and the no-op in release builds.
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-noop has the same setup calls as buoy-android.
They do nothing and return right away.
So your setup code builds in both, with no if around it.
The no-op adds no Compose and no Buoy screens to your release APK. It adds a little code that keeps a few calls working the normal way:
BuoyNetwork.interceptor passes each call straight on.BuoyClock.nowMs() gives the real time.BuoyPermissions.check and request give Android's real answer.BuoyNotifications.notify posts the notification as it is.Buoy.start returns null.To tell "blocked" from "never asked", the no-op keeps a small gg.buoy.permissions preferences file.
The real SDK adds the INTERNET and POST_NOTIFICATIONS permissions. The no-op adds none.
If your app posts its own notifications, put POST_NOTIFICATIONS in your own manifest.
Otherwise it works in debug and fails in release.
The no-op only covers setup calls. These are not in it:
BuoyAskBuoy.configure and AskBuoyConfig.BuoyTool and BuoyDevTools.register.BuoyAsyncImage and Modifier.buoyTrackRenders. They need Compose.AskBuoyHeader, MessageList and Composer.Put code that uses them in src/debug.
Then the release build never sees it.
You can put the real SDK in an internal build, like a QA build. Give that build type its own line, so it gets the real SDK and not the no-op:
dependencies {
debugImplementation("gg.buoy:buoy-android:0.1.0")
"qaImplementation"("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")
"qaImplementation"("gg.buoy:buoy-android:0.1.0")
releaseImplementation("gg.buoy:buoy-android-noop:0.1.0")
}
A build that is not debuggable needs a Pro plan.
Guard Buoy.start with your own check, so only your testers get it.
If that build turns on R8, keep your BuildConfig fields, or the Env tool shows nothing:
-keepclassmembers class com.example.app.BuildConfig { public static final <fields>; }
-keepclassmembers class com.example.app.BuildConfig { public static final <fields>; }
An environment badge or a user role is a label, not a lock. Use your app's own checks for who can see or change its data.
Some actions check the build again, even when Buoy runs. They need a debuggable build:
adb shell setprop debug.buoy.socketUrl.