### Implement SeekListener Source: https://github.com/yuliskov/smarttube/blob/master/doubletapplayerview/README.md Interface for handling events when the video playback reaches the start or end boundaries. ```kotlin // Called when the start of the video is reached fun onVideoStartReached() // Called when the end of the video is reached fun onVideoEndReached() ``` -------------------------------- ### SeekListener Source: https://github.com/yuliskov/smarttube/blob/master/doubletapplayerview/README.md Interface for reacting to events when the video reaches its start or end boundaries during a seek operation. ```APIDOC ## SeekListener ### Description This interface reacts to events during rewinding or forwarding operations. ### Methods - **onVideoStartReached()**: Called when the start of the video is reached. - **onVideoEndReached()**: Called when the end of the video is reached. ``` -------------------------------- ### Set environment variables for build Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/flac/README.md Define the root directory and extension path for the ExoPlayer build process. ```bash cd "" EXOPLAYER_ROOT="$(pwd)" FLAC_EXT_PATH="${EXOPLAYER_ROOT}/extensions/flac/src/main" ``` -------------------------------- ### Initialize and Launch File Picker Source: https://github.com/yuliskov/smarttube/blob/master/filepicker-lib/README.md Register the Activity Result API and configure the MaterialFilePicker instance to launch the picker. ```kotlin /** * This library require "Activity Result" API **/ private val startForResultFiles = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { result: ActivityResult -> onActivityResult(result.resultCode, result.data) } ... // External Storage Path val externalStorage = FileUtils.getFile(applicationContext, null) MaterialFilePicker() // Pass a source of context. Can be: // .withActivity(Activity activity) // .withFragment(Fragment fragment) // .withSupportFragment(androidx.fragment.app.Fragment fragment) .withActivity(this) // With cross icon on the right side of toolbar for closing picker straight away .withCloseMenu(true) // Entry point path (user will start from it) //.withPath(alarmsFolder.absolutePath) // Root path (user won't be able to come higher than it) .withRootPath(externalStorage.absolutePath) // Showing hidden files .withHiddenFiles(true) // Want to choose only jpg images .withFilter(Pattern.compile(".*\\.(jpg|jpeg)$")) // Don't apply filter to directories names .withFilterDirectories(false) .withTitle("Sample title") // Require "Activity Result" API .withActivityResultApi(startForResultFiles) .start() ``` -------------------------------- ### Fetch and build FFmpeg Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/ffmpeg/README.md Configure and build FFmpeg for multiple Android architectures. ```bash COMMON_OPTIONS="\ --target-os=android \ --disable-static \ --enable-shared \ --disable-doc \ --disable-programs \ --disable-everything \ --disable-avdevice \ --disable-avformat \ --disable-swscale \ --disable-postproc \ --disable-avfilter \ --disable-symver \ --disable-swresample \ --enable-avresample \ --enable-decoder=vorbis \ --enable-decoder=opus \ --enable-decoder=flac \ " && \ cd "${FFMPEG_EXT_PATH}" && \ (git -C ffmpeg pull || git clone git://source.ffmpeg.org/ffmpeg ffmpeg) && \ cd ffmpeg && git checkout release/4.0 && \ ./configure \ --libdir=android-libs/armeabi-v7a \ --arch=arm \ --cpu=armv7-a \ --cross-prefix="${NDK_PATH}/toolchains/arm-linux-androideabi-4.9/prebuilt/${HOST_PLATFORM}/bin/arm-linux-androideabi-" \ --sysroot="${NDK_PATH}/platforms/android-9/arch-arm/" \ --extra-cflags="-march=armv7-a -mfloat-abi=softfp" \ --extra-ldflags="-Wl,--fix-cortex-a8" \ --extra-ldexeflags=-pie \ ${COMMON_OPTIONS} \ && \ make -j4 && make install-libs && \ make clean && ./configure \ --libdir=android-libs/arm64-v8a \ --arch=aarch64 \ --cpu=armv8-a \ --cross-prefix="${NDK_PATH}/toolchains/aarch64-linux-android-4.9/prebuilt/${HOST_PLATFORM}/bin/aarch64-linux-android-" \ --sysroot="${NDK_PATH}/platforms/android-21/arch-arm64/" \ --extra-ldexeflags=-pie \ ${COMMON_OPTIONS} \ && \ make -j4 && make install-libs && \ make clean && ./configure \ --libdir=android-libs/x86 \ --arch=x86 \ --cpu=i686 \ --cross-prefix="${NDK_PATH}/toolchains/x86-4.9/prebuilt/${HOST_PLATFORM}/bin/i686-linux-android-" \ --sysroot="${NDK_PATH}/platforms/android-9/arch-x86/" \ --extra-ldexeflags=-pie \ --disable-asm \ ${COMMON_OPTIONS} \ && \ make -j4 && make install-libs && \ make clean ``` -------------------------------- ### Set host platform Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/ffmpeg/README.md Define the host platform environment variable. ```bash HOST_PLATFORM="linux-x86_64" ``` -------------------------------- ### Fetch libvpx source Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/vp9/README.md Download the libvpx source code into the JNI directory. ```bash cd "${VP9_EXT_PATH}/jni" && \ git clone https://chromium.googlesource.com/webm/libvpx libvpx ``` -------------------------------- ### Configure Repositories in build.gradle Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/README-ORIGINAL.md Add Google and JCenter repositories to the root build.gradle file to resolve ExoPlayer dependencies. ```gradle repositories { google() jcenter() } ``` -------------------------------- ### Configure YouTubeOverlay in Activity or Fragment Source: https://github.com/yuliskov/smarttube/blob/master/doubletapplayerview/README.md Set up the animation listeners and link the player instance to the overlay in your Kotlin code. ```kotlin youtube_overlay .performListener(object : YouTubeOverlay.PerformListener { override fun onAnimationStart() { // Do UI changes when circle scaling animation starts (e.g. hide controller views) youtube_overlay.visibility = View.VISIBLE } override fun onAnimationEnd() { // Do UI changes when circle scaling animation starts (e.g. show controller views) youtube_overlay.visibility = View.GONE } }) // Uncomment this line if you haven't set yt_playerView in XML // .playerView(playerView) // Uncomment this line if you haven't set dtpv_controller in XML // playerView.controller(youtube_overlay) // Call this method whenever the player is released and recreated youtube_overlay.player(simpleExoPlayer) ``` -------------------------------- ### Generate libvpx configuration Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/vp9/README.md Run the script to generate necessary configuration files for the Android build. ```bash cd ${VP9_EXT_PATH}/jni && \ ./generate_libvpx_android_configs.sh ``` -------------------------------- ### Initialize OkHttpDataSource for mixed content Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/okhttp/README.md Use these constructors when your application needs to support both HTTP and non-HTTP content types. ```java new DefaultDataSource( ... new OkHttpDataSource(...) /* baseDataSource argument */); ``` ```java new DefaultDataSourceFactory( ... new OkHttpDataSourceFactory(...) /* baseDataSourceFactory argument */); ``` -------------------------------- ### Add ExoPlayer Dependencies Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/README-ORIGINAL.md Include the full ExoPlayer library or specific modules in the app-level build.gradle file. ```gradle implementation 'com.google.android.exoplayer:exoplayer:2.X.X' ``` ```gradle implementation 'com.google.android.exoplayer:exoplayer-core:2.X.X' implementation 'com.google.android.exoplayer:exoplayer-dash:2.X.X' implementation 'com.google.android.exoplayer:exoplayer-ui:2.X.X' ``` -------------------------------- ### Convert ARM Assembly Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/opus/README.md Run the conversion script to make ARM assembly compatible with the NDK. ```bash cd ${OPUS_EXT_PATH}/jni && ./convert_android_asm.sh ``` -------------------------------- ### Checkout specific libvpx version Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/vp9/README.md Switch to the verified version of libvpx compatible with the current extension scripts. ```bash cd "${VP9_EXT_PATH}/jni/libvpx" && \ git checkout tags/v1.8.0 -b v1.8.0 ``` -------------------------------- ### Add OkHttp extension dependency Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/okhttp/README.md Include this dependency in your build.gradle file, ensuring the version matches your ExoPlayer library version. ```gradle implementation 'com.google.android.exoplayer:extension-okhttp:2.X.X' ``` -------------------------------- ### Configure Local Module Dependencies Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/README-ORIGINAL.md Update settings.gradle to include local ExoPlayer modules. ```gradle gradle.ext.exoplayerRoot = 'path/to/exoplayer' gradle.ext.exoplayerModulePrefix = 'exoplayer-' apply from: new File(gradle.ext.exoplayerRoot, 'core_settings.gradle') ``` ```gradle implementation project(':exoplayer-library-core') implementation project(':exoplayer-library-dash') implementation project(':exoplayer-library-ui') ``` -------------------------------- ### Add Leanback extension dependency Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/leanback/README.md Include this dependency in your build.gradle file, ensuring the version matches your ExoPlayer library version. ```gradle implementation 'com.google.android.exoplayer:extension-leanback:2.X.X' ``` -------------------------------- ### Configure Gradle Dependencies Source: https://github.com/yuliskov/smarttube/blob/master/filepicker-lib/README.md Add the JitPack repository and the required library dependencies to your project's build.gradle files. ```gradle build.gradle (Project) allprojects { repositories { maven { url 'https://jitpack.io' } } } build.gradle (Module: app) dependencies { ... // Java implementation 'androidx.activity:activity:1.4.0' implementation 'androidx.fragment:fragment:1.4.1' // Kotlin implementation 'androidx.activity:activity-ktx:1.4.0' implementation 'androidx.fragment:fragment-ktx:1.4.1' implementation 'com.github.arteaprogramar:Android-MaterialFilePicker:3.0.1' } ``` -------------------------------- ### Clone ExoPlayer Repository Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/README-ORIGINAL.md Commands to clone the ExoPlayer repository and switch to the release branch for local development. ```sh git clone https://github.com/google/ExoPlayer.git git checkout release-v2 ``` -------------------------------- ### Set environment variables for build Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/vp9/README.md Define the root directory and extension path variables required for the build process. ```bash cd "" EXOPLAYER_ROOT="$(pwd)" VP9_EXT_PATH="${EXOPLAYER_ROOT}/extensions/vp9/src/main" ``` -------------------------------- ### Add MediaSession extension dependency Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/mediasession/README.md Include the extension in your project using Gradle. Ensure the version matches your ExoPlayer library version. ```gradle implementation 'com.google.android.exoplayer:extension-mediasession:2.X.X' ``` -------------------------------- ### Implement YouTubeOverlay.PerformListener Source: https://github.com/yuliskov/smarttube/blob/master/doubletapplayerview/README.md Interface for managing the lifecycle of the overlay animation and determining seek direction. ```kotlin // Obligatory: Called when the overlay is not visible and the first valid double tap event occurred. // Visibility of the overlay should be set to VISIBLE within this interface method. fun onAnimationStart() // Obligatory: Called when the circle animation is finished. // Visibility of the overlay should be set to GONE or INVISIBLE within this interface method. fun onAnimationEnd() // Optional: Determines whether the player should forward (true), rewind (false) or ignore (null) taps. fun shouldForward(player: Player, playerView: DoubleTapPlayerView, posX: Float): Boolean? ``` -------------------------------- ### Initialize CronetDataSource for mixed content Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/cronet/README.md Use these constructors when your application needs to support both HTTP and non-HTTP content like local files. ```java new DefaultDataSource( ... new CronetDataSource(...) /* baseDataSource argument */); ``` ```java new DefaultDataSourceFactory( ... new CronetDataSourceFactory(...) /* baseDataSourceFactory argument */); ``` -------------------------------- ### Define Fragment Layout XML Source: https://github.com/yuliskov/smarttube/blob/master/slidableactivity/README.md Configure the root FrameLayout and content container with a transparent background for proper sliding behavior. ```xml ...other stuff ``` -------------------------------- ### Download and extract libFLAC Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/flac/README.md Fetch and prepare the flac-1.3.2 source code within the extension's JNI directory. ```bash cd "${FLAC_EXT_PATH}/jni" && \ curl https://ftp.osuosl.org/pub/xiph/releases/flac/flac-1.3.2.tar.xz | tar xJ && \ mv flac-1.3.2 flac ``` -------------------------------- ### Enable Java 8 Support Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/README-ORIGINAL.md Configure the android section in build.gradle to support Java 8 features required by ExoPlayer. ```gradle compileOptions { targetCompatibility JavaVersion.VERSION_1_8 } ``` -------------------------------- ### YouTubeOverlay.PerformListener Source: https://github.com/yuliskov/smarttube/blob/master/doubletapplayerview/README.md Interface for handling the lifecycle of the YouTube-style overlay animation and determining seek behavior. ```APIDOC ## YouTubeOverlay.PerformListener ### Description This interface listens to the lifecycle of the overlay and determines if a seek action should proceed. ### Methods - **onAnimationStart()**: Called when the overlay is not visible and the first valid double tap event occurred. Visibility should be set to VISIBLE here. - **onAnimationEnd()**: Called when the circle animation is finished. Visibility should be set to GONE or INVISIBLE here. - **shouldForward(player: Player, playerView: DoubleTapPlayerView, posX: Float): Boolean?**: Determines whether the player should forward (true), rewind (false), or ignore (null) taps. ``` -------------------------------- ### Attach Slidr with Default Settings Source: https://github.com/yuliskov/smarttube/blob/master/slidableactivity/README.md Use this method for a basic implementation of Slidr without custom color configurations. ```java public class ExampleActivity extends { @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_example); Slidr.attach(this); } } ``` -------------------------------- ### Set FFmpeg extension path Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/ffmpeg/README.md Define the path to the FFmpeg extension JNI source directory. ```bash cd "" FFMPEG_EXT_PATH="$(pwd)/extensions/ffmpeg/src/main/jni" ``` -------------------------------- ### Build JNI native libraries Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/flac/README.md Compile the native JNI components using the ndk-build tool. ```bash cd "${FLAC_EXT_PATH}"/jni && \ ${NDK_PATH}/ndk-build APP_ABI=all -j4 ``` -------------------------------- ### Fetch libopus Source Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/opus/README.md Clone the libopus repository into the extension's JNI directory. ```bash cd "${OPUS_EXT_PATH}/jni" && \ git clone https://git.xiph.org/opus.git libopus ``` -------------------------------- ### Add GVR extension dependency Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/gvr/README.md Include the GVR extension in your project using Gradle. Ensure the version matches your ExoPlayer library version. ```gradle implementation 'com.google.android.exoplayer:extension-gvr:2.X.X' ``` -------------------------------- ### Add Gradle dependency for JobDispatcher extension Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/jobdispatcher/README.md Include this dependency in your build.gradle file, ensuring the version matches your ExoPlayer library version. ```gradle implementation 'com.google.android.exoplayer:extension-jobdispatcher:2.X.X' ``` -------------------------------- ### Set Android NDK path Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/flac/README.md Define the location of the Android NDK required for compiling native libraries. ```bash NDK_PATH="" ``` -------------------------------- ### Add Library Dependency Source: https://github.com/yuliskov/smarttube/blob/master/doubletapplayerview/README.md Add the library dependency to your app-level build.gradle file. ```gradle android { ... // If you face problems during building you should try including the below lines if you // haven't already // compileOptions { // sourceCompatibility JavaVersion.VERSION_1_8 // targetCompatibility JavaVersion.VERSION_1_8 // } } dependencies { implementation 'com.github.vkay94:DoubleTapPlayerView:1.0.4' } ``` -------------------------------- ### Integrate DoubleTapPlayerView in XML Source: https://github.com/yuliskov/smarttube/blob/master/doubletapplayerview/README.md Add the DoubleTapPlayerView and YouTubeOverlay components to your layout XML file. ```xml ``` -------------------------------- ### Add WorkManager extension dependency Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/workmanager/README.md Include the extension in your project by adding this dependency to your build.gradle file, ensuring the version matches your ExoPlayer library version. ```gradle implementation 'com.google.android.exoplayer:extension-workmanager:2.X.X' ``` -------------------------------- ### Add JitPack Repository to Gradle Source: https://github.com/yuliskov/smarttube/blob/master/doubletapplayerview/README.md Include the JitPack repository in your project-level build.gradle file to access the library. ```gradle allprojects { repositories { ... maven { url 'https://jitpack.io' } } } ``` -------------------------------- ### Add IMA extension dependency Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/ima/README.md Include the IMA extension in your project using Gradle, ensuring the version matches your ExoPlayer library version. ```gradle implementation 'com.google.android.exoplayer:extension-ima:2.X.X' ``` -------------------------------- ### Add RTMP extension dependency Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/rtmp/README.md Include the RTMP extension in your project by adding this dependency to your build.gradle file, ensuring the version matches your ExoPlayer library version. ```gradle implementation 'com.google.android.exoplayer:extension-rtmp:2.X.X' ``` -------------------------------- ### Add Cronet dependency in Gradle Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/cronet/README.md Include the Cronet extension in your project by adding this dependency to your build.gradle file, ensuring the version matches your ExoPlayer library version. ```gradle implementation 'com.google.android.exoplayer:extension-cronet:2.X.X' ``` -------------------------------- ### Add Cast extension as a Gradle dependency Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/cast/README.md Include this dependency in your build.gradle file, ensuring the version matches your ExoPlayer library version. ```gradle implementation 'com.google.android.exoplayer:extension-cast:2.X.X' ``` -------------------------------- ### Handle Activity Result Source: https://github.com/yuliskov/smarttube/blob/master/filepicker-lib/README.md Override the activity result to retrieve the selected file path from the intent data. ```kotlin private fun onActivityResult(resultCode: Int, data: Intent?) { if (resultCode == Activity.RESULT_OK) { val path: String? = data?.getStringExtra(FilePickerActivity.RESULT_FILE_PATH) if (path != null) { Log.d("Path: ", path) Toast.makeText(this, "Picked file: $path", Toast.LENGTH_LONG).show() } } } ``` -------------------------------- ### Initialize Slidr in Fragment Source: https://github.com/yuliskov/smarttube/blob/master/slidableactivity/README.md Attach Slidr to the fragment view during onResume to handle swipe-to-dismiss functionality. ```java // This interface is needed to see if the fragment // is resuming after creation (Slidr to be attached) or // simply from the background (app was paused before). SlidrInterface slidrInterface; @Override public void onResume() { super.onResume(); if(slidrInterface == null) slidrInterface = Slidr.replace(getView().findViewById(R.id.content_container), new SlidrConfig.Builder().position(SlidrPosition.LEFT).build()); } ``` -------------------------------- ### Attach Slidr with Custom Colors Source: https://github.com/yuliskov/smarttube/blob/master/slidableactivity/README.md Use this method to attach Slidr with specific primary and secondary colors for the slide effect. ```java public class ExampleActivity extends { @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_example); int primary = getResources().getColor(R.color.primaryDark); int secondary = getResources().getColor(R.color.secondaryDark); Slidr.attach(this, primary, secondary); } } ``` -------------------------------- ### Uninstall official YouTube app via ADB Source: https://github.com/yuliskov/smarttube/blob/master/README.md Command to remove the pre-installed YouTube application on rooted Android devices to enable bridge app functionality. ```bash adb shell pm uninstall com.google.android.youtube.tv ``` -------------------------------- ### Keep MediaRouteActionProvider class Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/demos/cast/proguard-rules.txt Prevents Proguard from obfuscating or removing the MediaRouteActionProvider class, which is accessed via menu.xml. ```proguard -keep class androidx.mediarouter.app.MediaRouteActionProvider { *; } ``` -------------------------------- ### Add Fragment to Activity Source: https://github.com/yuliskov/smarttube/blob/master/slidableactivity/README.md Use FragmentManager to add the fragment into the designated container within the activity layout. ```java getSupportFragmentManager().beginTransaction() .add(R.id.fragment_container, YourFragmentClass.newInstance()) .commit(); ``` -------------------------------- ### Keep SimpleOutputBuffer Class Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/opus/proguard-rules.txt Ensures that members of the SimpleOutputBuffer class remain unobfuscated as they are accessed via native code. ```proguard -keep class com.google.android.exoplayer2.decoder.SimpleOutputBuffer { *; } ``` -------------------------------- ### Preserve ViewHolder constructors Source: https://github.com/yuliskov/smarttube/blob/master/chatkit/proguard.txt Use this rule to prevent ProGuard from stripping or renaming public constructors for classes extending the Chatkit ViewHolder. ```proguard # ViewHolder constructors are resolved by reflection -keepclassmembers class * extends com.stfalcon.chatkit.commons.ViewHolder { public (android.view.View); } ``` -------------------------------- ### Proguard Rules for ImaAdsLoader Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/demos/main/proguard-rules.txt Prevents Proguard from noting or removing the ImaAdsLoader class and its specific constructor used in PlayerActivity. ```proguard -dontnote com.google.android.exoplayer2.ext.ima.ImaAdsLoader -keepclassmembers class com.google.android.exoplayer2.ext.ima.ImaAdsLoader { (android.content.Context, android.net.Uri); } ``` -------------------------------- ### Keep native methods in Proguard Source: https://github.com/yuliskov/smarttube/blob/master/exoplayer-amzn-2.10.6/extensions/ffmpeg/proguard-rules.txt Use this rule to prevent Proguard from renaming native methods, which would break the link between Java and native code. ```proguard -keepclasseswithmembernames class * { native ; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.