feat: KSPlayer as an option for iOS + other improvements (#1266)

This commit is contained in:
Fredrik Burmester
2026-01-03 13:05:50 +01:00
committed by GitHub
parent d1795c9df8
commit 74d86b5d12
191 changed files with 88479 additions and 2316 deletions

View File

@@ -0,0 +1,71 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'maven-publish'
group = 'expo.modules.sfplayer'
version = '1.0.0'
buildscript {
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
if (expoModulesCorePlugin.exists()) {
apply from: expoModulesCorePlugin
applyKotlinExpoModulesCorePlugin()
}
}
afterEvaluate {
publishing {
publications {
release(MavenPublication) {
from components.release
}
}
repositories {
maven {
url = mavenLocal().url
}
}
}
}
android {
compileSdkVersion safeExtGet("compileSdkVersion", 34)
def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
if (agpVersion.tokenize('.')[0].toInteger() < 8) {
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.majorVersion
}
}
namespace "expo.modules.sfplayer"
defaultConfig {
minSdkVersion safeExtGet("minSdkVersion", 23)
targetSdkVersion safeExtGet("targetSdkVersion", 34)
}
lintOptions {
abortOnError false
}
publishing {
singleVariant("release") {
withSourcesJar()
}
}
}
repositories {
mavenCentral()
}
dependencies {
implementation project(':expo-modules-core')
}
def safeExtGet(prop, fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}

View File

@@ -0,0 +1,2 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

View File

@@ -0,0 +1,120 @@
package expo.modules.sfplayer
import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition
class SfPlayerModule : Module() {
override fun definition() = ModuleDefinition {
Name("SfPlayer")
View(SfPlayerView::class) {
Prop("source") { view: SfPlayerView, source: Map<String, Any>? ->
// Android stub - KSPlayer is iOS only
}
AsyncFunction("play") { view: SfPlayerView ->
}
AsyncFunction("pause") { view: SfPlayerView ->
}
AsyncFunction("seekTo") { view: SfPlayerView, position: Double ->
}
AsyncFunction("seekBy") { view: SfPlayerView, offset: Double ->
}
AsyncFunction("setSpeed") { view: SfPlayerView, speed: Double ->
}
AsyncFunction("getSpeed") { view: SfPlayerView ->
1.0
}
AsyncFunction("isPaused") { view: SfPlayerView ->
true
}
AsyncFunction("getCurrentPosition") { view: SfPlayerView ->
0.0
}
AsyncFunction("getDuration") { view: SfPlayerView ->
0.0
}
AsyncFunction("startPictureInPicture") { view: SfPlayerView ->
}
AsyncFunction("stopPictureInPicture") { view: SfPlayerView ->
}
AsyncFunction("isPictureInPictureSupported") { view: SfPlayerView ->
false
}
AsyncFunction("isPictureInPictureActive") { view: SfPlayerView ->
false
}
AsyncFunction("getSubtitleTracks") { view: SfPlayerView ->
emptyList<Map<String, Any>>()
}
AsyncFunction("setSubtitleTrack") { view: SfPlayerView, trackId: Int ->
}
AsyncFunction("disableSubtitles") { view: SfPlayerView ->
}
AsyncFunction("getCurrentSubtitleTrack") { view: SfPlayerView ->
0
}
AsyncFunction("addSubtitleFile") { view: SfPlayerView, url: String, select: Boolean ->
}
AsyncFunction("setSubtitlePosition") { view: SfPlayerView, position: Int ->
}
AsyncFunction("setSubtitleScale") { view: SfPlayerView, scale: Double ->
}
AsyncFunction("setSubtitleMarginY") { view: SfPlayerView, margin: Int ->
}
AsyncFunction("setSubtitleAlignX") { view: SfPlayerView, alignment: String ->
}
AsyncFunction("setSubtitleAlignY") { view: SfPlayerView, alignment: String ->
}
AsyncFunction("setSubtitleFontSize") { view: SfPlayerView, size: Int ->
}
AsyncFunction("getAudioTracks") { view: SfPlayerView ->
emptyList<Map<String, Any>>()
}
AsyncFunction("setAudioTrack") { view: SfPlayerView, trackId: Int ->
}
AsyncFunction("getCurrentAudioTrack") { view: SfPlayerView ->
0
}
AsyncFunction("setVideoZoomToFill") { view: SfPlayerView, enabled: Boolean ->
}
AsyncFunction("getVideoZoomToFill") { view: SfPlayerView ->
false
}
AsyncFunction("setAutoPipEnabled") { view: SfPlayerView, enabled: Boolean ->
}
Events("onLoad", "onPlaybackStateChange", "onProgress", "onError", "onTracksReady", "onPictureInPictureChange")
}
}
}

View File

@@ -0,0 +1,29 @@
package expo.modules.sfplayer
import android.content.Context
import android.view.View
import android.widget.FrameLayout
import expo.modules.kotlin.AppContext
import expo.modules.kotlin.views.ExpoView
class SfPlayerView(context: Context, appContext: AppContext) : ExpoView(context, appContext) {
private val placeholder: View = View(context).apply {
setBackgroundColor(android.graphics.Color.BLACK)
layoutParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT
)
}
init {
addView(placeholder)
}
}