Skip to content

feat(live-update): integrate Ionic Live Update Provider SDK - #818

Open
robingenz wants to merge 12 commits into
mainfrom
feat/live-update-ionic-provider
Open

feat(live-update): integrate Ionic Live Update Provider SDK#818
robingenz wants to merge 12 commits into
mainfrom
feat/live-update-ionic-provider

Conversation

@robingenz

@robingenz robingenz commented Apr 9, 2026

Copy link
Copy Markdown
Member

Summary

Adds integration with the Ionic Live Update Provider SDK (1.0.0) so that @capawesome/capacitor-live-update can serve as a live update provider for Federated Capacitor and Ionic Portals apps.

Under the 1.0.0 contract there is no registry and no provider id: Federated Capacitor resolves providers by their Capacitor plugin name (LiveUpdate on both platforms) and calls createManager(...) natively on the resolved plugin instance.

Originally built against 0.1.0-alpha.2 (registry-based); reworked for the 1.0.0 contract after the SDK's stable release.

Optional dependency design

The SDK integration is optional on both platforms, in different ways:

  • Android — zero configuration. The SDK is compileOnly; Federated Capacitor and Ionic Portals bring it transitively at runtime. The plugin deliberately does not implement the SDK's LiveUpdateProvider interface (ART resolves superinterfaces eagerly at class-definition time, which would crash the plugin whenever the SDK is absent). Instead, LiveUpdatePlugin.createManager(Context, Map) matches the interface's exact signature, and Federated Capacitor invokes it via its reflection fallback when the cast fails (added by the Ionic team based on our feedback on 1.0.0). Method references resolve lazily, so the plugin class loads fine without the SDK, and the provider classes are only loaded when a host actually calls createManager. A consumer-rules.pro (-dontwarn io.ionic.liveupdateprovider.**) keeps R8 full mode happy for apps without the SDK. Unlike the alpha design, there is no opt-in Gradle property and no reflection gate on our side anymore.
  • iOS — build-time opt-in. The IonicProvider CocoaPods subspec / SPM package trait links the LiveUpdateProvider package and sets CAPAWESOME_INCLUDE_IONIC_PROVIDER, which compiles in the #if-gated conformance extension and manager. The SPM trait requires swift-tools 6.1 (Capacitor CLI 8.3.0+, Xcode 16.3+).

What's included

Dependency wiring

  • Android (Gradle)compileOnly "io.ionic:liveupdateprovider:$ionicLiveUpdateProviderVersion" (default 1.0.0, documented in the README variables section) + consumer ProGuard rules. The module applies the Kotlin plugin.
  • iOS (CocoaPods)Default (no-op) and IonicProvider subspecs; the latter adds LiveUpdateProvider, '~> 1.0.0' and the compile flag.
  • iOS (SPM)IonicProvider package trait that conditionally pulls in the SDK and defines the flag.

Provider implementation

  • AndroidLiveUpdatePlugin.createManager(context, configuration) (reflection contract, see above) returns providers/ionic/LiveUpdateIonicManager.kt, a Kotlin implementation of ProviderManager: the suspending sync() bridges the plugin's callback-based fetchLatestBundle/downloadBundle via stdlib kotlin.coroutines.suspendCoroutineno kotlinx-coroutines dependency (the underlying calls are async OkHttp enqueue).
  • iOSLiveUpdatePlugin conforms to LiveUpdateProvider via a #if-gated extension (Providers/Ionic/LiveUpdatePlugin+LiveUpdateProvider.swift); LiveUpdateIonicManager conforms to ProviderManager with sync() async throws -> (any ProviderSyncResult)?. The plugin's own Xcode project sets the compile flag so npm run verify:ios compiles the gated code.
  • Portals direct manager construction — Portals 0.14.0 attaches a ProviderManager directly to the Portal configuration (liveUpdateSource: .provider(manager:) on iOS, setLiveUpdateProviderManager(...) on Android). The manager therefore has a public constructor/initializer taking only (context,) configuration, backed by a headless LiveUpdate core (injected Context, nullable plugin, WebView/bridge operations and plugin events degrade gracefully). appId/channel come from the configuration map; other settings use defaults.
  • sync() semantics per the 1.0.0 contract: returns nil/null when no update is available (nothing to report), a MetadataSyncResult (metadata: bundleId, channel, customProperties) when a bundle was applied, and propagates failures unwrapped. createManager is not exposed as a bridged plugin method — Federated Capacitor invokes it natively.

Plumbing changes

  • LiveUpdate.{java,swift}: new public getBundleDirectory(bundleId) helper.
  • FetchLatestBundleOptions.{java,swift}: new optional per-call appId override so each manager can target a different Capawesome Cloud app without touching global preferences.
  • FetchLatestBundleResult.{java,swift}: getters added (the classes previously only exposed toJSObject).

State isolation

Provider-mode managers keep their own bundle pointer in a separate SharedPreferences file (Android) / UserDefaults key (iOS) namespaced by managerKey. They never touch the standalone plugin's currentBundleId / nextBundleId state, so standalone JS sync and provider mode can coexist without interfering.

Provider configuration (V1)

createManager(configuration) accepts a minimal map:

Key Type Required Notes
managerKey string Yes Scopes per-manager persisted state.
appId string No Falls back to plugin-wide appId from capacitor.config.json.
channel string No Falls back to plugin-wide defaultChannel.

The Federated Capacitor side selects the provider by plugin name and passes this map (config shape confirmed by the Ionic team):

liveUpdateConfig: {
  pluginName: 'LiveUpdate',
  config: { managerKey: 'my-shell', appId: '...', channel: 'production' },
  autoUpdateMethod: 'none',
}

All other settings come from the plugin-wide capacitor config. customId stays a global per-device value; consumers set it via the existing LiveUpdate.setCustomId({...}) JS API.

Documentation

  • README: feature bullets, $ionicLiveUpdateProviderVersion variable, and a pointer to the full setup guide.
  • docs/ionic-live-update-provider-sdk-integration.md rewritten for 1.0.0: resolution by plugin name, zero-config Android, iOS opt-in (subspec/trait), confirmed FedCap config, simplified native-host (Portals) wiring. The Ionic Portals usage section has concrete direct-construction snippets for the Portals 0.14.0 API on both platforms.

Example app

example-ionic-provider is a plain Capacitor app with a small IonicProviderTest plugin that exercises the provider contract end-to-end without a FedCap/Portals host. It resolves the provider exactly like Federated Capacitor does: bridge.getPlugin("LiveUpdate"), cast to LiveUpdateProvider first, then the reflection fallback on createManager(Context, Map) (the path this plugin actually takes on Android). The example app declares the SDK itself since the plugin's dependency is compile-only.

Deferred (follow-ups)

  • Bundle pruning in provider mode (deleteBundleIfUnused helper) — V1 leaks previous bundles to disk on each sync; matches the reference mock plugin behavior.
  • Per-manager overrides for serverDomain, publicKey, httpTimeout, etc.

Test plan

  • npm run verify (iOS + Android + Web) passes locally in packages/live-update; iOS verified with CAPAWESOME_INCLUDE_IONIC_PROVIDER active (gated code compiled).
  • example-ionic-provider Android app builds end-to-end (assembleDebug), including the reflection-based test plugin.
  • Smoke test on device with the example app: isProviderAvailable (exercises the reflection lookup), syncManager, state restoration across relaunch, managerKey isolation.
  • Smoke test in a real Federated Capacitor app with the 1.0.0-based FedCap release (out 2026-07-13): resolve by pluginName: 'LiveUpdate' via the reflection fallback, trigger sync, verify latestAppDirectory updates and metadata reaches JS.
  • Confirm opting out on Android leaves io.ionic out of the consumer APK and R8 full mode passes with the shipped consumer rules.
  • Smoke test in an Ionic Portals app with Portals 0.14.0 and a directly constructed manager (ionic-portals-ecommerce-demo migrated and verified on device).

🤖 Generated with Claude Code

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.
Copilot AI review requested due to automatic review settings April 9, 2026 07:09
@pkg-pr-new

pkg-pr-new Bot commented Apr 9, 2026

Copy link
Copy Markdown

Open in StackBlitz

@capawesome/capacitor-accessibility-preferences

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-accessibility-preferences@818

@capawesome/capacitor-action-sheet

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-action-sheet@818

@capawesome/capacitor-age-signals

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-age-signals@818

@capawesome/capacitor-alarm

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-alarm@818

@capawesome-team/capacitor-android-battery-optimization

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome-team/capacitor-android-battery-optimization@818

@capawesome/capacitor-android-dark-mode-support

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-android-dark-mode-support@818

@capawesome/capacitor-android-edge-to-edge-support

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-android-edge-to-edge-support@818

@capawesome-team/capacitor-android-foreground-service

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome-team/capacitor-android-foreground-service@818

@capawesome/capacitor-android-intent-launcher

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-android-intent-launcher@818

@capawesome/capacitor-android-sms-retriever

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-android-sms-retriever@818

@capawesome/capacitor-app-icon

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-app-icon@818

@capawesome/capacitor-app-integrity

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-app-integrity@818

@capawesome/capacitor-app-language

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-app-language@818

@capawesome/capacitor-app-launcher

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-app-launcher@818

@capawesome/capacitor-app-review

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-app-review@818

@capawesome/capacitor-app-shortcuts

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-app-shortcuts@818

@capawesome/capacitor-app-tracking-transparency

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-app-tracking-transparency@818

@capawesome/capacitor-app-update

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-app-update@818

@capawesome/capacitor-apple-sign-in

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-apple-sign-in@818

@capawesome/capacitor-asset-manager

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-asset-manager@818

@capawesome/capacitor-audio-session

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-audio-session@818

@capawesome/capacitor-background-task

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-background-task@818

@capawesome/capacitor-badge

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-badge@818

@capawesome/capacitor-battery

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-battery@818

@capawesome/capacitor-clipboard

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-clipboard@818

@capawesome/capacitor-cloudinary

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-cloudinary@818

@capawesome/capacitor-compass

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-compass@818

@capawesome/capacitor-crisp

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-crisp@818

@capawesome-team/capacitor-datetime-picker

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome-team/capacitor-datetime-picker@818

@capawesome/capacitor-device-info

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-device-info@818

@capawesome/capacitor-dialog

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-dialog@818

@capawesome/capacitor-exif

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-exif@818

@capawesome/capacitor-facebook-sign-in

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-facebook-sign-in@818

@capawesome-team/capacitor-file-opener

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome-team/capacitor-file-opener@818

@capawesome/capacitor-file-picker

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-file-picker@818

@capawesome/capacitor-formbricks

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-formbricks@818

@capawesome/capacitor-google-sign-in

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-google-sign-in@818

@capawesome/capacitor-grafana-faro

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-grafana-faro@818

@capawesome/capacitor-gyroscope

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-gyroscope@818

@capawesome/capacitor-haptics

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-haptics@818

@capawesome/capacitor-home-indicator

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-home-indicator@818

@capawesome/capacitor-in-app-browser

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-in-app-browser@818

@capawesome/capacitor-install-referrer

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-install-referrer@818

@capawesome/capacitor-intercom

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-intercom@818

@capawesome/capacitor-intune

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-intune@818

@capawesome/capacitor-keep-awake

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-keep-awake@818

@capawesome/capacitor-libsql

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-libsql@818

@capawesome/capacitor-light-sensor

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-light-sensor@818

@capawesome/capacitor-live-update

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-live-update@818

@capawesome/capacitor-localization

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-localization@818

@capawesome/capacitor-mail-composer

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-mail-composer@818

@capawesome/capacitor-managed-configurations

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-managed-configurations@818

@capawesome/capacitor-maps-launcher

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-maps-launcher@818

@capawesome/capacitor-navigation-bar

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-navigation-bar@818

@capawesome/capacitor-network

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-network@818

@capawesome/capacitor-nodejs

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-nodejs@818

@capawesome/capacitor-passkeys

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-passkeys@818

@capawesome/capacitor-password-autofill

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-password-autofill@818

@capawesome/capacitor-pdf-generator

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-pdf-generator@818

@capawesome/capacitor-pdf-viewer

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-pdf-viewer@818

@capawesome/capacitor-permissions

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-permissions@818

@capawesome/capacitor-phone-dialer

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-phone-dialer@818

@capawesome/capacitor-photo-editor

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-photo-editor@818

@capawesome/capacitor-photo-manipulator

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-photo-manipulator@818

@capawesome/capacitor-pixlive

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-pixlive@818

@capawesome/capacitor-posthog

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-posthog@818

@capawesome/capacitor-privacy-screen

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-privacy-screen@818

@capawesome/capacitor-proximity-sensor

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-proximity-sensor@818

@capawesome/capacitor-realtimekit

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-realtimekit@818

@capawesome/capacitor-root-detection

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-root-detection@818

@capawesome/capacitor-screen-brightness

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-screen-brightness@818

@capawesome/capacitor-screen-orientation

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-screen-orientation@818

@capawesome/capacitor-screen-reader

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-screen-reader@818

@capawesome/capacitor-screenshot

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-screenshot@818

@capawesome/capacitor-settings-launcher

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-settings-launcher@818

@capawesome/capacitor-shake

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-shake@818

@capawesome/capacitor-silent-mode

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-silent-mode@818

@capawesome/capacitor-sim

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-sim@818

@capawesome/capacitor-sms-composer

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-sms-composer@818

@capawesome/capacitor-square-mobile-payments

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-square-mobile-payments@818

@capawesome/capacitor-superwall

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-superwall@818

@capawesome/capacitor-system-webview

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-system-webview@818

@capawesome/capacitor-text-interaction

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-text-interaction@818

@capawesome/capacitor-text-zoom

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-text-zoom@818

@capawesome/capacitor-thermal-state

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-thermal-state@818

@capawesome/capacitor-toast

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-toast@818

@capawesome/capacitor-torch

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-torch@818

@capawesome/capacitor-volume

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-volume@818

@capawesome/capacitor-wallet

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-wallet@818

@capawesome/capacitor-youtube-player

npm i https://pkg.pr.new/capawesome-team/capacitor-plugins/@capawesome/capacitor-youtube-player@818

commit: f9cc1d1

Copilot AI left a comment

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.

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 appId override 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.

Comment thread packages/live-update/README.md Outdated
Comment thread packages/live-update/ios/Plugin/LiveUpdate.swift
Comment thread packages/live-update/ios/Plugin/Providers/Ionic/LiveUpdateIonicManager.swift Outdated
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.
@robingenz

Copy link
Copy Markdown
Member Author
npm i @capawesome/capacitor-live-update@8.2.1-dev.70823ec8.1778138208

@robingenz robingenz self-assigned this Jul 10, 2026
robingenz and others added 4 commits July 10, 2026 09:41
… to 1.0.0

The 1.0.0 SDK removes the provider registry: Federated Capacitor now
resolves providers by Capacitor plugin name, so the plugin class itself
implements the LiveUpdateProvider contract. Since ART resolves
superinterfaces at class-definition time, the SDK can no longer be an
optional (compileOnly) dependency on Android — it is now a regular
dependency on both platforms.

- Android: LiveUpdatePlugin implements LiveUpdateProvider; manager
  rewritten in Kotlin (suspend sync() bridged via stdlib
  suspendCoroutine, no kotlinx-coroutines needed); registry and
  reflection gate removed; opt-in Gradle property removed.
- iOS: conformance via extension; registry registration removed;
  subspecs, SPM trait, and CAPAWESOME_INCLUDE_IONIC_PROVIDER guards
  removed; Package.swift back to swift-tools 5.9.
- sync() returns nil/null when no update is available, a
  MetadataSyncResult on success, and propagates errors unwrapped.
- Docs and example app updated to the new contract.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Federated Capacitor now falls back to reflection when the resolved plugin
does not conform to LiveUpdateProvider, so the SDK no longer needs to be
a hard dependency:

- Android: SDK back to compileOnly with zero configuration — the plugin
  skips the interface conformance and exposes createManager with the
  exact interface signature for FedCap's reflection fallback. Hosts
  (FedCap/Portals) provide the SDK at runtime. Consumer proguard rules
  suppress R8 missing-class errors for apps without it.
- iOS: opt-in restored via the IonicProvider CocoaPods subspec and SPM
  package trait with CAPAWESOME_INCLUDE_IONIC_PROVIDER guards. The
  plugin's own Xcode project now sets the flag so verify compiles the
  gated provider code.
- Docs: confirmed Federated Capacitor config shape (pluginName/config/
  autoUpdateMethod); Android install is now zero-config; iOS opt-in
  instructions restored.
- Example app resolves the provider like FedCap does: cast first, then
  reflection on createManager(Context, Map).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…onic Portals

Ionic Portals 0.14.0 attaches a ProviderManager directly to the Portal
configuration (liveUpdateSource: .provider(manager:) on iOS,
setLiveUpdateProviderManager(...) on Android) — there is no resolution
step, so hosts must be able to construct the manager without a loaded
Capacitor plugin:

- LiveUpdate core is now headless-capable: the Android Context is
  injected instead of pulled from the plugin, the plugin reference is
  nullable on both platforms, and WebView/bridge operations (server
  path reads/writes, reload) and plugin events degrade gracefully
  without one.
- LiveUpdateIonicManager gains a public constructor/initializer taking
  only (context,) configuration, backed by a headless LiveUpdate with
  default config; appId and channel come from the configuration map.
- Docs: Portals usage section now has concrete snippets for the
  Portals 0.14.0 API on both platforms.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants