Files
LoveLiveMusicPlayerKMP/iosApp/README.md
2026-08-11 00:33:28 +08:00

3.6 KiB

iOS App (Xcode host)

Kotlin Multiplatform Compose UI runs inside a native iOS shell. Sources here are Xcode-ready scaffolding; building requires macOS + Xcode.

App Group migration

Old (Flutter) New (KMP)
group.com.zhushenwudi.lovelivemusicplayer group.top.zhushenwudi.llmp

Kotlin writes widget / PiP / CarPlay keys via WidgetDataWriter (shared/.../IosPlatformHooks.kt). Swift Widget + CarPlay read the same suite.

Build steps (macOS)

cd LoveLiveMusicPlayerKMP
./gradlew :composeApp:linkDebugFrameworkIosSimulatorArm64
# or iosArm64 for device
  1. Open Xcode → File → New → Project → App (or add targets to an existing workspace).
  2. Set bundle ID top.zhushenwudi.llmp (main app).
  3. Copy iosApp/iosApp/* into the app target; add WidgetExtension/* as a Widget Extension target (top.zhushenwudi.llmp.widget).
  4. Link the Gradle-produced ComposeApp.framework (and embedded Shared.framework if split).
  5. Signing: enable App Groups group.top.zhushenwudi.llmp on both app + widget targets (iosApp.entitlements, WidgetExtension.entitlements).
  6. CarPlay: entitlements include com.apple.developer.carplay-audio and com.apple.developer.playable-contentrequires Apple Developer approval before TestFlight/App Store CarPlay works.
  7. Add black.mp4 (minimal black video) to the app bundle for PiP — copy from Flutter ios/Runner if present, or generate a 1-frame H.264 clip.
  8. Copy widget image assets from Flutter ios/HomeWidgetExample/Assets.xcassets (logo, cd_white, cd_black, favorites).

Entry point:

MainViewControllerKt.MainViewController()  // ComposeApp framework

MainViewController.kt calls installIosPlatformServices() on startup.

Targets & layout

iosApp/
  iosApp/
    AppDelegate.swift          — lifecycle, widget shutdown, notification wiring
    SceneDelegate.swift        — UIWindow + PiP notification handlers
    ContentView.swift          — SwiftUI host for Compose UIViewController
    HostBridge.swift           — share sheet, deep links, widget/CarPlay → host
    Info.plist
    iosApp.entitlements
    CarPlay/CarPlaySceneDelegate.swift
    pip/                       — desktop lyric PiP (from Flutter Runner/pip)
  WidgetExtension/             — White/Black home widgets (from Flutter HomeWidgetExample)

Kotlin ↔ Swift bridge (remaining macOS work)

Feature Kotlin side Swift side Gap
Playback PlayerController.ios.kt AVPlayer + MPRemoteCommandCenter Done in Kotlin
Home widget data IosHomeWidgetController → UserDefaults Widget reads keys Wire widget tap → Kotlin player (export callback or observe llmpHostTogglePlay)
PiP lyrics IosDesktopLyricController posts notifications PipScreenManager Done via NotificationCenter
Share IosShareBridge posts llmpShareRequest HostBridge.presentShare Done
Deep link llmp:// IosDeepLinkHandler SceneDelegate + HostBridge Handle payload in Kotlin UI layer
CarPlay IosCarPlayHook.refreshCatalog() writes JSON CarPlaySceneDelegate Play/group/menu callbacks need Kotlin export

CarPlay note

CarPlaySceneDelegate reads carplay_* JSON from the App Group. Full parity with Flutter flutter_carplay needs exported Kotlin handlers for onPlay(musicId) — until then, NotificationCenter events (llmpHostCarPlayPlay, etc.) are posted for the host to forward.

Permissions

Add usage strings in Xcode as needed (camera for QR, photo library, etc.) — see Flutter ios/Runner/Info.plist for reference.