feat(sample): Live Activities demo screens - #618
Conversation
Sample app builds 📱Below you will find the list of the latest versions of the sample apps. It's recommended to always download the latest builds of the sample apps to accurately test the pull request.
|
3dab7ab to
5697c59
Compare
88c39e1 to
b183a6d
Compare
| } minimal: { | ||
| Image(systemName: "car.fill") | ||
| } | ||
| } |
There was a problem hiding this comment.
Could we apply .cioWidgetUrl(context.state.cioMetadata) to both the lock-screen view and the DynamicIsland, like the bundled templates do? Right now the custom activity never emits the Customer.io URL, so the AppDelegate forwarding added in this PR is never reached for Rideshare: no opened metric and no customer deep-link routing. This affects every server-pushed custom activity, not just a visual edge case.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- End the current notification before re-issuing startCustom on update so Android replaces it in place instead of stacking/orphaning a second one. - Return a terminal, non-ongoing notification on the end event so the custom rideshare notification can be dismissed. - Format bridged numeric ETA as an integer (was rendering "5.0 min"). - Revert an unrelated local ccache build-setting change that leaked into the tracked project.pbxproj. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- AppDelegate: handleWidgetUrl replaces reportDeepLinkOpen and returns the customer's redirect URL, which is what the app now routes. - MainApplication: the custom rideshare renderer implements the dedicated CustomerIOLiveNotificationsCallback (createLiveNotification moved off CustomerIOPushNotificationCallback in the native Android SDK). - Config: `liveActivities`/`templates` -> `liveNotifications`/`types`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…cond module Custom iOS activity types previously stood up their own LiveActivitiesModule alongside the wrapper's. With Live Activities now an SDK-managed module reached through CustomerIO.liveActivities, a second registration is last-write-wins and would clobber the built-in templates — and the static initialize entry point it used is gone. The app now requests the activity through ActivityKit and adopts it, so update/end still report. `adopt` does not report `start`: that needs the type registered on the SDK module, which only a Swift metatype can do and so cannot be driven from JavaScript. Verified: example app + LiveActivityWidget.appex build for the simulator. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ending Segments left the card frozen at "3 of 4"; it now ends showing all segments complete and "Delivered". Countdown ends without an endTime so it reads as finished instead of counting down. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
TEMPORARY (REL-1). Adds the Sonatype snapshots host for the Android branch snapshot, and a :git/:branch override so CocoaPods can find the Live Activities pods, which are not on trunk yet. Remove both once Live Notifications ships in released native SDKs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…reen The LiveActivityWidget target is in the tracked Xcode project and its bundle imports CioLiveActivities_Attributes/_Templates, but the Podfile declared no target for it, so it linked nothing and failed to resolve those modules. The block was written earlier and lost in a rebase; this restores it, retargeted at the branch the rest of the Podfile already uses. Also formats liveactivities.tsx, which had never been run through prettier. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The rideshare demo needed an app-owned native module and an `adopt` call on iOS, `startCustom` on Android, and a Platform branch in between. It now uses the same start/update/end the built-in templates use, on both platforms. Deletes what that made redundant: the RideshareAttributes type, the SampleCustomLiveActivity native module, and its ObjC bridge. The widget renders CIOCustomAttributes instead — the SDK owns the type, the app owns the view, which is the whole point of the new custom template. Android's "update" was ending the notification and starting a new one, justified by a comment claiming there is no by-id update for custom types. There is (updateLiveNotification(activityId, activityType, data)); the workaround and the comment are both gone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…se branch The per-PR branch these pods were pinned to was deleted when it merged, so CocoaPods can no longer resolve it. The feature branch it merged into carries the same podspecs and is where the work now lives.
The widget was the one embedded extension with no provisioning profile, and it
carried CODE_SIGNING_ALLOWED = NO — an unsigned appex inside a signed app, which
is what "embedded binary is not signed with the same certificate as the parent
app" was reporting.
Its bundle id also has to follow the host app's, which differs per push
provider, so a single hardcoded value could never sign both builds. It now comes
from BuildSettings/{apn,fcm} xcconfigs like the app and rich-push targets, hard-
linked into place by the same Podfile step.
Requires the two new identifiers to exist in the Apple Developer account before
CI can sign them.
With a profile finally attached, the widget fell back to an Apple Development signing identity while using the AdHoc profile, so xcodebuild rejected the pair: '"match AdHoc io.customer.ami.LiveActivityWidget" doesn't include signing certificate "Apple Development"'. The app and rich-push targets both pin manual signing plus the distribution identity on Release; the widget now matches them.
Adding the Live Activity widget target broke the APN configuration: the widget and the app share the Live Activities Swift pods, and with no framework build type CocoaPods lays those modules out so that the app cannot resolve `customerio_reactnative` — its generated compatibility header imports an umbrella header that only exists in a framework. FCM already built static frameworks and was unaffected, which is why only APN failed. CocoaPods refuses to let a host target and the target it embeds disagree on use_frameworks!, so this has to be set for the app rather than just the widget. Verified locally on a clean tree: pod install and a Release build of SampleApp both succeed with the widget compiled in.
414fb50 to
d6fbe95
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit d6fbe95. Configure here.
The widget rendered correctly but applied no `.cioWidgetUrl`, so the AppDelegate route never fired for a rideshare tap and every server-pushed custom activity lost its opened metric and deep link. Applied to the lock screen and the Dynamic Island, matching where the SDK's built-in templates put it.

Demo screens for the two built-in templates and an app-owned custom type, plus AppDelegate routing for the opened metric.
Stacked on #617.
Note
Low Risk
Changes are confined to the example app and reference integrations; deep-link handling is additive and only affects the sample AppDelegate.
Overview
Adds a Live Activities demo to the React Native sample app, covering built-in Segments and Countdown templates plus a custom Rideshare type, with the native plumbing needed on both platforms.
A new Live Activities screen drives
CustomerIO.liveActivitiesstart/update/end for each template. Default SDK config now registers segment and countdown types and the ridesharecustomType. Home navigation links to the screen.iOS adds a
LiveActivityWidgetextension (SDK built-in templates + app-ownedRideshareLiveActivitySwiftUI), enablesNSSupportsLiveActivities, wires theliveactivitiespod subspec with temporary branch-based CIO pods, uses static frameworks for both push providers, and extends Fastlane/Xcode project setup for widget bundle IDs per APN/FCM. AppDelegate routes opened URLs throughNativeLiveActivities.handleWidgetUrlbeforeRCTLinkingManagerso Live Activity taps record opened and deep links still work.Android registers
RideshareLiveNotificationCallbackbefore RN init to render the custom live notification type (including terminal end state) and adds a temporary Maven snapshot repo for pre-release SDK bits.Reviewed by Cursor Bugbot for commit 5ae1329. Bugbot is set up for automated code reviews on this repo. Configure here.