Repository navigation
Make custom callbacks work on iOS and Android - #20
Conversation
PaywallPresentationHandler.OnCustomCallback existed but neither native bridge called it, and C# had no way to reply. Every callback a paywall requested failed straight away without reaching the game. Both bridges now register a native handler, hold each request until C# replies, and fail instead of waiting when a request can't be delivered or a reply can't be parsed. On Android, an activity-hosted paywall pauses Unity, so callbacks fail immediately and log an error naming the fix. OnCustomCallback becomes Func<CustomCallback, Task<CustomCallbackResult>> so a handler can wait on a network request. If it throws, is cancelled or returns null, or the placement has none, the paywall gets a failure. The generated Podfile now requires SuperwallKit 4.12.10 or newer, the first version with this API, and updates the old requirement in a Podfile kept by an Append build. Adds bridge tests on iOS and Android, and a .NET harness that runs Tests/Runtime in CI without a Unity licence. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
📚 Docs requiredWhat changed for customers: Unity games can now handle a paywall's Custom Callback action on iOS and Android, by awaiting their own logic and returning a result that picks the paywall's onSuccess or onFailure branch. A synchronous Why this needs docs:
Coverage today: stale in places and absent in others. No page says Unity lacks custom callbacks, but none explains how to use them on Unity.
Without a docs page this change also gets no changelog entry: Prompt for the docs agent — run in
|
Problem
PaywallPresentationHandler.OnCustomCallbackexisted but never ran:onCustomCallback, so the SDK found no handler and answered every callback withfailure. No C# ran and nothing was logged in Unity.HandleOnCustomCallbackbuilt a response and never sent it.A paywall that asks the game to do something, such as creating an account through its own API, therefore always took its failure branch.
Changes
onCustomCallbackto C#, and hold the request untilRespondToCustomCallbackanswers with the samecallbackId. A request that can't be delivered or a reply that can't be parsed fails, so the paywall never waits on a reply that can't come.OnCustomCallbackis nowFunc<CustomCallback, Task<CustomCallbackResult>>. If it throws, is cancelled or returns null, or the placement has no handler, the paywall gets a failure. The reply always goes out from the main thread. AddsCustomCallbackResult.Success(data)andFailure(data).AndroidPaywallPresentation.Activityeach callback fails immediately and logs an error naming the fix.>= 4.12.10, < 5.0, the first versions with this API, and rewrites the old~> 4.0line in a Podfile kept by an Append build. A customer's own pin is left alone.Breaking change
A synchronous
OnCustomCallbackhandler no longer compiles. The fix is anasynclambda orTask.FromResult(...). Nothing that works today stops working, because that handler never ran. Keeping the old field alongside a new one would leave a field that looks usable and does nothing.New CI
native.ymlnow runs an XCTest target on a simulator, which also covers the Swift half of this contract.csharpjob runsTests/Runtimeon .NET throughci~/csharp-harness, with no Unity licence. It compiles the realRuntime/, tests and sample against a smallUnityEnginestand-in that copies the behaviour the tests rely on: frames, the main-thread context,LogAssert, and failing on an unexpected error log. It also compiles theUNITY_IOSandUNITY_ANDROIDbranches, which nothing else in CI builds.unity.ymlstays parked.Testing
Not yet run in a real Unity player, or on a physical device. Please run a signup through a real build on both platforms before release.
Live, against a published paywall in an internal test app, with a small native app standing in for Unity and calling the same bridge entry points:
AndroidPaywallPresentation.ActivityokStatus: failure, the reported symptomThese ran before the rebase onto #13 and #18, neither of which touches the callback code. The test paywalls and campaigns are archived.
On this branch:
UNITY_IOSandUNITY_ANDROIDbranches compileFour deliberate breaks to the C# handler were each caught: replying off the main thread, not catching exceptions, no reply for a missing handler, and not waiting for the task. Two payloads captured from the live runs are pinned in
CustomCallbackTests. The Editor Podfile code isn't covered by CI. I compiled and ran it once against stubs, for a new Podfile, the old requirement, a customer's own pin and a Podfile with no SuperwallKit, and CocoaPods parsed each result.The new CI jobs have not run yet; this PR is their first run.
🤖 Generated with Claude Code