diff --git a/.github/actions/setup-node/action.yml b/.github/actions/setup-node/action.yml new file mode 100644 index 0000000000..4627f212fc --- /dev/null +++ b/.github/actions/setup-node/action.yml @@ -0,0 +1,34 @@ +name: Setup node_modules +description: Setup Node.js and install dependencies + +inputs: + working-directory: + description: 'working directory for yarn install' + default: ./ + required: false + +runs: + using: composite + steps: + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.x + + - name: Cache dependencies + id: yarn-cache + uses: actions/cache@v3 + with: + path: | + **/node_modules + .yarn/install-state.gz + key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}-${{ hashFiles('**/package.json', '!node_modules/**') }} + restore-keys: | + ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} + ${{ runner.os }}-yarn- + - name: Install dependencies + working-directory: ${{ inputs.working-directory }} + if: steps.yarn-cache.outputs.cache-hit != 'true' + run: yarn install --immutable --ignore-scripts + shell: bash + diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml new file mode 100644 index 0000000000..40fcbb3215 --- /dev/null +++ b/.github/workflows/build-android.yml @@ -0,0 +1,80 @@ +name: Build Android + +on: + push: + branches: + - master + paths: + - '.github/workflows/build-android.yml' + - 'android/**' + - 'examples/basic/android/**' + - 'yarn.lock' + - 'examples/basic/yarn.lock' + pull_request: + paths: + - '.github/workflows/build-android.yml' + - 'android/**' + - 'examples/basic/android/**' + - 'yarn.lock' + - 'examples/basic/yarn.lock' + +jobs: + build: + name: Build Android Example App + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup JDK 11 + uses: actions/setup-java@v2 + with: + distribution: 'zulu' + java-version: 11 + java-package: jdk + + - name: Install node_modules + uses: ./.github/actions/setup-node + with: + working-directory: examples/basic + + - name: Restore Gradle cache + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Run Gradle Build for basic example + run: cd examples/basic/android && ./gradlew assembleDebug --build-cache && cd ../../.. + + build-without-ads: + name: Build Android Example App Without Ads + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup JDK 11 + uses: actions/setup-java@v2 + with: + distribution: 'zulu' + java-version: 11 + java-package: jdk + + - name: Install node_modules + uses: ./.github/actions/setup-node + with: + working-directory: examples/basic + + - name: Restore Gradle cache + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Run Gradle Build for basic example + run: cd examples/basic/android && export RNV_SAMPLE_ENABLE_ADS=false && ./gradlew assembleDebug --build-cache && cd ../../.. \ No newline at end of file diff --git a/.github/workflows/build-ios.yml b/.github/workflows/build-ios.yml new file mode 100644 index 0000000000..cf969a3476 --- /dev/null +++ b/.github/workflows/build-ios.yml @@ -0,0 +1,165 @@ +name: Build iOS + +on: + push: + branches: + - main + paths: + - '.github/workflows/build-ios.yml' + - 'ios/**' + - '*.podspec' + - 'examples/basic/ios/**' + pull_request: + paths: + - '.github/workflows/build-ios.yml' + - 'ios/**' + - '*.podspec' + - 'examples/basic/ios/**' + +jobs: + build: + name: Build iOS Example App + runs-on: macOS-latest + defaults: + run: + working-directory: examples/basic/ios + steps: + - uses: actions/checkout@v4 + + - name: Install node_modules + uses: ./.github/actions/setup-node + with: + working-directory: examples/basic + + - name: Restore buildcache + uses: mikehardy/buildcache-action@v2 + continue-on-error: true + + - name: Setup Ruby (bundle) + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6.10 + bundler-cache: true + + - name: Restore Pods cache + uses: actions/cache@v3 + with: + path: | + examples/basic/ios/Pods + ~/Library/Caches/CocoaPods + ~/.cocoapods + key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} + restore-keys: | + ${{ runner.os }}-pods- + - name: Install Pods + run: pod install + - name: Install xcpretty + run: gem install xcpretty + - name: Build App + run: "set -o pipefail && xcodebuild \ + -derivedDataPath build -UseModernBuildSystem=YES \ + -workspace videoplayer.xcworkspace \ + -scheme videoplayer \ + -sdk iphonesimulator \ + -configuration Debug \ + -destination 'platform=iOS Simulator,name=iPhone 11 Pro' \ + build \ + CODE_SIGNING_ALLOWED=NO | xcpretty" + + build-with-ads: + name: Build iOS Example App With Ads + runs-on: macOS-latest + defaults: + run: + working-directory: examples/basic/ios + steps: + - uses: actions/checkout@v4 + + - name: Install node_modules + uses: ./.github/actions/setup-node + with: + working-directory: examples/basic + + - name: Restore buildcache + uses: mikehardy/buildcache-action@v2 + continue-on-error: true + + - name: Setup Ruby (bundle) + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6.10 + bundler-cache: true + + - name: Restore Pods cache + uses: actions/cache@v3 + with: + path: | + examples/basic/ios/Pods + ~/Library/Caches/CocoaPods + ~/.cocoapods + key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} + restore-keys: | + ${{ runner.os }}-pods- + - name: Install Pods + run: export RNV_SAMPLE_ENABLE_ADS=true && pod install + - name: Install xcpretty + run: gem install xcpretty + - name: Build App + run: "set -o pipefail && export RNV_SAMPLE_ENABLE_ADS=true && xcodebuild \ + -derivedDataPath build -UseModernBuildSystem=YES \ + -workspace videoplayer.xcworkspace \ + -scheme videoplayer \ + -sdk iphonesimulator \ + -configuration Debug \ + -destination 'platform=iOS Simulator,name=iPhone 11 Pro' \ + build \ + CODE_SIGNING_ALLOWED=NO | xcpretty" + + build-with-caching: + name: Build iOS Example App With Caching + runs-on: macOS-latest + defaults: + run: + working-directory: examples/basic/ios + steps: + - uses: actions/checkout@v4 + + - name: Install node_modules + uses: ./.github/actions/setup-node + with: + working-directory: examples/basic + + - name: Restore buildcache + uses: mikehardy/buildcache-action@v2 + continue-on-error: true + + - name: Setup Ruby (bundle) + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6.10 + bundler-cache: true + + - name: Restore Pods cache + uses: actions/cache@v3 + with: + path: | + examples/basic/ios/Pods + ~/Library/Caches/CocoaPods + ~/.cocoapods + key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} + restore-keys: | + ${{ runner.os }}-pods- + - name: Install Pods + run: export RNV_SAMPLE_VIDEO_CACHING=true && pod install + - name: Install xcpretty + run: gem install xcpretty + - name: Build App + run: "set -o pipefail && export RNV_SAMPLE_VIDEO_CACHING=true && xcodebuild \ + -derivedDataPath build -UseModernBuildSystem=YES \ + -workspace videoplayer.xcworkspace \ + -scheme videoplayer \ + -sdk iphonesimulator \ + -configuration Debug \ + -destination 'platform=iOS Simulator,name=iPhone 11 Pro' \ + build \ + CODE_SIGNING_ALLOWED=NO | xcpretty" \ No newline at end of file diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index e6724dfebb..f8c2cc957f 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -25,6 +25,9 @@ import androidx.activity.OnBackPressedCallback; import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; +import androidx.core.view.WindowCompat; +import androidx.core.view.WindowInsetsCompat; +import androidx.core.view.WindowInsetsControllerCompat; import androidx.media3.common.AudioAttributes; import androidx.media3.common.C; import androidx.media3.common.Format; @@ -102,6 +105,7 @@ import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.uimanager.ThemedReactContext; import com.google.ads.interactivemedia.v3.api.AdEvent; import com.google.ads.interactivemedia.v3.api.AdErrorEvent; @@ -1973,34 +1977,27 @@ public void setFullscreen(boolean fullscreen) { } Window window = activity.getWindow(); - View decorView = window.getDecorView(); - int uiOptions; + WindowInsetsControllerCompat controller = new WindowInsetsControllerCompat(window, window.getDecorView()); if (isFullscreen) { - if (Util.SDK_INT >= 19) { // 4.4+ - uiOptions = SYSTEM_UI_FLAG_HIDE_NAVIGATION - | SYSTEM_UI_FLAG_IMMERSIVE_STICKY - | SYSTEM_UI_FLAG_FULLSCREEN; - } else { - uiOptions = SYSTEM_UI_FLAG_HIDE_NAVIGATION - | SYSTEM_UI_FLAG_FULLSCREEN; - } eventEmitter.fullscreenWillPresent(); if (controls && fullScreenPlayerView != null) { fullScreenPlayerView.show(); } - post(() -> { - decorView.setSystemUiVisibility(uiOptions); + UiThreadUtil.runOnUiThread(() -> { + WindowCompat.setDecorFitsSystemWindows(window, false); + controller.hide(WindowInsetsCompat.Type.systemBars()); + controller.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); eventEmitter.fullscreenDidPresent(); }); } else { - uiOptions = View.SYSTEM_UI_FLAG_VISIBLE; eventEmitter.fullscreenWillDismiss(); if (controls && fullScreenPlayerView != null) { fullScreenPlayerView.dismiss(); reLayout(exoPlayerView); } - post(() -> { - decorView.setSystemUiVisibility(uiOptions); + UiThreadUtil.runOnUiThread(() -> { + WindowCompat.setDecorFitsSystemWindows(window, true); + controller.show(WindowInsetsCompat.Type.systemBars()); eventEmitter.fullscreenDidDismiss(); }); } diff --git a/examples/basic/android/build.gradle b/examples/basic/android/build.gradle index 8034dfe888..67960abbe3 100644 --- a/examples/basic/android/build.gradle +++ b/examples/basic/android/build.gradle @@ -11,7 +11,7 @@ buildscript { // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP. ndkVersion = "23.1.7779620" - RNVUseExoplayerIMA = true + RNVUseExoplayerIMA = System.getenv("RNV_SAMPLE_ENABLE_ADS") ?: true } repositories { google() diff --git a/examples/basic/ios/Podfile b/examples/basic/ios/Podfile index fa8c02c8ba..445e22406f 100644 --- a/examples/basic/ios/Podfile +++ b/examples/basic/ios/Podfile @@ -29,8 +29,13 @@ target 'videoplayer' do config = use_native_modules! use_frameworks! :linkage => :static - # $RNVideoUseGoogleIMA = true - $RNVideoUseVideoCaching = true + + if ENV['RNV_SAMPLE_ENABLE_ADS'] + $RNVideoUseGoogleIMA = true + end + if ENV['RNV_SAMPLE_VIDEO_CACHING'] + $RNVideoUseVideoCaching = true + end # Flags change depending on the env values. flags = get_default_flags()