Skip to content

chore: upgrade Example app to React Native 0.86.2, and fix the Android library build for AGP 8 - #243

Open
octavianduminicaconnatix wants to merge 3 commits into
masterfrom
feature/react-native-0.86.2-upgrade
Open

chore: upgrade Example app to React Native 0.86.2, and fix the Android library build for AGP 8#243
octavianduminicaconnatix wants to merge 3 commits into
masterfrom
feature/react-native-0.86.2-upgrade

Conversation

@octavianduminicaconnatix

Copy link
Copy Markdown
Contributor

What does this Pull Request do?

Why

The Example app no longer compiled on Xcode 26. fmt 11.0.2 — pinned by React Native
0.78.1 — fails clang 21's stricter C++20 consteval rules, so the build died inside a
dependency before it ever reached wrapper code. Since the Example app is the only way to
manually verify this library, that left it unverifiable on current tooling.

RN 0.86 ships ReactNativeDependencies as a prebuilt binary, so fmt is no longer
compiled from source at all and the failure disappears rather than being patched around.

Bringing the Example app up to 0.86.2 also surfaced several ways the Android library
module
had fallen behind modern AGP and RN. Those fixes are the part of this PR that
matters to anyone consuming this package.

Does this affect consumers?

Yes — two files in android/ are consumer-facing. Everything else is under
Example/ and is development-only.

Change Why
Added namespace 'com.jwplayer.rnjwplayer'; removed package= from AndroidManifest.xml AGP 8 requires namespace and rejects the manifest package attribute. This is the fix for Namespace not specified build failures.
com.facebook.react:react-native:+com.facebook.react:react-android The old coordinate doesn't exist for RN 0.71+.
Removed the $rootDir/../node_modules/react-native/android Maven repo That directory no longer exists — RN publishes to Maven Central now.
Added buildFeatures { buildConfig true } AGP 8 makes BuildConfig generation opt-in, and this module emits USE_IMA / USE_CAST / IS_NEW_ARCHITECTURE_ENABLED.
compileSdkVersioncompileSdk, lintOptionslint Renamed in AGP 8.
Removed a stale classpath 'com.android.tools.build:gradle:3.4.2' buildscript block Dead config from 2019; the consuming project's AGP is what applies.
Fallback SDK levels raised: minSdkVersion 16 → 24, compile/targetSdkVersion 28 → 36 These are only safeExtGet defaults, used when the consuming app doesn't set them. Any modern RN app defines its own, and RN itself hasn't supported minSdk 16 for years.

No public API, JS, or TypeScript changes. No behavioural change to the player.

What changed in the Example app

Followed the official rn-diff-purge 0.78.1..0.86.2 diff
that backs the RN Upgrade Helper, then fixed what the template diff doesn't cover.

JS / toolingreact-native 0.78.1 → 0.86.2, react 19.0.0 → 19.2.3, CLI 15 → 20,
@react-native/* → 0.86.2 (+ jest-preset), native deps bumped (screens 4.26.2,
safe-area-context 5.8.0, gesture-handler 3.1.0, bootsplash 7.3.2, device-info 15.0.2,
vector-icons 10.3.0), engines.node>= 22.11.0, plus the template's jest,
tsconfig, prettier and Gemfile changes.

iOSAppDelegate migrated from subclassing RCTAppDelegate to
UIResponder + RCTReactNativeFactory + ReactNativeDelegate, preserving the
GoogleCast setup and moving RNBootSplash into customize(). Podfile platform pinned to
iOS 15.6 (RN's min_ios_version_supported is lower than RNJWPlayer.podspec's 15.6,
which produced a CocoaPods platform-compatibility warning).

Android — Gradle 8.12 → 9.3.1 (wrapper regenerated), buildTools/targetSdk
36, Kotlin 2.0.21 → 2.1.20, MainApplication simplified to loadReactNative() +
getDefaultReactHost(context, packageList), usesCleartextTraffic manifest placeholder
(and the debug manifest it supersedes removed), edgeToEdgeEnabled=false.

Two changes the template diff couldn't tell us about:

  • MainActivity isn't in the RN diff (the template's copy didn't change), but it
    broke anyway with 'loadApp' overrides nothingRNBootSplash 7 replaced its Android
    integration
    . Splash init moves into onCreate before super, with
    RNScreensFragmentFactory as required when using react-native-screens.
  • Splash theme migration (values/styles.xml + new values-v31/styles.xml).
    RNBootSplash 7 renamed its theme attributes (bootSplashBackground / bootSplashLogo /
    postBootSplashTheme), so the old theme silently configured nothing. A values-v31
    variant is required — with the theme only in values/, the platform splash screen on
    API 31+ doesn't pick the attributes up at all.

Deliberately not taken from the template

  • The Info.plist orientation change, which makes iPhone portrait-only — this app needs
    landscape for fullscreen playback.
  • App.tsx, which is the template's demo screen; this app has its own.

Local environment requirements

Worth knowing before you build — these cost real time to work out:

  • Use JDK 17 for Gradle. Android Studio 2026.1 bundles JBR 25, and on JDK 25 the
    build fails at :app:configureCMakeDebug with
    WARNING: A restricted method in java.lang.System has been called. That's JDK 24+'s
    JEP 472 warning; AGP 8.12's prefab step treats any
    subprocess stderr line as fatal. Set Gradle JDK → 17 (Settings → Build, Execution,
    Deployment → Build Tools → Gradle). Verified: JDK 17 passes, JDK 25 fails.

Known issues and follow-ups

  • Splash (Android, API 31+): RNBootSplash.init is intentionally not called. On
    API 31+ its post-system-splash view draws a large black ring instead of the logo, and it
    does not resolve ?bootSplashLogo from the theme — verified with three different logo
    assets, and bootSplashBackground has no effect on it either. The platform splash screen
    shows the branded logo, and the window is painted with the splash background so the gap
    before React's first render is white rather than black. Verified by sampling six frames
    across the whole splash: no black pixels in any of them. The dependency is kept — iOS
    uses it successfully, and BootTheme inherits Theme.BootSplash from it. Worth an
    upstream issue; if fixed, re-enabling one line restores a logo for the whole splash.

Not included

No JW SDK version changes — JWPlayerKit and the Android JW SDK pins are untouched. This
PR is only the React Native upgrade plus the Android library compatibility fixes.

The Example app no longer compiled on Xcode 26. fmt 11.0.2 — pinned by RN
0.78.1 — fails clang 21's stricter C++20 consteval rules, so the build died
in a dependency before reaching any wrapper code. RN 0.86 ships
ReactNativeDependencies as a prebuilt binary, so fmt is no longer compiled
from source at all and the failure disappears rather than being patched
around.

Followed the rn-diff-purge 0.78.1..0.86.2 diff (the data behind the RN
upgrade helper) for both platform templates, then fixed what the templates
don't cover.

JS / tooling:
- react-native 0.78.1 -> 0.86.2, react 19.0.0 -> 19.2.3
- @react-native-community/cli 15.0.1 -> 20.1.0, @react-native/* -> 0.86.2
  (+ @react-native/jest-preset)
- native deps: screens 4.26.2, safe-area-context 5.8.0, gesture-handler
  3.1.0, bootsplash 7.3.2, device-info 15.0.2, vector-icons 10.3.0
- engines: node >= 22.11.0; jest preset, tsconfig, prettier, Gemfile per
  template

iOS:
- AppDelegate: RCTAppDelegate subclass -> UIResponder +
  RCTReactNativeFactory + ReactNativeDelegate, preserving the GoogleCast
  GCKCastContext setup and moving RNBootSplash into customize()
- Podfile: pin platform to iOS 15.6. RN's min_ios_version_supported is
  15.1, which is below RNJWPlayer.podspec's 15.6 and triggered a CocoaPods
  platform-compatibility warning
- Info.plist: add CADisableMinimumFrameDurationOnPhone

Android (Example app):
- Gradle 8.12 -> 9.3.1 (wrapper jar and scripts regenerated), buildTools
  and targetSdk -> 36, Kotlin 2.0.21 -> 2.1.20
- MainApplication: drop ReactNativeHost/SoLoader boilerplate for
  loadReactNative() + getDefaultReactHost(context, packageList)
- MainActivity: RNBootSplash 7 replaced its Android integration — the
  custom ReactActivityDelegate no longer compiled ('loadApp' overrides
  nothing, the signature is now loadApp(String?)). Splash init moves into
  onCreate before super, with RNScreensFragmentFactory as required when
  using react-native-screens. The PiP and orientation broadcasts are
  unchanged
- manifest: usesCleartextTraffic placeholder; drop the debug manifest it
  supersedes
- gradle.properties: edgeToEdgeEnabled=false, since MainActivity already
  applies edge-to-edge via WindowCompat

Library module (android/):
Required independently of the template — the module did not build against
AGP 8.12 / RN 0.86:
- declare namespace 'com.jwplayer.rnjwplayer' and drop the deprecated
  package attribute from the manifest (AGP 8 requires the former and
  rejects the latter)
- com.facebook.react:react-native:+ -> react-android, and remove the
  $rootDir/../node_modules/react-native/android maven repo; that directory
  no longer exists, as RN publishes to mavenCentral now
- compileSdkVersion -> compileSdk, lintOptions -> lint, add
  buildFeatures.buildConfig, refresh stale defaults, and drop a leftover
  AGP 3.4.2 buildscript block

Deliberately not taken from the template:
- the Info.plist orientation change, which makes iPhone portrait-only —
  this app needs landscape for fullscreen playback
- App.tsx, which is the template's demo screen; this app has its own

No SDK version changes: JWPlayerKit stays 4.26.2 and IMA 3.22.1, matching
master.

Verified: iOS builds and links RNJWPlayer.app with JWPlayerKit.framework;
Android assembles app-debug.apk; both smoke tested.
The Example app's splash was misconfigured after the react-native-bootsplash
6.3.4 -> 7.3.2 bump in the RN 0.86.2 upgrade. v7 renamed its theme attributes,
so BootTheme silently configured nothing: the branded logo never appeared and
the platform drew its own icon-background circle instead, showing up as a
coloured disc where the logo should be.

Theme (values/styles.xml, values-v31/styles.xml):
- Migrate BootTheme to v7's attribute names: windowSplashScreenBackground ->
  bootSplashBackground, postSplashScreenTheme -> postBootSplashTheme, and set
  bootSplashLogo (previously unset, which is why no logo was drawn).
- Add a values-v31 BootTheme. With the theme defined only in values/, the
  platform splash screen on API 31+ did not pick up bootSplashBackground or
  bootSplashLogo at all; a green-background test confirmed the values/ theme
  was not in effect there.
- Set windowSplashScreenIconBackgroundColor explicitly. The platform picks its
  own colour for the icon circle when it is unset; matching it to the splash
  background keeps the circle invisible so only the logo shows.
- Drop the now-unused bootsplash_icon_background (#EC0041) from colors.xml.

MainActivity:
- Do not initialise react-native-bootsplash's post-splash view. On API 31+ it
  draws a large black ring where the logo should be, and it does not resolve
  ?bootSplashLogo from the theme — verified with three different logo assets
  (adaptive icon, plain PNG, BitmapDrawable wrapper), none of which changed it,
  and bootSplashBackground has no effect on it either. Disabling it removes the
  ring; the platform splash screen already shows the branded logo.
- Paint the window and decor view with the splash background. With the splash
  view gone nothing covers the window between the platform splash exiting and
  React's first render, and the bare window is black.

The dependency is kept: iOS still uses it (AppDelegate initWithStoryboard) and
works correctly, BootTheme inherits Theme.BootSplash from it, and its API 31+
attribute mapping is what makes the fix above work. Only the broken Android
code path is bypassed. The JS RNBootSplash.hide() call is left in place as a
no-op so re-enabling init later needs no JS change.

Verified on an API 36 emulator by sampling six frames across the whole splash
and measuring pixels: platform splash shows the logo on white, the gap is
white, and no frame contains black pixels. Previously the gap was a black ring
(20% dark) and, with the splash view naively removed, a fully black flash
(95-100% dark).
@octavianduminicaconnatix
octavianduminicaconnatix requested a review from a team as a code owner August 4, 2026 18:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant