From 64e3191f73c828067094031a55e6868696b40a34 Mon Sep 17 00:00:00 2001 From: Krzysztof Moch Date: Tue, 16 Apr 2024 14:23:19 +0200 Subject: [PATCH] feat(android): allow to disable selected functionalities (#3681) * feat(android): add possibility do disable some of functionalities * create dump classes * remove dump files when functionalities are enabled * add docs * enable all functionalities in example * throw error when trying to use disabled functionality * update docs --- android/build.gradle | 75 +++++++++++++++---- android/gradle.properties | 6 +- .../exoplayer/dash/DashMediaSource.java | 36 +++++++++ .../media3/exoplayer/dash/DashUtil.java | 12 +++ .../dash/DefaultDashChunkSource.java | 10 +++ .../dash/manifest/AdaptationSet.java | 13 ++++ .../exoplayer/dash/manifest/DashManifest.java | 15 ++++ .../exoplayer/dash/manifest/Period.java | 7 ++ .../dash/manifest/Representation.java | 12 +++ .../media3/exoplayer/hls/HlsMediaSource.java | 34 +++++++++ .../exoplayer/rtsp/RtspMediaSource.java | 34 +++++++++ .../smoothstreaming/DefaultSsChunkSource.java | 34 +++++++++ .../smoothstreaming/SsMediaSource.java | 34 +++++++++ .../exoplayer/ReactExoplayerView.java | 21 ++++++ docs/pages/installation.md | 20 ++++- examples/basic/android/build.gradle | 8 +- 16 files changed, 352 insertions(+), 19 deletions(-) create mode 100644 android/src/main/java/androidx/media3/exoplayer/dash/DashMediaSource.java create mode 100644 android/src/main/java/androidx/media3/exoplayer/dash/DashUtil.java create mode 100644 android/src/main/java/androidx/media3/exoplayer/dash/DefaultDashChunkSource.java create mode 100644 android/src/main/java/androidx/media3/exoplayer/dash/manifest/AdaptationSet.java create mode 100644 android/src/main/java/androidx/media3/exoplayer/dash/manifest/DashManifest.java create mode 100644 android/src/main/java/androidx/media3/exoplayer/dash/manifest/Period.java create mode 100644 android/src/main/java/androidx/media3/exoplayer/dash/manifest/Representation.java create mode 100644 android/src/main/java/androidx/media3/exoplayer/hls/HlsMediaSource.java create mode 100644 android/src/main/java/androidx/media3/exoplayer/rtsp/RtspMediaSource.java create mode 100644 android/src/main/java/androidx/media3/exoplayer/smoothstreaming/DefaultSsChunkSource.java create mode 100644 android/src/main/java/androidx/media3/exoplayer/smoothstreaming/SsMediaSource.java diff --git a/android/build.gradle b/android/build.gradle index ba304056..1ba46ae4 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -36,17 +36,30 @@ def supportsNamespace() { return major >= 8 } -def useExoplayerIMA = safeExtGet("RNVUseExoplayerIMA")?.toBoolean() ?: false +def ExoplayerDependenciesList = [ + "useExoplayerIMA", + "useExoplayerSmoothStreaming", + "useExoplayerDash", + "useExoplayerHls", + "useExoplayerRtsp", +] -println "useExoplayerIMA:" + useExoplayerIMA +def ExoplayerDependencies = ExoplayerDependenciesList.collectEntries { property -> + [(property): safeExtGet(property)?.toBoolean() ?: false] +} + +ExoplayerDependenciesList.each { propertyName -> + def propertyValue = ExoplayerDependencies[propertyName] + println "$propertyName: $propertyValue" +} // 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 = ( - 'useExoplayerIMA' + useExoplayerIMA \ -).md5() +def configStringPath = ExoplayerDependencies.collect { property, value -> + property + value +}.join('').md5() if (isNewArchitectureEnabled()) { apply plugin: "com.facebook.react" @@ -83,7 +96,13 @@ android { targetSdkVersion safeExtGet('targetSdkVersion') versionCode 1 versionName "1.0" + buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() + buildConfigField "boolean", "USE_EXOPLAYER_IMA", ExoplayerDependencies["useExoplayerIMA"].toString() + buildConfigField "boolean", "USE_EXOPLAYER_SMOOTH_STREAMING", ExoplayerDependencies["useExoplayerSmoothStreaming"].toString() + buildConfigField "boolean", "USE_EXOPLAYER_DASH", ExoplayerDependencies["useExoplayerDash"].toString() + buildConfigField "boolean", "USE_EXOPLAYER_HLS", ExoplayerDependencies["useExoplayerHls"].toString() + buildConfigField "boolean", "USE_EXOPLAYER_RTSP", ExoplayerDependencies["useExoplayerRtsp"].toString() ndk { abiFilters(*reactNativeArchitectures()) @@ -103,10 +122,26 @@ android { sourceSets { main { java { - if (useExoplayerIMA) { + if (ExoplayerDependencies["useExoplayerIMA"]) { exclude 'com/google/ads/interactivemedia/v3/api' exclude 'androidx/media3/exoplayer/ima' } + + if (ExoplayerDependencies["useExoplayerSmoothStreaming"]) { + exclude 'androidx/media3/exoplayer/smoothstreaming' + } + + if (ExoplayerDependencies["useExoplayerDash"]) { + exclude 'androidx/media3/exoplayer/dash' + } + + if (ExoplayerDependencies["useExoplayerHls"]) { + exclude 'androidx/media3/exoplayer/hls' + } + + if (ExoplayerDependencies["useExoplayerRtsp"]) { + exclude 'androidx/media3/exoplayer/rtsp' + } } } } @@ -158,16 +193,28 @@ dependencies { // For media playback using ExoPlayer implementation "androidx.media3:media3-exoplayer:$media3_version" - // For Smooth Streaming playback support with ExoPlayer - implementation "androidx.media3:media3-exoplayer-smoothstreaming:$media3_version" - // For DASH playback support with ExoPlayer - implementation "androidx.media3:media3-exoplayer-dash:$media3_version" - // For HLS playback support with ExoPlayer - implementation "androidx.media3:media3-exoplayer-hls:$media3_version" + if (ExoplayerDependencies["useExoplayerSmoothStreaming"]) { + // For Smooth Streaming playback support with ExoPlayer + implementation "androidx.media3:media3-exoplayer-smoothstreaming:$media3_version" + } - implementation "androidx.media3:media3-exoplayer-rtsp:$media3_version" + if (ExoplayerDependencies["useExoplayerDash"]) { + // For DASH playback support with ExoPlayer + 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 RTSP playback support with ExoPlayer + if (ExoplayerDependencies["useExoplayerRtsp"]) { + implementation "androidx.media3:media3-exoplayer-rtsp:$media3_version" + } + // For ad insertion using the Interactive Media Ads SDK with ExoPlayer - if (useExoplayerIMA) { + if (ExoplayerDependencies["useExoplayerIMA"]) { implementation "androidx.media3:media3-exoplayer-ima:$media3_version" } diff --git a/android/gradle.properties b/android/gradle.properties index 151fee68..f19a0a19 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -5,6 +5,10 @@ RNVideo_compileSdkVersion=31 RNVideo_ndkversion=21.4.7075529 RNVideo_buildToolsVersion=30.0.2 RNVideo_media3Version=1.1.1 -RNVideo_RNVUseExoplayerIMA=false +RNVideo_useExoplayerIMA=false +RNVideo_useExoplayerRtsp=false +RNVideo_useExoplayerSmoothStreaming=true +RNVideo_useExoplayerDash=true +RNVideo_useExoplayerHls=true RNVideo_androidxCoreVersion=1.9.0 RNVideo_androidxActivityVersion=1.7.0 diff --git a/android/src/main/java/androidx/media3/exoplayer/dash/DashMediaSource.java b/android/src/main/java/androidx/media3/exoplayer/dash/DashMediaSource.java new file mode 100644 index 00000000..092f1d59 --- /dev/null +++ b/android/src/main/java/androidx/media3/exoplayer/dash/DashMediaSource.java @@ -0,0 +1,36 @@ +package androidx.media3.exoplayer.dash; + +import androidx.media3.common.MediaItem; +import androidx.media3.datasource.DataSource; +import androidx.media3.exoplayer.drm.DrmSessionManagerProvider; +import androidx.media3.exoplayer.source.MediaSource; +import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy; + +public class DashMediaSource { + public static class Factory implements MediaSource.Factory { + + public Factory(DefaultDashChunkSource.Factory factory, DataSource.Factory factory1) { + } + + @Override + public MediaSource.Factory setDrmSessionManagerProvider(DrmSessionManagerProvider drmSessionManagerProvider) { + return null; + } + + @Override + public MediaSource.Factory setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy loadErrorHandlingPolicy) { + return null; + } + + @Override + public int[] getSupportedTypes() { + return new int[0]; + } + + @Override + public MediaSource createMediaSource(MediaItem mediaItem) { + return null; + } + } +} + diff --git a/android/src/main/java/androidx/media3/exoplayer/dash/DashUtil.java b/android/src/main/java/androidx/media3/exoplayer/dash/DashUtil.java new file mode 100644 index 00000000..8131148f --- /dev/null +++ b/android/src/main/java/androidx/media3/exoplayer/dash/DashUtil.java @@ -0,0 +1,12 @@ +package androidx.media3.exoplayer.dash; + +import android.net.Uri; + +import androidx.media3.datasource.DataSource; +import androidx.media3.exoplayer.dash.manifest.DashManifest; + +public class DashUtil { + public static DashManifest loadManifest(DataSource ds, Uri uri) { + return null; + } +} diff --git a/android/src/main/java/androidx/media3/exoplayer/dash/DefaultDashChunkSource.java b/android/src/main/java/androidx/media3/exoplayer/dash/DefaultDashChunkSource.java new file mode 100644 index 00000000..95026f07 --- /dev/null +++ b/android/src/main/java/androidx/media3/exoplayer/dash/DefaultDashChunkSource.java @@ -0,0 +1,10 @@ +package androidx.media3.exoplayer.dash; + +import androidx.media3.datasource.DataSource; + +public class DefaultDashChunkSource { + public static final class Factory { + public Factory(DataSource.Factory mediaDataSourceFactory) { + } + } +} diff --git a/android/src/main/java/androidx/media3/exoplayer/dash/manifest/AdaptationSet.java b/android/src/main/java/androidx/media3/exoplayer/dash/manifest/AdaptationSet.java new file mode 100644 index 00000000..e74c4fb8 --- /dev/null +++ b/android/src/main/java/androidx/media3/exoplayer/dash/manifest/AdaptationSet.java @@ -0,0 +1,13 @@ +package androidx.media3.exoplayer.dash.manifest; + +import androidx.collection.CircularArray; +import androidx.media3.common.C; + +public class AdaptationSet { + public int type = 0; + public CircularArray representations; + + public AdaptationSet() { + representations = null; + } +} diff --git a/android/src/main/java/androidx/media3/exoplayer/dash/manifest/DashManifest.java b/android/src/main/java/androidx/media3/exoplayer/dash/manifest/DashManifest.java new file mode 100644 index 00000000..c65854b3 --- /dev/null +++ b/android/src/main/java/androidx/media3/exoplayer/dash/manifest/DashManifest.java @@ -0,0 +1,15 @@ +package androidx.media3.exoplayer.dash.manifest; + +public class DashManifest { + public DashManifest() { + + } + + public int getPeriodCount() { + return 0; + } + + public Period getPeriod(int index) { + return null; + } +} diff --git a/android/src/main/java/androidx/media3/exoplayer/dash/manifest/Period.java b/android/src/main/java/androidx/media3/exoplayer/dash/manifest/Period.java new file mode 100644 index 00000000..41daabf8 --- /dev/null +++ b/android/src/main/java/androidx/media3/exoplayer/dash/manifest/Period.java @@ -0,0 +1,7 @@ +package androidx.media3.exoplayer.dash.manifest; + +import androidx.collection.CircularArray; + +public class Period { + public CircularArray adaptationSets; +} diff --git a/android/src/main/java/androidx/media3/exoplayer/dash/manifest/Representation.java b/android/src/main/java/androidx/media3/exoplayer/dash/manifest/Representation.java new file mode 100644 index 00000000..72a905c0 --- /dev/null +++ b/android/src/main/java/androidx/media3/exoplayer/dash/manifest/Representation.java @@ -0,0 +1,12 @@ +package androidx.media3.exoplayer.dash.manifest; + +import androidx.media3.common.Format; + +public class Representation { + public Format format; + public long presentationTimeOffsetUs; + + public Representation() { + format = null; + } +} diff --git a/android/src/main/java/androidx/media3/exoplayer/hls/HlsMediaSource.java b/android/src/main/java/androidx/media3/exoplayer/hls/HlsMediaSource.java new file mode 100644 index 00000000..69f11f1f --- /dev/null +++ b/android/src/main/java/androidx/media3/exoplayer/hls/HlsMediaSource.java @@ -0,0 +1,34 @@ +package androidx.media3.exoplayer.hls; + +import androidx.media3.common.MediaItem; +import androidx.media3.datasource.DataSource; +import androidx.media3.exoplayer.drm.DrmSessionManagerProvider; +import androidx.media3.exoplayer.source.MediaSource; +import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy; + +public class HlsMediaSource { + public static class Factory implements MediaSource.Factory { + public Factory(DataSource.Factory mediaDataSourceFactory) { + } + + @Override + public MediaSource.Factory setDrmSessionManagerProvider(DrmSessionManagerProvider drmSessionManagerProvider) { + return null; + } + + @Override + public MediaSource.Factory setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy loadErrorHandlingPolicy) { + return null; + } + + @Override + public int[] getSupportedTypes() { + return new int[0]; + } + + @Override + public MediaSource createMediaSource(MediaItem mediaItem) { + return null; + } + } +} diff --git a/android/src/main/java/androidx/media3/exoplayer/rtsp/RtspMediaSource.java b/android/src/main/java/androidx/media3/exoplayer/rtsp/RtspMediaSource.java new file mode 100644 index 00000000..0382e935 --- /dev/null +++ b/android/src/main/java/androidx/media3/exoplayer/rtsp/RtspMediaSource.java @@ -0,0 +1,34 @@ +package androidx.media3.exoplayer.rtsp; + +import androidx.media3.common.MediaItem; +import androidx.media3.exoplayer.drm.DrmSessionManagerProvider; +import androidx.media3.exoplayer.source.MediaSource; +import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy; + +public class RtspMediaSource { + public RtspMediaSource() { + + } + + public static class Factory implements MediaSource.Factory { + @Override + public MediaSource.Factory setDrmSessionManagerProvider(DrmSessionManagerProvider drmSessionManagerProvider) { + return null; + } + + @Override + public MediaSource.Factory setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy loadErrorHandlingPolicy) { + return null; + } + + @Override + public int[] getSupportedTypes() { + return new int[0]; + } + + @Override + public MediaSource createMediaSource(MediaItem mediaItem) { + return null; + } + } +} \ No newline at end of file diff --git a/android/src/main/java/androidx/media3/exoplayer/smoothstreaming/DefaultSsChunkSource.java b/android/src/main/java/androidx/media3/exoplayer/smoothstreaming/DefaultSsChunkSource.java new file mode 100644 index 00000000..fb0826d4 --- /dev/null +++ b/android/src/main/java/androidx/media3/exoplayer/smoothstreaming/DefaultSsChunkSource.java @@ -0,0 +1,34 @@ +package androidx.media3.exoplayer.smoothstreaming; + +import androidx.media3.common.MediaItem; +import androidx.media3.datasource.DataSource; +import androidx.media3.exoplayer.drm.DrmSessionManagerProvider; +import androidx.media3.exoplayer.source.MediaSource; +import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy; + +public class DefaultSsChunkSource { + public static class Factory implements MediaSource.Factory { + public Factory(DataSource.Factory mediaDataSourceFactory) { + } + + @Override + public MediaSource.Factory setDrmSessionManagerProvider(DrmSessionManagerProvider drmSessionManagerProvider) { + return null; + } + + @Override + public MediaSource.Factory setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy loadErrorHandlingPolicy) { + return null; + } + + @Override + public int[] getSupportedTypes() { + return new int[0]; + } + + @Override + public MediaSource createMediaSource(MediaItem mediaItem) { + return null; + } + } +} diff --git a/android/src/main/java/androidx/media3/exoplayer/smoothstreaming/SsMediaSource.java b/android/src/main/java/androidx/media3/exoplayer/smoothstreaming/SsMediaSource.java new file mode 100644 index 00000000..e00ec92b --- /dev/null +++ b/android/src/main/java/androidx/media3/exoplayer/smoothstreaming/SsMediaSource.java @@ -0,0 +1,34 @@ +package androidx.media3.exoplayer.smoothstreaming; + +import androidx.media3.common.MediaItem; +import androidx.media3.datasource.DataSource; +import androidx.media3.exoplayer.drm.DrmSessionManagerProvider; +import androidx.media3.exoplayer.source.MediaSource; +import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy; + +public class SsMediaSource { + public static class Factory implements MediaSource.Factory { + public Factory(DefaultSsChunkSource.Factory factory, DataSource.Factory factory1) { + } + + @Override + public MediaSource.Factory setDrmSessionManagerProvider(DrmSessionManagerProvider drmSessionManagerProvider) { + return null; + } + + @Override + public MediaSource.Factory setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy loadErrorHandlingPolicy) { + return null; + } + + @Override + public int[] getSupportedTypes() { + return new int[0]; + } + + @Override + public MediaSource createMediaSource(MediaItem mediaItem) { + return null; + } + } +} diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index c4000f1d..cfd61b6f 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -101,6 +101,7 @@ import com.brentvatne.common.api.Track; import com.brentvatne.common.api.VideoTrack; import com.brentvatne.common.react.VideoEventEmitter; import com.brentvatne.common.toolbox.DebugLog; +import com.brentvatne.react.BuildConfig; import com.brentvatne.react.R; import com.brentvatne.receiver.AudioBecomingNoisyReceiver; import com.brentvatne.receiver.BecomingNoisyListener; @@ -822,18 +823,33 @@ public class ReactExoplayerView extends FrameLayout implements switch (type) { case CONTENT_TYPE_SS: + if(!BuildConfig.USE_EXOPLAYER_SMOOTH_STREAMING) { + DebugLog.e("Exo Player Exception", "Smooth Streaming is not enabled!"); + throw new IllegalStateException("Smooth Streaming is not enabled!"); + } + mediaSourceFactory = new SsMediaSource.Factory( new DefaultSsChunkSource.Factory(mediaDataSourceFactory), buildDataSourceFactory(false) ); break; case CONTENT_TYPE_DASH: + if(!BuildConfig.USE_EXOPLAYER_DASH) { + DebugLog.e("Exo Player Exception", "DASH is not enabled!"); + throw new IllegalStateException("DASH is not enabled!"); + } + mediaSourceFactory = new DashMediaSource.Factory( new DefaultDashChunkSource.Factory(mediaDataSourceFactory), buildDataSourceFactory(false) ); break; case CONTENT_TYPE_HLS: + if (!BuildConfig.USE_EXOPLAYER_HLS) { + DebugLog.e("Exo Player Exception", "HLS is not enabled!"); + throw new IllegalStateException("HLS is not enabled!"); + } + mediaSourceFactory = new HlsMediaSource.Factory( mediaDataSourceFactory ); @@ -844,6 +860,11 @@ public class ReactExoplayerView extends FrameLayout implements ); break; case CONTENT_TYPE_RTSP: + if (!BuildConfig.USE_EXOPLAYER_RTSP) { + DebugLog.e("Exo Player Exception", "RTSP is not enabled!"); + throw new IllegalStateException("RTSP is not enabled!"); + } + mediaSourceFactory = new RtspMediaSource.Factory(); break; default: { diff --git a/docs/pages/installation.md b/docs/pages/installation.md index 4f59c883..9187aa94 100644 --- a/docs/pages/installation.md +++ b/docs/pages/installation.md @@ -65,14 +65,28 @@ buildscript { ### Enable custom feature in gradle file -#### Enable client side ads insertion -To enable client side ads insertion CSAI with google IMA SDK, you need to enable it in your gradle file. +You can disable or enable the following features by setting the following variables in your `android/build.gradle` file: +- `useExoplayerIMA` - Enable Google IMA SDK (Ads support) +- `useExoplayerRtsp` - Enable RTSP support +- `useExoplayerSmoothStreaming` - Enable SmoothStreaming support +- `useExoplayerDash` - Enable Dash support +- `useExoplayerHls` - Enable HLS support + +Each of these features enabled will increase the size of your APK, so only enable the features you need. +By default enabled features are: `useExoplayerSmoothStreaming`, `useExoplayerDash`, `useExoplayerHls` + + +Example: ```gradle buildscript { ext { ... - RNVUseExoplayerIMA = true + useExoplayerIMA = true + useExoplayerRtsp = true + useExoplayerSmoothStreaming = true + useExoplayerDash = true + useExoplayerHls = true ... } } diff --git a/examples/basic/android/build.gradle b/examples/basic/android/build.gradle index 6278ed23..3838f933 100644 --- a/examples/basic/android/build.gradle +++ b/examples/basic/android/build.gradle @@ -9,7 +9,13 @@ buildscript { ndkVersion = "26.1.10909125" kotlinVersion = "1.9.22" - RNVUseExoplayerIMA = System.getenv("RNV_SAMPLE_ENABLE_ADS") ?: true + useExoplayerIMA = System.getenv("RNV_SAMPLE_ENABLE_ADS") ?: true + useExoplayerRtsp = true + + // use the following to disable ExoPlayer modules - this will reduce the size of your app + // useExoplayerSmoothStreaming = false + // useExoplayerDash = false + // useExoplayerHls = false } repositories { google()