From a7d834a80a2b06cde46ba79232d90d2279cd0a7d Mon Sep 17 00:00:00 2001 From: Olivier Bouillet <62574056+freeboub@users.noreply.github.com> Date: Tue, 25 Jun 2024 13:20:12 +0200 Subject: [PATCH] feat(android): allow building exoplayer from source (#3932) * feat(android): allow to build from source code * fix(android): allow to build plugin from source --- android/build.gradle | 85 ++++++++++++++----- android/gradle.properties | 1 + docs/pages/other/debug.md | 35 ++++++++ examples/basic/android/app/build.gradle | 10 +++ examples/basic/android/build.gradle | 3 + examples/basic/android/settings.gradle | 4 + .../android/build.gradle | 10 ++- 7 files changed, 127 insertions(+), 21 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 1ba46ae4..81e11c04 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -43,6 +43,7 @@ def ExoplayerDependenciesList = [ "useExoplayerHls", "useExoplayerRtsp", ] +def media3_buildFromSource = safeExtGet('buildFromMedia3Source').toBoolean() ?: false def ExoplayerDependencies = ExoplayerDependenciesList.collectEntries { property -> [(property): safeExtGet(property)?.toBoolean() ?: false] @@ -52,14 +53,17 @@ ExoplayerDependenciesList.each { propertyName -> def propertyValue = ExoplayerDependencies[propertyName] println "$propertyName: $propertyValue" } +println "buildFromSource: $media3_buildFromSource" // This string is used to define build path. // As react native build output directory is react-native path of the module. // We need to force a new path on each configuration change. // If you add a new build parameter, please add the new value in this string -def configStringPath = ExoplayerDependencies.collect { property, value -> - property + value -}.join('').md5() +def configStringPath = ExoplayerDependencies + .collect { property, value -> property + value} + .join('') + .concat("buildFromSource:$media3_buildFromSource") + .md5() if (isNewArchitectureEnabled()) { apply plugin: "com.facebook.react" @@ -191,46 +195,87 @@ dependencies { implementation "androidx.activity:activity-ktx:$androidxActivity_version" // For media playback using ExoPlayer - implementation "androidx.media3:media3-exoplayer:$media3_version" + if (media3_buildFromSource) { + implementation(project(":media-lib-exoplayer")) + } else { + implementation "androidx.media3:media3-exoplayer:$media3_version" + } if (ExoplayerDependencies["useExoplayerSmoothStreaming"]) { // For Smooth Streaming playback support with ExoPlayer - implementation "androidx.media3:media3-exoplayer-smoothstreaming:$media3_version" + if (media3_buildFromSource) { + implementation(project(":media-lib-exoplayer-smoothstreaming")) + } else { + implementation "androidx.media3:media3-exoplayer-smoothstreaming:$media3_version" + } } if (ExoplayerDependencies["useExoplayerDash"]) { // For DASH playback support with ExoPlayer - implementation "androidx.media3:media3-exoplayer-dash:$media3_version" + if (media3_buildFromSource) { + implementation(project(":media-lib-exoplayer-dash")) + } else { + implementation "androidx.media3:media3-exoplayer-dash:$media3_version" + } } if (ExoplayerDependencies["useExoplayerHls"]) { - // For HLS playback support with ExoPlayer - implementation "androidx.media3:media3-exoplayer-hls:$media3_version" + // For HLS playback support with ExoPlayer + if (media3_buildFromSource) { + implementation(project(":media-lib-exoplayer-hls")) + } else { + implementation "androidx.media3:media3-exoplayer-hls:$media3_version" + } } // For RTSP playback support with ExoPlayer if (ExoplayerDependencies["useExoplayerRtsp"]) { - implementation "androidx.media3:media3-exoplayer-rtsp:$media3_version" + if (media3_buildFromSource) { + implementation(project(":media-lib-exoplayer-rtsp")) + } else { + implementation "androidx.media3:media3-exoplayer-rtsp:$media3_version" + } } // For ad insertion using the Interactive Media Ads SDK with ExoPlayer if (ExoplayerDependencies["useExoplayerIMA"]) { - implementation "androidx.media3:media3-exoplayer-ima:$media3_version" + if (media3_buildFromSource) { + implementation(project(":media-lib-exoplayer-ima")) + } else { + implementation "androidx.media3:media3-exoplayer-ima:$media3_version" + } } - // For loading data using the OkHttp network stack - implementation "androidx.media3:media3-datasource-okhttp:$media3_version" + if (media3_buildFromSource) { + // For loading data using the OkHttp network stack + implementation(project(":media-lib-datasource-okhttp")) - // For building media playback UIs - implementation "androidx.media3:media3-ui:$media3_version" + // For building media playback UIs + implementation(project(":media-lib-ui")) - // For exposing and controlling media sessions - implementation "androidx.media3:media3-session:$media3_version" + // For exposing and controlling media sessions + implementation(project(":media-lib-session")) - // Common functionality for loading data - implementation "androidx.media3:media3-datasource:$media3_version" - // Common functionality used across multiple media libraries - implementation "androidx.media3:media3-common:$media3_version" + // Common functionality for loading data + implementation(project(":media-lib-datasource")) + // Common functionality used across multiple media libraries + implementation(project(":media-lib-common")) + } else { + // For loading data using the OkHttp network stack + implementation "androidx.media3:media3-datasource-okhttp:$media3_version" + + // For building media playback UIs + implementation "androidx.media3:media3-ui:$media3_version" + + // For exposing and controlling media sessions + implementation "androidx.media3:media3-session:$media3_version" + + // Common functionality for loading data + implementation "androidx.media3:media3-datasource:$media3_version" + + // Common functionality used across multiple media libraries + implementation "androidx.media3:media3-common:$media3_version" + } implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" } diff --git a/android/gradle.properties b/android/gradle.properties index f19a0a19..32cd544d 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -12,3 +12,4 @@ RNVideo_useExoplayerDash=true RNVideo_useExoplayerHls=true RNVideo_androidxCoreVersion=1.9.0 RNVideo_androidxActivityVersion=1.7.0 +RNVideo_buildFromMedia3Source=false diff --git a/docs/pages/other/debug.md b/docs/pages/other/debug.md index 0cbaebf2..74c8bfd1 100644 --- a/docs/pages/other/debug.md +++ b/docs/pages/other/debug.md @@ -56,6 +56,41 @@ With these tool you should be able to analyze what is going on with network. You Then try to compare exchanges with previous tests you made. +## Debug media3: build from media3 source + +If you need to use a specific exoplayer version or patch default behavior, you may want to build from media3 source code. + +Building from media3 source is possible. You need to add 2 or 3 things in your app: + +### Configure player path + +You need to add following lines in settings.gradle to configure your media3 source path: + +```gradle +gradle.ext.androidxMediaModulePrefix = 'media-' +apply from: file("../../../../media3/core_settings.gradle") +```` + +Of course, you should replace with media3 source path. Be carefull, you need to use the same version (or version with compatible api) that the package support. + +### Enable building from source +In your build.gradle file, add following setting: + +```gradle +buildscript { + ext { + ... + buildFromMedia3Source = true + ... + } +} +``` + +### Desugaring +to be able to link you may also need to enable coreLibraryDesugaringEnabled in your app. + +See: https://developer.android.com/studio/write/java8-support?hl=fr#library-desugaring for more informations. + ## It's still not working You can try to open a ticket now ! diff --git a/examples/basic/android/app/build.gradle b/examples/basic/android/app/build.gradle index 124d86d3..fa4d074b 100644 --- a/examples/basic/android/app/build.gradle +++ b/examples/basic/android/app/build.gradle @@ -81,12 +81,20 @@ android { compileSdkVersion rootProject.ext.compileSdkVersion namespace "com.videoplayer" + + compileOptions { + // These options are necessary to be able to build fro source + coreLibraryDesugaringEnabled true + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 + } defaultConfig { applicationId "com.videoplayer" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 versionName "1.0" + multiDexEnabled true } signingConfigs { debug { @@ -147,6 +155,8 @@ dependencies { because("kotlin-stdlib-jdk8 is now a part of kotlin-stdlib") } } + // coreLibraryDesugaring is mandatory to be able to build exoplayer from source + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4' } apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) diff --git a/examples/basic/android/build.gradle b/examples/basic/android/build.gradle index 3838f933..92447666 100644 --- a/examples/basic/android/build.gradle +++ b/examples/basic/android/build.gradle @@ -16,6 +16,9 @@ buildscript { // useExoplayerSmoothStreaming = false // useExoplayerDash = false // useExoplayerHls = false + + // uncomment this line to be able to build from media3 source code + // buildFromMedia3Source = true } repositories { google() diff --git a/examples/basic/android/settings.gradle b/examples/basic/android/settings.gradle index bfb02b91..e91a2122 100644 --- a/examples/basic/android/settings.gradle +++ b/examples/basic/android/settings.gradle @@ -8,6 +8,10 @@ project (':react-native-video-plugin-sample').projectDir = new File(rootProject. include ':react-native-video' project (':react-native-video').projectDir = new File(rootProject.projectDir, '../../../android') +// uncomment these lines to be able to build from media3 source code +// gradle.ext.androidxMediaModulePrefix = 'media-' +// apply from: file("../../../../media3/core_settings.gradle") + includeBuild('../node_modules/@react-native/gradle-plugin') apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle") diff --git a/examples/react-native-video-plugin-sample/android/build.gradle b/examples/react-native-video-plugin-sample/android/build.gradle index 796511f6..8335c5e3 100644 --- a/examples/react-native-video-plugin-sample/android/build.gradle +++ b/examples/react-native-video-plugin-sample/android/build.gradle @@ -100,7 +100,15 @@ dependencies { //noinspection GradleDynamicVersion implementation "com.facebook.react:react-native:+" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation "androidx.media3:media3-exoplayer:$media3_version" + + def media3_buildFromSource = safeExtGet('buildFromMedia3Source')?.toBoolean() ?: false + if (media3_buildFromSource) { + implementation(project(":media-lib-exoplayer")) + implementation(project(":media-lib-exoplayer-dash")) + } else { + implementation "androidx.media3:media3-exoplayer:$media3_version" + implementation "androidx.media3:media3-exoplayer-dash:$media3_version" + } implementation project(':react-native-video') }