feat(live-update): integrate Ionic Live Update Provider SDK#818
Open
feat(live-update): integrate Ionic Live Update Provider SDK#818
Conversation
Adds optional integration with the Ionic Live Update Provider SDK (`io.ionic:liveupdateprovider` / `pod 'LiveUpdateProvider'`) so the plugin can register itself as a Capawesome provider for Federated Capacitor and Ionic Portals. The SDK is an optional native dependency on both platforms: - Android: `compileOnly` by default; opt in via the `capawesomeCapacitorLiveUpdateIncludeIonicProvider` Gradle property. - iOS CocoaPods: new `IonicProvider` subspec adds the `LiveUpdateProvider` pod and the `CAPAWESOME_INCLUDE_IONIC_PROVIDER` compile flag. - iOS SPM: new `IonicProvider` package trait wires the dependency and the same compile flag conditionally. Provider mode keeps its own bundle pointer scoped by `managerKey` and never touches the standalone `currentBundleId` / `nextBundleId` state.
@capawesome/capacitor-age-signals
@capawesome-team/capacitor-android-battery-optimization
@capawesome/capacitor-android-dark-mode-support
@capawesome/capacitor-android-edge-to-edge-support
@capawesome-team/capacitor-android-foreground-service
@capawesome/capacitor-app-review
@capawesome/capacitor-app-shortcuts
@capawesome/capacitor-app-update
@capawesome/capacitor-apple-sign-in
@capawesome/capacitor-asset-manager
@capawesome/capacitor-background-task
@capawesome/capacitor-badge
@capawesome/capacitor-cloudinary
@capawesome-team/capacitor-datetime-picker
@capawesome-team/capacitor-file-opener
@capawesome/capacitor-file-picker
@capawesome/capacitor-google-sign-in
@capawesome/capacitor-libsql
@capawesome/capacitor-live-update
@capawesome/capacitor-managed-configurations
@capawesome/capacitor-photo-editor
@capawesome/capacitor-pixlive
@capawesome/capacitor-posthog
@capawesome/capacitor-realtimekit
@capawesome/capacitor-screen-orientation
@capawesome/capacitor-screenshot
@capawesome/capacitor-square-mobile-payments
@capawesome/capacitor-superwall
@capawesome/capacitor-torch
commit: |
Contributor
There was a problem hiding this comment.
Pull request overview
Adds optional integration with the Ionic Live Update Provider SDK so @capawesome/capacitor-live-update can act as a Capawesome provider (providerId = "capawesome") for Federated Capacitor and Ionic Portals, while keeping the SDK out of builds unless explicitly enabled.
Changes:
- Adds optional Ionic Provider SDK wiring for Android (Gradle flag), iOS (CocoaPods subspec + SPM trait), and registers the provider on plugin load.
- Implements provider + manager on Android and iOS, including managerKey-scoped persisted “latest bundle” pointers isolated from the standalone plugin state.
- Adds per-call
appIdoverride plumbing and additional getters for fetch results.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/live-update/README.md | Documents opt-in steps + provider config/usage for Portals and Federated Capacitor. |
| packages/live-update/Package.swift | Adds SPM trait, conditional product dependency, and compile define for provider build. |
| packages/live-update/ios/Plugin/Providers/Ionic/LiveUpdateIonicProvider.swift | iOS provider wrapper (trait-gated). |
| packages/live-update/ios/Plugin/Providers/Ionic/LiveUpdateIonicManager.swift | iOS manager implementation + managerKey-scoped persistence (trait-gated). |
| packages/live-update/ios/Plugin/LiveUpdatePlugin.swift | Registers the provider with LiveUpdateProviderRegistry when enabled. |
| packages/live-update/ios/Plugin/LiveUpdate.swift | Adds bundle-directory helper and supports per-call appId override for latest-bundle fetch. |
| packages/live-update/ios/Plugin/Classes/Results/FetchLatestBundleResult.swift | Adds getters for provider/manager usage. |
| packages/live-update/ios/Plugin/Classes/Options/FetchLatestBundleOptions.swift | Adds optional per-call appId. |
| packages/live-update/ios/Plugin.xcodeproj/project.pbxproj | Adds new provider source files to the Xcode project. |
| packages/live-update/CapawesomeCapacitorLiveUpdate.podspec | Introduces Default + IonicProvider subspecs with a Swift compile flag. |
| packages/live-update/android/src/main/java/.../providers/ionic/LiveUpdateIonicProviderRegistration.java | Android registration helper for the optional SDK. |
| packages/live-update/android/src/main/java/.../providers/ionic/LiveUpdateIonicProvider.java | Android provider implementation. |
| packages/live-update/android/src/main/java/.../providers/ionic/LiveUpdateIonicManager.java | Android manager implementation + managerKey-scoped persistence. |
| packages/live-update/android/src/main/java/.../LiveUpdatePlugin.java | Hooks registration into plugin load. |
| packages/live-update/android/src/main/java/.../LiveUpdate.java | Adds bundle-directory helper and supports per-call appId override for latest-bundle fetch. |
| packages/live-update/android/src/main/java/.../classes/results/FetchLatestBundleResult.java | Adds getters for provider/manager usage. |
| packages/live-update/android/src/main/java/.../classes/options/FetchLatestBundleOptions.java | Adds optional per-call appId. |
| packages/live-update/android/build.gradle | Adds optional dependency wiring (implementation vs compileOnly) controlled by a Gradle property. |
| .changeset/tall-doors-clean.md | Declares a minor version bump for the package. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Adds a new sibling example app under `packages/live-update/example-ionic-portals`
that exercises the Ionic Live Update Provider SDK integration end-to-end without
requiring a real Federated Capacitor or Portals host.
The app opts into the integration on both platforms:
- Android: `capawesomeCapacitorLiveUpdateIncludeIonicProvider = true` in
`variables.gradle`.
- iOS: `pod 'CapawesomeCapacitorLiveUpdate/IonicProvider'` in the Podfile.
It ships a small custom Capacitor plugin (`IonicProviderTest`) implemented
natively in Java and Swift that exposes the SDK to JavaScript:
- `isProviderRegistered()` — confirms the provider is in
`LiveUpdateProviderRegistry`.
- `getLatestAppDirectory({ managerKey, appId?, channel? })` — constructs a
manager and returns its restored `latestAppDirectory` without syncing.
- `syncManager({ managerKey, appId?, channel? })` — full sync; returns the
new `latestAppDirectory` and any `FederatedCapacitorSyncResult.metadata`.
The web UI provides input fields for the per-manager config plus three
buttons backed by these methods, with a log pane for results.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds optional integration with the Ionic Live Update Provider SDK so that
@capawesome/capacitor-live-updatecan serve as a Capawesome provider for Federated Capacitor and Ionic Portals apps. The plugin registers itself withLiveUpdateProviderRegistryunder the provider idcapawesomewhenever the optional native dependency is present.The Ionic SDK is wired as an optional native dependency on every build system, so consumers who don't need it pay zero install footprint.
What's included
Optional native dependency wiring
capawesomeCapacitorLiveUpdateIncludeIonicProviderproject property (defaultfalse). Whentrue,io.ionic:liveupdateprovideris pulled in viaimplementation; otherwise it'scompileOnlyand never bundled into the consumer APK. A runtimeClass.forNamereflection check guards registration so the plugin never touches the SDK when it's absent.IonicProvidersubspec on top of the newDefaultsubspec. TheIonicProvidersubspec addspod 'LiveUpdateProvider', '0.1.0-alpha.2'and setsOTHER_SWIFT_FLAGS = -DCAPAWESOME_INCLUDE_IONIC_PROVIDERto compile in the provider classes.6.1and added anIonicProviderpackage trait that conditionally pulls in the SDK and conditionally definesCAPAWESOME_INCLUDE_IONIC_PROVIDER. Requires Capacitor CLI 8.3.0+ and Xcode 16.3+.Provider implementation
providers/ionic/with three Java classes:LiveUpdateIonicProvider— implements the SDK'sLiveUpdateProviderfactory.LiveUpdateIonicManager— implementsLiveUpdateProviderManager, scoped permanagerKeyso multiple shells can persist their own state.LiveUpdateIonicProviderRegistration— reflection-gated registration helper invoked fromLiveUpdatePlugin.load().Providers/Ionic/group withLiveUpdateIonicProvider.swiftandLiveUpdateIonicManager.swift, both wrapped in#if CAPAWESOME_INCLUDE_IONIC_PROVIDER. Registration happens inline (also gated) inLiveUpdatePlugin.swift load().Plumbing changes
LiveUpdate.{java,swift}: new publicgetBundleDirectory(bundleId)helper.FetchLatestBundleOptions.{java,swift}: new optional per-callappIdoverride so each manager can target a different Capawesome Cloud app without touching global preferences.fetchLatestBundleInternal(Java) /fetchLatestBundle(Swift) now honor it.FetchLatestBundleResult.{java,swift}: getters added (the classes previously only exposedtoJSObject).State isolation
Provider-mode managers keep their own bundle pointer in a separate
SharedPreferencesfile (Android) /UserDefaultskey (iOS) namespaced bymanagerKey. They never touch the standalone plugin'scurrentBundleId/nextBundleIdstate, so standalone JS sync and provider mode can coexist without interfering.Provider config (V1)
The provider's
createManager(config)accepts a minimal map:managerKeyappIdappIdfromcapacitor.config.json.channeldefaultChannel.All other settings come from the plugin-wide capacitor config.
customIdstays a global per-device value; consumers set it via the existingLiveUpdate.setCustomId({...})JS API.Documentation
Deferred (follow-ups)
deleteBundleIfUnusedhelper) — V1 leaks previous bundles to disk on each sync; matches the reference mock plugin behavior.serverDomain,publicKey,httpTimeout, etc.consumer-rules.pro(none needed yet — Android verify passed without them).Test plan
npm run verify(iOS + Android + Web) passes locally inpackages/live-update.liveUpdateConfig: { providerId: "capawesome", providerConfig: { managerKey, appId, channel } }, confirmLiveUpdateProviderRegistry.resolve("capawesome")returns the provider, trigger sync, and verifylatestAppDirectoryupdates and FedCap loads the new bundle.io.ionicout of the consumer APK (./gradlew :app:dependencies).IonicProviderCocoaPods subspec compiles with-DCAPAWESOME_INCLUDE_IONIC_PROVIDERset and pulls in theLiveUpdateProviderpod.