Distribute Kotlin Library
Release a library using the plugin
We can distribute to other users a Kotlin library using native or third-party dependency, some requirements are necessary for Apple targets.
Requirement
The user must :
- add the same native dependency used by the Kotlin library to his Xcode project.
- use the same version as the library use.
It will fix issues with linking, missing resources, App Store compliance, and more.
Note
The user doesn't have access to the Kotlin library source code, which is great!
Example
A Compose Multiplatform Component library using a native video player.
commonMain/kotlin/KmpPlayer.kt
@Composable
public expect fun KmpPlayer(modifier: Modifier = Modifier, url: String)
Android
For Android, it uses Exoplyer.
Gradle
library/build.gradle.kts
androidMain.dependencies {
implementation(libs.media3.exoplayer)
implementation(libs.media3.exoplayer.dash)
implementation(libs.media3.ui)
}
AndroidMain
androidMain/kotlin/KmpPlayer.kt
@Composable
public actual fun KmpPlayer(modifier: Modifier, url: String) {
val context = LocalContext.current
// Initialize ExoPlayer
val exoPlayer = ExoPlayer.Builder(context).build()
val mediaSource = remember(url) {
MediaItem.fromUri(url)
}
LaunchedEffect(url) {
exoPlayer.setMediaItem(mediaSource)
exoPlayer.prepare()
}
// Manage lifecycle events
DisposableEffect(Unit) {
onDispose {
exoPlayer.release()
}
}
AndroidView(
factory = { ctx ->
PlayerView(ctx).apply {
player = exoPlayer
}
},
modifier = modifier
)
}
iOS
For iOS, it uses KSPlayer, it's a pure Swift library.
Gradle
library/build.gradle.kts
swiftPackageConfig {
create("appleDeps") {
minIos = "13.0"
minMacos = "10.15"
minTvos = "13.0"
minWatchos = "2.0"
dependency(
SwiftDependency.Package.Remote.Branch(
url = URI("https://github.com/kingslay/KSPlayer"),
products = {
add("KSPlayer")
},
branch = "main"
),
)
}
}
Bridge
src/swift/appleDeps/MEPlayerController.swift
import Foundation
import KSPlayer
@objcMembers public class MEPlayerController: NSObject {
private let player = IOSVideoPlayerView()
override init() {
super.init()
KSOptions.secondPlayerType = KSMEPlayer.self
player.delegate = self
player.autoresizingMask = [.flexibleWidth, .flexibleHeight]
player.contentMode = .scaleAspectFill
}
public func setMediaItem(videoUrl: URL) {
player.set(
url: videoUrl,
options: KSOptions()
)
}
public var playerView: NSObject {
player
}
public func releasePlayer() {
player.resetPlayer()
player.removeFromSuperview()
}
}
IOSMain
iosMain/kotlin/KmpPlayer.kt
import appleDeps.MEPlayerController
@Composable
public actual fun KmpPlayer(modifier: Modifier, url: String) {
val playerController = MEPlayerController()
val mediaSource = remember(url) {
NSURL.URLWithString(url)
}
LaunchedEffect(url) {
if (mediaSource == null) {
throw Exception("Bad input URL")
}
playerController.setMediaItemWithVideoUrl(videoUrl = mediaSource)
}
DisposableEffect(Unit) {
onDispose {
playerController.releasePlayer()
}
}
UIKitView(
factory = {
playerController.playerView() as UIView
},
modifier = modifier,
update = {
}
)
}
Requirement
The setup guide of your library must contain the rule that KSPlayer package must be added to his Xcode project with the explicit version.
Sample
The sample is available.
- Run the command
./gradlew publishToMavenLocal --no-configuration-cache
on the repository root. - Open the project
sampleApp
and test the application