Skip to content

feat(sample): Live Activities demo screens - #618

Merged
mahmoud-elmorabea merged 13 commits into
live-activities-sdkfrom
live-activities-sample
Jul 30, 2026
Merged

feat(sample): Live Activities demo screens#618
mahmoud-elmorabea merged 13 commits into
live-activities-sdkfrom
live-activities-sample

Conversation

@mahmoud-elmorabea

@mahmoud-elmorabea mahmoud-elmorabea commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

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.liveActivities start/update/end for each template. Default SDK config now registers segment and countdown types and the rideshare customType. Home navigation links to the screen.

iOS adds a LiveActivityWidget extension (SDK built-in templates + app-owned RideshareLiveActivity SwiftUI), enables NSSupportsLiveActivities, wires the liveactivities pod 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 through NativeLiveActivities.handleWidgetUrl before RCTLinkingManager so Live Activity taps record opened and deep links still work.

Android registers RideshareLiveNotificationCallback before 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.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

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.


  • iOS FCM: 618.13.0 (29754175)
  • iOS APN: 618.13.0 (29754175)

@mahmoud-elmorabea mahmoud-elmorabea changed the title feat(live-activities): sample app demo screens + custom template feat(sample): Live Activities demo screens Jul 27, 2026
@mahmoud-elmorabea
mahmoud-elmorabea force-pushed the live-activities-sample branch 7 times, most recently from 88c39e1 to b183a6d Compare July 27, 2026 17:34
@mahmoud-elmorabea
mahmoud-elmorabea marked this pull request as ready for review July 28, 2026 06:31
@mahmoud-elmorabea
mahmoud-elmorabea requested a review from a team as a code owner July 28, 2026 06:31
} minimal: {
Image(systemName: "car.fill")
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

mahmoud-elmorabea and others added 12 commits July 28, 2026 14:05
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.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.

Comment thread example/ios/LiveActivityWidget/RideshareLiveActivity.swift
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.
@mahmoud-elmorabea
mahmoud-elmorabea merged commit 425e65a into live-activities-sdk Jul 30, 2026
18 checks passed
@mahmoud-elmorabea
mahmoud-elmorabea deleted the live-activities-sample branch July 30, 2026 08:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants