Fix(android): restart issue react76 (#4302)

* fix: upgrade to expo 54
* fix: more bufferConfig inside source
- restart issue on react 0.76
- fix constness
- deprecate bufferConfig in root props
- update documentation
This commit is contained in:
Olivier Bouillet 2024-11-24 21:19:46 +01:00 committed by GitHub
parent daaac9740a
commit 2b7c215e66
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 1843 additions and 1375 deletions

View File

@ -91,9 +91,10 @@ def configStringPath = ExoplayerDependencies
.concat("buildFromSource:$media3_buildFromSource") .concat("buildFromSource:$media3_buildFromSource")
.md5() .md5()
if (isNewArchitectureEnabled()) { // commented as new architecture not yet fully supported
apply plugin: "com.facebook.react" // if (isNewArchitectureEnabled()) {
} // apply plugin: "com.facebook.react"
// }
android { android {
if (supportsNamespace()) { if (supportsNamespace()) {

View File

@ -31,11 +31,11 @@ class BufferConfig {
var targetOffsetMs: Long = BufferConfigPropUnsetInt.toLong() var targetOffsetMs: Long = BufferConfigPropUnsetInt.toLong()
companion object { companion object {
private val PROP_BUFFER_CONFIG_LIVE_MAX_PLAYBACK_SPEED = "maxPlaybackSpeed" private const val PROP_BUFFER_CONFIG_LIVE_MAX_PLAYBACK_SPEED = "maxPlaybackSpeed"
private val PROP_BUFFER_CONFIG_LIVE_MIN_PLAYBACK_SPEED = "minPlaybackSpeed" private const val PROP_BUFFER_CONFIG_LIVE_MIN_PLAYBACK_SPEED = "minPlaybackSpeed"
private val PROP_BUFFER_CONFIG_LIVE_MAX_OFFSET_MS = "maxOffsetMs" private const val PROP_BUFFER_CONFIG_LIVE_MAX_OFFSET_MS = "maxOffsetMs"
private val PROP_BUFFER_CONFIG_LIVE_MIN_OFFSET_MS = "minOffsetMs" private const val PROP_BUFFER_CONFIG_LIVE_MIN_OFFSET_MS = "minOffsetMs"
private val PROP_BUFFER_CONFIG_LIVE_TARGET_OFFSET_MS = "targetOffsetMs" private const val PROP_BUFFER_CONFIG_LIVE_TARGET_OFFSET_MS = "targetOffsetMs"
@JvmStatic @JvmStatic
fun parse(src: ReadableMap?): Live { fun parse(src: ReadableMap?): Live {
@ -54,16 +54,16 @@ class BufferConfig {
val BufferConfigPropUnsetInt = -1 val BufferConfigPropUnsetInt = -1
val BufferConfigPropUnsetDouble = -1.0 val BufferConfigPropUnsetDouble = -1.0
private val PROP_BUFFER_CONFIG_CACHE_SIZE = "cacheSizeMB" private const val PROP_BUFFER_CONFIG_CACHE_SIZE = "cacheSizeMB"
private val PROP_BUFFER_CONFIG_MIN_BUFFER_MS = "minBufferMs" private const val PROP_BUFFER_CONFIG_MIN_BUFFER_MS = "minBufferMs"
private val PROP_BUFFER_CONFIG_MAX_BUFFER_MS = "maxBufferMs" private const val PROP_BUFFER_CONFIG_MAX_BUFFER_MS = "maxBufferMs"
private val PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS = "bufferForPlaybackMs" private const val PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS = "bufferForPlaybackMs"
private val PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS = "bufferForPlaybackAfterRebufferMs" private const val PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS = "bufferForPlaybackAfterRebufferMs"
private val PROP_BUFFER_CONFIG_MAX_HEAP_ALLOCATION_PERCENT = "maxHeapAllocationPercent" private const val PROP_BUFFER_CONFIG_MAX_HEAP_ALLOCATION_PERCENT = "maxHeapAllocationPercent"
private val PROP_BUFFER_CONFIG_MIN_BACK_BUFFER_MEMORY_RESERVE_PERCENT = "minBackBufferMemoryReservePercent" private const val PROP_BUFFER_CONFIG_MIN_BACK_BUFFER_MEMORY_RESERVE_PERCENT = "minBackBufferMemoryReservePercent"
private val PROP_BUFFER_CONFIG_MIN_BUFFER_MEMORY_RESERVE_PERCENT = "minBufferMemoryReservePercent" private const val PROP_BUFFER_CONFIG_MIN_BUFFER_MEMORY_RESERVE_PERCENT = "minBufferMemoryReservePercent"
private val PROP_BUFFER_CONFIG_BACK_BUFFER_DURATION_MS = "backBufferDurationMs" private const val PROP_BUFFER_CONFIG_BACK_BUFFER_DURATION_MS = "backBufferDurationMs"
private val PROP_BUFFER_CONFIG_LIVE = "live" private const val PROP_BUFFER_CONFIG_LIVE = "live"
@JvmStatic @JvmStatic
fun parse(src: ReadableMap?): BufferConfig { fun parse(src: ReadableMap?): BufferConfig {

View File

@ -74,6 +74,11 @@ class Source {
*/ */
var adsProps: AdsProps? = null var adsProps: AdsProps? = null
/*
* buffering configuration
*/
var bufferConfig = BufferConfig()
/** /**
* The list of sideLoaded text tracks * The list of sideLoaded text tracks
*/ */
@ -95,7 +100,8 @@ class Source {
cmcdProps == other.cmcdProps && cmcdProps == other.cmcdProps &&
sideLoadedTextTracks == other.sideLoadedTextTracks && sideLoadedTextTracks == other.sideLoadedTextTracks &&
adsProps == other.adsProps && adsProps == other.adsProps &&
minLoadRetryCount == other.minLoadRetryCount minLoadRetryCount == other.minLoadRetryCount &&
bufferConfig == other.bufferConfig
) )
} }
@ -164,6 +170,7 @@ class Source {
private const val PROP_SRC_TEXT_TRACKS_ALLOW_CHUNKLESS_PREPARATION = "textTracksAllowChunklessPreparation" private const val PROP_SRC_TEXT_TRACKS_ALLOW_CHUNKLESS_PREPARATION = "textTracksAllowChunklessPreparation"
private const val PROP_SRC_TEXT_TRACKS = "textTracks" private const val PROP_SRC_TEXT_TRACKS = "textTracks"
private const val PROP_SRC_MIN_LOAD_RETRY_COUNT = "minLoadRetryCount" private const val PROP_SRC_MIN_LOAD_RETRY_COUNT = "minLoadRetryCount"
private const val PROP_SRC_BUFFER_CONFIG = "bufferConfig"
@SuppressLint("DiscouragedApi") @SuppressLint("DiscouragedApi")
private fun getUriFromAssetId(context: Context, uriString: String): Uri? { private fun getUriFromAssetId(context: Context, uriString: String): Uri? {
@ -229,6 +236,8 @@ class Source {
source.textTracksAllowChunklessPreparation = safeGetBool(src, PROP_SRC_TEXT_TRACKS_ALLOW_CHUNKLESS_PREPARATION, true) source.textTracksAllowChunklessPreparation = safeGetBool(src, PROP_SRC_TEXT_TRACKS_ALLOW_CHUNKLESS_PREPARATION, true)
source.sideLoadedTextTracks = SideLoadedTextTrackList.parse(safeGetArray(src, PROP_SRC_TEXT_TRACKS)) source.sideLoadedTextTracks = SideLoadedTextTrackList.parse(safeGetArray(src, PROP_SRC_TEXT_TRACKS))
source.minLoadRetryCount = safeGetInt(src, PROP_SRC_MIN_LOAD_RETRY_COUNT, 3) source.minLoadRetryCount = safeGetInt(src, PROP_SRC_MIN_LOAD_RETRY_COUNT, 3)
source.bufferConfig = BufferConfig.parse(safeGetMap(src, PROP_SRC_BUFFER_CONFIG))
val propSrcHeadersArray = safeGetArray(src, PROP_SRC_HEADERS) val propSrcHeadersArray = safeGetArray(src, PROP_SRC_HEADERS)
if (propSrcHeadersArray != null) { if (propSrcHeadersArray != null) {
if (propSrcHeadersArray.size() > 0) { if (propSrcHeadersArray.size() > 0) {

View File

@ -206,7 +206,6 @@ public class ReactExoplayerView extends FrameLayout implements
private float rate = 1f; private float rate = 1f;
private AudioOutput audioOutput = AudioOutput.SPEAKER; private AudioOutput audioOutput = AudioOutput.SPEAKER;
private float audioVolume = 1f; private float audioVolume = 1f;
private BufferConfig bufferConfig = new BufferConfig();
private int maxBitRate = 0; private int maxBitRate = 0;
private boolean hasDrmFailed = false; private boolean hasDrmFailed = false;
private boolean isUsingContentResolution = false; private boolean isUsingContentResolution = false;
@ -691,7 +690,7 @@ public class ReactExoplayerView extends FrameLayout implements
runtime = Runtime.getRuntime(); runtime = Runtime.getRuntime();
ActivityManager activityManager = (ActivityManager) themedReactContext.getSystemService(ThemedReactContext.ACTIVITY_SERVICE); ActivityManager activityManager = (ActivityManager) themedReactContext.getSystemService(ThemedReactContext.ACTIVITY_SERVICE);
double maxHeap = config.getMaxHeapAllocationPercent() != BufferConfig.Companion.getBufferConfigPropUnsetDouble() double maxHeap = config.getMaxHeapAllocationPercent() != BufferConfig.Companion.getBufferConfigPropUnsetDouble()
? bufferConfig.getMaxHeapAllocationPercent() ? config.getMaxHeapAllocationPercent()
: DEFAULT_MAX_HEAP_ALLOCATION_PERCENT; : DEFAULT_MAX_HEAP_ALLOCATION_PERCENT;
availableHeapInBytes = (int) Math.floor(activityManager.getMemoryClass() * maxHeap * 1024 * 1024); availableHeapInBytes = (int) Math.floor(activityManager.getMemoryClass() * maxHeap * 1024 * 1024);
} }
@ -710,8 +709,8 @@ public class ReactExoplayerView extends FrameLayout implements
} }
long usedMemory = runtime.totalMemory() - runtime.freeMemory(); long usedMemory = runtime.totalMemory() - runtime.freeMemory();
long freeMemory = runtime.maxMemory() - usedMemory; long freeMemory = runtime.maxMemory() - usedMemory;
double minBufferMemoryReservePercent = bufferConfig.getMinBufferMemoryReservePercent() != BufferConfig.Companion.getBufferConfigPropUnsetDouble() double minBufferMemoryReservePercent = source.getBufferConfig().getMinBufferMemoryReservePercent() != BufferConfig.Companion.getBufferConfigPropUnsetDouble()
? bufferConfig.getMinBufferMemoryReservePercent() ? source.getBufferConfig().getMinBufferMemoryReservePercent()
: ReactExoplayerView.DEFAULT_MIN_BUFFER_MEMORY_RESERVE; : ReactExoplayerView.DEFAULT_MIN_BUFFER_MEMORY_RESERVE;
long reserveMemory = (long) minBufferMemoryReservePercent * runtime.maxMemory(); long reserveMemory = (long) minBufferMemoryReservePercent * runtime.maxMemory();
long bufferedMs = bufferedDurationUs / (long) 1000; long bufferedMs = bufferedDurationUs / (long) 1000;
@ -743,10 +742,20 @@ public class ReactExoplayerView extends FrameLayout implements
if (runningSource.getUri() == null) { if (runningSource.getUri() == null) {
return; return;
} }
if (player == null) { if (player == null) {
// Initialize core configuration and listeners // Initialize core configuration and listeners
initializePlayerCore(self); initializePlayerCore(self);
} }
if (source.getBufferConfig().getCacheSize() > 0) {
RNVSimpleCache.INSTANCE.setSimpleCache(
this.getContext(),
source.getBufferConfig().getCacheSize()
);
useCache = true;
} else {
useCache = false;
}
if (playerNeedsSource) { if (playerNeedsSource) {
// Will force display of shutter view if needed // Will force display of shutter view if needed
exoPlayerView.updateShutterViewVisibility(); exoPlayerView.updateShutterViewVisibility();
@ -813,7 +822,7 @@ public class ReactExoplayerView extends FrameLayout implements
DefaultAllocator allocator = new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE); DefaultAllocator allocator = new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE);
RNVLoadControl loadControl = new RNVLoadControl( RNVLoadControl loadControl = new RNVLoadControl(
allocator, allocator,
bufferConfig source.getBufferConfig()
); );
DefaultRenderersFactory renderersFactory = DefaultRenderersFactory renderersFactory =
new DefaultRenderersFactory(getContext()) new DefaultRenderersFactory(getContext())
@ -1119,7 +1128,7 @@ public class ReactExoplayerView extends FrameLayout implements
} }
} }
MediaItem.LiveConfiguration.Builder liveConfiguration = ConfigurationUtils.getLiveConfiguration(bufferConfig); MediaItem.LiveConfiguration.Builder liveConfiguration = ConfigurationUtils.getLiveConfiguration(source.getBufferConfig());
mediaItemBuilder.setLiveConfiguration(liveConfiguration.build()); mediaItemBuilder.setLiveConfiguration(liveConfiguration.build());
MediaSource.Factory mediaSourceFactory; MediaSource.Factory mediaSourceFactory;
@ -2368,21 +2377,6 @@ public class ReactExoplayerView extends FrameLayout implements
exoPlayerView.setHideShutterView(hideShutterView); exoPlayerView.setHideShutterView(hideShutterView);
} }
public void setBufferConfig(BufferConfig config) {
bufferConfig = config;
if (bufferConfig.getCacheSize() > 0) {
RNVSimpleCache.INSTANCE.setSimpleCache(
this.getContext(),
bufferConfig.getCacheSize()
);
useCache = true;
} else {
useCache = false;
}
releasePlayer();
initializePlayer();
}
@Override @Override
public void onDrmKeysLoaded(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) { public void onDrmKeysLoaded(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) {
DebugLog.d("DRM Info", "onDrmKeysLoaded"); DebugLog.d("DRM Info", "onDrmKeysLoaded");

View File

@ -2,7 +2,6 @@ package com.brentvatne.exoplayer
import android.graphics.Color import android.graphics.Color
import android.util.Log import android.util.Log
import com.brentvatne.common.api.BufferConfig
import com.brentvatne.common.api.BufferingStrategy import com.brentvatne.common.api.BufferingStrategy
import com.brentvatne.common.api.ControlsConfig import com.brentvatne.common.api.ControlsConfig
import com.brentvatne.common.api.ResizeMode import com.brentvatne.common.api.ResizeMode
@ -36,7 +35,6 @@ class ReactExoplayerViewManager(private val config: ReactExoplayerConfig) : View
private const val PROP_MUTED = "muted" private const val PROP_MUTED = "muted"
private const val PROP_AUDIO_OUTPUT = "audioOutput" private const val PROP_AUDIO_OUTPUT = "audioOutput"
private const val PROP_VOLUME = "volume" private const val PROP_VOLUME = "volume"
private const val PROP_BUFFER_CONFIG = "bufferConfig"
private const val PROP_PREVENTS_DISPLAY_SLEEP_DURING_VIDEO_PLAYBACK = private const val PROP_PREVENTS_DISPLAY_SLEEP_DURING_VIDEO_PLAYBACK =
"preventsDisplaySleepDuringVideoPlayback" "preventsDisplaySleepDuringVideoPlayback"
private const val PROP_PROGRESS_UPDATE_INTERVAL = "progressUpdateInterval" private const val PROP_PROGRESS_UPDATE_INTERVAL = "progressUpdateInterval"
@ -242,12 +240,6 @@ class ReactExoplayerViewManager(private val config: ReactExoplayerConfig) : View
videoView.setShutterColor(color) videoView.setShutterColor(color)
} }
@ReactProp(name = PROP_BUFFER_CONFIG)
fun setBufferConfig(videoView: ReactExoplayerView, bufferConfig: ReadableMap?) {
val config = BufferConfig.parse(bufferConfig)
videoView.setBufferConfig(config)
}
@ReactProp(name = PROP_SHOW_NOTIFICATION_CONTROLS) @ReactProp(name = PROP_SHOW_NOTIFICATION_CONTROLS)
fun setShowNotificationControls(videoView: ReactExoplayerView, showNotificationControls: Boolean) { fun setShowNotificationControls(videoView: ReactExoplayerView, showNotificationControls: Boolean) {
videoView.setShowNotificationControls(showNotificationControls) videoView.setShowNotificationControls(showNotificationControls)

View File

@ -52,6 +52,9 @@ A Boolean value that indicates whether the player should automatically delay pla
### `bufferConfig` ### `bufferConfig`
> [!WARNING]
> Deprecated, use source.bufferConfig instead
<PlatformsList types={['Android']} /> <PlatformsList types={['Android']} />
Adjust the buffer settings. This prop takes an object with one or more of the properties listed below. Adjust the buffer settings. This prop takes an object with one or more of the properties listed below.
@ -907,6 +910,56 @@ source={{
}} }}
``` ```
### `bufferConfig`
<PlatformsList types={['Android']} />
Adjust the buffer settings. This prop takes an object with one or more of the properties listed below.
| Property | Type | Description |
| --------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| minBufferMs | number | The default minimum duration of media that the player will attempt to ensure is buffered at all times, in milliseconds. |
| maxBufferMs | number | The default maximum duration of media that the player will attempt to buffer, in milliseconds. |
| bufferForPlaybackMs | number | The default duration of media that must be buffered for playback to start or resume following a user action such as a seek, in milliseconds. |
| bufferForPlaybackAfterRebufferMs | number | The default duration of media that must be buffered for playback to resume after a rebuffer, in milliseconds. A rebuffer is defined to be caused by buffer depletion rather than a user action. |
| backBufferDurationMs | number | The number of milliseconds of buffer to keep before the current position. This allows rewinding without rebuffering within that duration. |
| maxHeapAllocationPercent | number | The percentage of available heap that the video can use to buffer, between 0 and 1 |
| minBackBufferMemoryReservePercent | number | The percentage of available app memory at which during startup the back buffer will be disabled, between 0 and 1 |
| minBufferMemoryReservePercent | number | The percentage of available app memory to keep in reserve that prevents buffer from using it, between 0 and 1 |
| cacheSizeMB | number | Cache size in MB, enabling this to prevent new src requests and save bandwidth while repeating videos, or 0 to disable. Android only. |
| live | object | Object containing another config set for live playback configuration, see next table |
Description of live object:
| Property | Type | Description |
| --------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| maxPlaybackSpeed | number | The maximum playback speed the player can use to catch up when trying to reach the target live offset. |
| minPlaybackSpeed | number | The minimum playback speed the player can use to fall back when trying to reach the target live offset. |
| maxOffsetMs | number | The maximum allowed live offset. Even when adjusting the offset to current network conditions, the player will not attempt to get above this offset during playback. |
| minOffsetMs | number | The minimum allowed live offset. Even when adjusting the offset to current network conditions, the player will not attempt to get below this offset during playback. |
| targetOffsetMs | number | The target live offset. The player will attempt to get close to this live offset during playback if possible. |
For android, more informations about live configuration can be find [here](https://developer.android.com/media/media3/exoplayer/live-streaming?hl=en)
Example with default values:
```javascript
bufferConfig={{
minBufferMs: 15000,
maxBufferMs: 50000,
bufferForPlaybackMs: 2500,
bufferForPlaybackAfterRebufferMs: 5000,
backBufferDurationMs: 120000,
cacheSizeMB: 0,
live: {
targetOffsetMs: 500,
},
}}
```
Please note that the Android cache is a global cache that is shared among all components; individual components can still opt out of caching behavior by setting cacheSizeMB to 0, but multiple components with a positive cacheSizeMB will be sharing the same one, and the cache size will always be the first value set; it will not change during the app's lifecycle.
#### `minLoadRetryCount` #### `minLoadRetryCount`
<PlatformsList types={['Android']} /> <PlatformsList types={['Android']} />

View File

@ -240,7 +240,7 @@ const BasicExample = () => {
}; };
useEffect(() => { useEffect(() => {
videoRef.current?.setSource(currentSrc); videoRef.current?.setSource({...currentSrc, bufferConfig: _bufferConfig });
}, [currentSrc]); }, [currentSrc]);
return ( return (
@ -284,7 +284,6 @@ const BasicExample = () => {
selectedAudioTrack={selectedAudioTrack} selectedAudioTrack={selectedAudioTrack}
selectedVideoTrack={selectedVideoTrack} selectedVideoTrack={selectedVideoTrack}
playInBackground={false} playInBackground={false}
bufferConfig={_bufferConfig}
preventsDisplaySleepDuringVideoPlayback={true} preventsDisplaySleepDuringVideoPlayback={true}
renderLoader={_renderLoader} renderLoader={_renderLoader}
onPlaybackRateChange={onPlaybackRateChange} onPlaybackRateChange={onPlaybackRateChange}

View File

@ -11,6 +11,7 @@ import com.facebook.react.ReactPackage
import com.facebook.react.ReactHost import com.facebook.react.ReactHost
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactNativeHost import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.react.soloader.OpenSourceMergedSoMapping
import com.facebook.soloader.SoLoader import com.facebook.soloader.SoLoader
import expo.modules.ApplicationLifecycleDispatcher import expo.modules.ApplicationLifecycleDispatcher
@ -42,7 +43,7 @@ class MainApplication : Application(), ReactApplication {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
SoLoader.init(this, false) SoLoader.init(this, OpenSourceMergedSoMapping)
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
// If you opted-in for the New Architecture, we load the native entry point for this app. // If you opted-in for the New Architecture, we load the native entry point for this app.
load() load()

View File

@ -2,11 +2,11 @@
buildscript { buildscript {
ext { ext {
buildToolsVersion = findProperty('android.buildToolsVersion') ?: '34.0.0' buildToolsVersion = findProperty('android.buildToolsVersion') ?: '35.0.0'
minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '23') minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '24')
compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '34') compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '35')
targetSdkVersion = Integer.parseInt(findProperty('android.targetSdkVersion') ?: '34') targetSdkVersion = Integer.parseInt(findProperty('android.targetSdkVersion') ?: '35')
kotlinVersion = findProperty('android.kotlinVersion') ?: '1.9.23' kotlinVersion = findProperty('android.kotlinVersion') ?: '1.9.24'
ndkVersion = "26.1.10909125" ndkVersion = "26.1.10909125"
} }

View File

@ -22,9 +22,6 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
# https://developer.android.com/topic/libraries/support-library/androidx-rn # https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
# Enable AAPT2 PNG crunching # Enable AAPT2 PNG crunching
android.enablePngCrunchInReleaseBuilds=true android.enablePngCrunchInReleaseBuilds=true
@ -38,7 +35,7 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
# your application. You should enable this flag either if you want # your application. You should enable this flag either if you want
# to write custom TurboModules/Fabric components OR use libraries that # to write custom TurboModules/Fabric components OR use libraries that
# are providing them. # are providing them.
newArchEnabled=false newArchEnabled=true
# Use this property to enable or disable the Hermes JS engine. # Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead. # If set to false, you will be using JSC instead.

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

@ -8,6 +8,7 @@ pluginManagement {
if(reactNativeMinor == 74 && reactNativePatch <= 3){ if(reactNativeMinor == 74 && reactNativePatch <= 3){
includeBuild("react-settings-plugin") includeBuild("react-settings-plugin")
} }
includeBuild("../node_modules/@react-native/gradle-plugin")
} }
plugins { id("com.facebook.react.settings") } plugins { id("com.facebook.react.settings") }

View File

@ -11,8 +11,8 @@
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; }; 3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; };
69D28F37B56772B7A9D5E544 /* libPods-ExpoExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C65020CA55EC90CEE9A23ED2 /* libPods-ExpoExample.a */; };
6E3E1907139F4681BB29BA3F /* noop-file.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1CD8985E3A84FEF8F310E21 /* noop-file.swift */; }; 6E3E1907139F4681BB29BA3F /* noop-file.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1CD8985E3A84FEF8F310E21 /* noop-file.swift */; };
96905EF65AED1B983A6B3ABC /* libPods-ExpoExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-ExpoExample.a */; };
B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; }; B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; };
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; }; BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; };
F6DD9B61853ED7F5FE2C32F9 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3BCFB4767DA89C6653566DA4 /* PrivacyInfo.xcprivacy */; }; F6DD9B61853ED7F5FE2C32F9 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3BCFB4767DA89C6653566DA4 /* PrivacyInfo.xcprivacy */; };
@ -26,12 +26,12 @@
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ExpoExample/Info.plist; sourceTree = "<group>"; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ExpoExample/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ExpoExample/main.m; sourceTree = "<group>"; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ExpoExample/main.m; sourceTree = "<group>"; };
3BCFB4767DA89C6653566DA4 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = ExpoExample/PrivacyInfo.xcprivacy; sourceTree = "<group>"; }; 3BCFB4767DA89C6653566DA4 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = ExpoExample/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
58EEBF8E8E6FB1BC6CAF49B5 /* libPods-ExpoExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ExpoExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 5762883CF0477CB8DEB074D2 /* Pods-ExpoExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExpoExample.debug.xcconfig"; path = "Target Support Files/Pods-ExpoExample/Pods-ExpoExample.debug.xcconfig"; sourceTree = "<group>"; };
6C2E3173556A471DD304B334 /* Pods-ExpoExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExpoExample.debug.xcconfig"; path = "Target Support Files/Pods-ExpoExample/Pods-ExpoExample.debug.xcconfig"; sourceTree = "<group>"; }; 9C0AF52D744330C1CAD2989E /* Pods-ExpoExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExpoExample.release.xcconfig"; path = "Target Support Files/Pods-ExpoExample/Pods-ExpoExample.release.xcconfig"; sourceTree = "<group>"; };
7A4D352CD337FB3A3BF06240 /* Pods-ExpoExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExpoExample.release.xcconfig"; path = "Target Support Files/Pods-ExpoExample/Pods-ExpoExample.release.xcconfig"; sourceTree = "<group>"; };
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = ExpoExample/SplashScreen.storyboard; sourceTree = "<group>"; }; AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = ExpoExample/SplashScreen.storyboard; sourceTree = "<group>"; };
B7DF2D7F8A384D51B801CEE7 /* ExpoExample-Bridging-Header.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = "ExpoExample-Bridging-Header.h"; path = "ExpoExample/ExpoExample-Bridging-Header.h"; sourceTree = "<group>"; }; B7DF2D7F8A384D51B801CEE7 /* ExpoExample-Bridging-Header.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = "ExpoExample-Bridging-Header.h"; path = "ExpoExample/ExpoExample-Bridging-Header.h"; sourceTree = "<group>"; };
BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = "<group>"; }; BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = "<group>"; };
C65020CA55EC90CEE9A23ED2 /* libPods-ExpoExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ExpoExample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
E1CD8985E3A84FEF8F310E21 /* noop-file.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "noop-file.swift"; path = "ExpoExample/noop-file.swift"; sourceTree = "<group>"; }; E1CD8985E3A84FEF8F310E21 /* noop-file.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "noop-file.swift"; path = "ExpoExample/noop-file.swift"; sourceTree = "<group>"; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-ExpoExample/ExpoModulesProvider.swift"; sourceTree = "<group>"; }; FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-ExpoExample/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
@ -42,7 +42,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
96905EF65AED1B983A6B3ABC /* libPods-ExpoExample.a in Frameworks */, 69D28F37B56772B7A9D5E544 /* libPods-ExpoExample.a in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -70,7 +70,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
ED297162215061F000B7C4FE /* JavaScriptCore.framework */, ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
58EEBF8E8E6FB1BC6CAF49B5 /* libPods-ExpoExample.a */, C65020CA55EC90CEE9A23ED2 /* libPods-ExpoExample.a */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
@ -125,8 +125,8 @@
D65327D7A22EEC0BE12398D9 /* Pods */ = { D65327D7A22EEC0BE12398D9 /* Pods */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
6C2E3173556A471DD304B334 /* Pods-ExpoExample.debug.xcconfig */, 5762883CF0477CB8DEB074D2 /* Pods-ExpoExample.debug.xcconfig */,
7A4D352CD337FB3A3BF06240 /* Pods-ExpoExample.release.xcconfig */, 9C0AF52D744330C1CAD2989E /* Pods-ExpoExample.release.xcconfig */,
); );
path = Pods; path = Pods;
sourceTree = "<group>"; sourceTree = "<group>";
@ -146,14 +146,14 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ExpoExample" */; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ExpoExample" */;
buildPhases = ( buildPhases = (
08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */, EBDF7B38F7D33D49CA2B39C6 /* [CP] Check Pods Manifest.lock */,
6E9FB0155D627BF633A3CB08 /* [Expo] Configure project */, 6E9FB0155D627BF633A3CB08 /* [Expo] Configure project */,
13B07F871A680F5B00A75B9A /* Sources */, 13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */, 13B07F8E1A680F5B00A75B9A /* Resources */,
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */, 2ECC1AFFBE97E107FF88D15D /* [CP] Embed Pods Frameworks */,
CED90EB9939E56B1E5D48A24 /* [CP] Embed Pods Frameworks */, DC89C28FF1E7E51E27603886 /* [CP] Copy Pods Resources */,
); );
buildRules = ( buildRules = (
); );
@ -225,26 +225,22 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" \"$PROJECT_ROOT\" ios absolute | tail -n 1)\"\nfi\n\nif [[ -z \"$CLI_PATH\" ]]; then\n # Use Expo CLI\n export CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })\")\"\nfi\nif [[ -z \"$BUNDLE_COMMAND\" ]]; then\n # Default Expo CLI command for bundling\n export BUNDLE_COMMAND=\"export:embed\"\nfi\n\n# Source .xcode.env.updates if it exists to allow\n# SKIP_BUNDLING to be unset if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.updates\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.updates\"\nfi\n# Source local changes to allow overrides\n# if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n`\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n\n"; shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" \"$PROJECT_ROOT\" ios absolute | tail -n 1)\"\nfi\n\nif [[ -z \"$CLI_PATH\" ]]; then\n # Use Expo CLI\n export CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })\")\"\nfi\nif [[ -z \"$BUNDLE_COMMAND\" ]]; then\n # Default Expo CLI command for bundling\n export BUNDLE_COMMAND=\"export:embed\"\nfi\n\n# Source .xcode.env.updates if it exists to allow\n# SKIP_BUNDLING to be unset if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.updates\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.updates\"\nfi\n# Source local changes to allow overrides\n# if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n`\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n\n";
}; };
08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */ = { 2ECC1AFFBE97E107FF88D15D /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputFileListPaths = (
);
inputPaths = ( inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Target Support Files/Pods-ExpoExample/Pods-ExpoExample-frameworks.sh",
"${PODS_ROOT}/Manifest.lock", "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
); );
name = "[CP] Embed Pods Frameworks";
outputPaths = ( outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-ExpoExample-checkManifestLockResult.txt", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ExpoExample/Pods-ExpoExample-frameworks.sh\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
6E9FB0155D627BF633A3CB08 /* [Expo] Configure project */ = { 6E9FB0155D627BF633A3CB08 /* [Expo] Configure project */ = {
@ -266,7 +262,7 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-ExpoExample/expo-configure-project.sh\"\n"; shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-ExpoExample/expo-configure-project.sh\"\n";
}; };
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */ = { DC89C28FF1E7E51E27603886 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
@ -276,36 +272,48 @@
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/ExpoConstants_privacy.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/ExpoConstants_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/RCTI18nStrings.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/boost/boost_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/glog/glog_privacy.bundle",
); );
name = "[CP] Copy Pods Resources"; name = "[CP] Copy Pods Resources";
outputPaths = ( outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoConstants_privacy.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoConstants_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCTI18nStrings.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/boost_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/glog_privacy.bundle",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ExpoExample/Pods-ExpoExample-resources.sh\"\n"; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ExpoExample/Pods-ExpoExample-resources.sh\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
CED90EB9939E56B1E5D48A24 /* [CP] Embed Pods Frameworks */ = { EBDF7B38F7D33D49CA2B39C6 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputPaths = ( inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-ExpoExample/Pods-ExpoExample-frameworks.sh", );
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
); );
name = "[CP] Embed Pods Frameworks";
outputPaths = ( outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", "$(DERIVED_FILE_DIR)/Pods-ExpoExample-checkManifestLockResult.txt",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ExpoExample/Pods-ExpoExample-frameworks.sh\"\n"; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
/* End PBXShellScriptBuildPhase section */ /* End PBXShellScriptBuildPhase section */
@ -327,7 +335,7 @@
/* Begin XCBuildConfiguration section */ /* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = { 13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 6C2E3173556A471DD304B334 /* Pods-ExpoExample.debug.xcconfig */; baseConfigurationReference = 5762883CF0477CB8DEB074D2 /* Pods-ExpoExample.debug.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
@ -339,7 +347,7 @@
"FB_SONARKIT_ENABLED=1", "FB_SONARKIT_ENABLED=1",
); );
INFOPLIST_FILE = ExpoExample/Info.plist; INFOPLIST_FILE = ExpoExample/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 15.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
@ -360,14 +368,14 @@
}; };
13B07F951A680F5B00A75B9A /* Release */ = { 13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 7A4D352CD337FB3A3BF06240 /* Pods-ExpoExample.release.xcconfig */; baseConfigurationReference = 9C0AF52D744330C1CAD2989E /* Pods-ExpoExample.release.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = ExpoExample/ExpoExample.entitlements; CODE_SIGN_ENTITLEMENTS = ExpoExample/ExpoExample.entitlements;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
INFOPLIST_FILE = ExpoExample/Info.plist; INFOPLIST_FILE = ExpoExample/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 15.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
@ -434,7 +442,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 15.1;
LD = ""; LD = "";
LDPLUSPLUS = ""; LDPLUSPLUS = "";
LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)";
@ -447,6 +455,7 @@
); );
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
USE_HERMES = true; USE_HERMES = true;
}; };
name = Debug; name = Debug;
@ -493,7 +502,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 15.1;
LD = ""; LD = "";
LDPLUSPLUS = ""; LDPLUSPLUS = "";
LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)";

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
{ {
"expo.jsEngine": "hermes", "expo.jsEngine": "hermes",
"EX_DEV_CLIENT_NETWORK_INSPECTOR": "true" "EX_DEV_CLIENT_NETWORK_INSPECTOR": "true",
"ios.deploymentTarget": "15.1"
} }

View File

@ -12,25 +12,40 @@
"web": "expo start --web", "web": "expo start --web",
"prebuild:tv": "EXPO_TV=1 expo prebuild", "prebuild:tv": "EXPO_TV=1 expo prebuild",
"prebuild": "EXPO_TV=0 expo prebuild", "prebuild": "EXPO_TV=0 expo prebuild",
"update-src": "echo 'Updating src from ../bare/src' && rm -r ./src && cp -r ../bare/src ./src && echo 'Updated src from ../bare/src'" "update-src": "echo 'Updating src from ../bare/src' && rm -r ./src && cp -r ../bare/src ./src && echo 'Updated src from ../bare/src'",
"clean": "rm -rf node_modules && rm -rf android/build/ && rm -rf android/app/build && rm -rf ./lib @@ rm -rf ./android/.gradle && rm -rf ./android/.idea && rm -rf ./.expo"
}, },
"dependencies": { "dependencies": {
"@expo/metro-runtime": "^3.2.3", "@expo/metro-runtime": "~4.0.0",
"@react-native-picker/picker": "2.8.1", "@react-native-picker/picker": "2.9.0",
"expo": "~51.0.39", "expo": "^52.0.7",
"expo-splash-screen": "~0.27.7", "expo-splash-screen": "~0.29.10",
"expo-status-bar": "~1.12.1", "expo-status-bar": "~2.0.0",
"react": "18.2.0", "react": "18.3.1",
"react-dom": "18.2.0", "react-dom": "18.3.1",
"react-native": "npm:react-native-tvos@~0.74.5-0", "react-native": "npm:react-native-tvos@0.76.2-0",
"react-native-web": "^0.19.13" "react-native-web": "^0.19.13"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.24.0", "@babel/core": "^7.25.2",
"@expo/config-plugins": "^8.0.10", "@babel/preset-env": "^7.25.3",
"@babel/runtime": "^7.25.0",
"@react-native-community/cli": "15.0.1",
"@react-native-community/cli-platform-android": "15.0.1",
"@react-native-community/cli-platform-ios": "15.0.1",
"@react-native/babel-preset": "0.76.3",
"@react-native/eslint-config": "0.76.3",
"@react-native/metro-config": "0.76.3",
"@react-native/typescript-config": "0.76.3",
"@types/react": "^18.2.6",
"@types/react-test-renderer": "^18.0.0",
"babel-jest": "^29.6.3",
"eslint": "^8.19.0",
"jest": "^29.6.3",
"prettier": "2.8.8",
"react-test-renderer": "18.3.1",
"@expo/config-plugins": "^9.0.9",
"@react-native-tvos/config-tv": "^0.0.10", "@react-native-tvos/config-tv": "^0.0.10",
"@react-native/metro-config": "^0.75.4",
"@types/react": "~18.2.45",
"babel-plugin-module-resolver": "^5.0.2", "babel-plugin-module-resolver": "^5.0.2",
"typescript": "~5.3.3" "typescript": "~5.3.3"
}, },

View File

@ -240,7 +240,7 @@ const BasicExample = () => {
}; };
useEffect(() => { useEffect(() => {
videoRef.current?.setSource(currentSrc); videoRef.current?.setSource({...currentSrc, bufferConfig: _bufferConfig });
}, [currentSrc]); }, [currentSrc]);
return ( return (
@ -284,7 +284,6 @@ const BasicExample = () => {
selectedAudioTrack={selectedAudioTrack} selectedAudioTrack={selectedAudioTrack}
selectedVideoTrack={selectedVideoTrack} selectedVideoTrack={selectedVideoTrack}
playInBackground={false} playInBackground={false}
bufferConfig={_bufferConfig}
preventsDisplaySleepDuringVideoPlayback={true} preventsDisplaySleepDuringVideoPlayback={true}
renderLoader={_renderLoader} renderLoader={_renderLoader}
onPlaybackRateChange={onPlaybackRateChange} onPlaybackRateChange={onPlaybackRateChange}

View File

@ -108,6 +108,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
onAspectRatio, onAspectRatio,
localSourceEncryptionKeyScheme, localSourceEncryptionKeyScheme,
minLoadRetryCount, minLoadRetryCount,
bufferConfig,
...rest ...rest
}, },
ref, ref,
@ -219,6 +220,8 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
const _minLoadRetryCount = const _minLoadRetryCount =
_source.minLoadRetryCount || minLoadRetryCount; _source.minLoadRetryCount || minLoadRetryCount;
const _bufferConfig = _source.bufferConfig || bufferConfig;
return { return {
uri, uri,
isNetwork, isNetwork,
@ -240,6 +243,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
textTracksAllowChunklessPreparation: textTracksAllowChunklessPreparation:
resolvedSource.textTracksAllowChunklessPreparation, resolvedSource.textTracksAllowChunklessPreparation,
minLoadRetryCount: _minLoadRetryCount, minLoadRetryCount: _minLoadRetryCount,
bufferConfig: _bufferConfig,
}; };
}, },
[ [
@ -251,6 +255,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
minLoadRetryCount, minLoadRetryCount,
source?.cmcd, source?.cmcd,
textTracks, textTracks,
bufferConfig,
], ],
); );

View File

@ -51,6 +51,7 @@ export type VideoSrc = Readonly<{
textTracks?: TextTracks; textTracks?: TextTracks;
ad?: AdsConfig; ad?: AdsConfig;
minLoadRetryCount?: Int32; // Android minLoadRetryCount?: Int32; // Android
bufferConfig?: BufferConfig; // Android
}>; }>;
type DRMType = WithDefault<string, 'widevine'>; type DRMType = WithDefault<string, 'widevine'>;
@ -358,7 +359,6 @@ export interface VideoNativeProps extends ViewProps {
restoreUserInterfaceForPIPStopCompletionHandler?: boolean; restoreUserInterfaceForPIPStopCompletionHandler?: boolean;
debug?: DebugConfig; debug?: DebugConfig;
showNotificationControls?: WithDefault<boolean, false>; // Android, iOS showNotificationControls?: WithDefault<boolean, false>; // Android, iOS
bufferConfig?: BufferConfig; // Android
currentPlaybackTime?: Double; // Android currentPlaybackTime?: Double; // Android
disableDisconnectError?: boolean; // Android disableDisconnectError?: boolean; // Android
focusable?: boolean; // Android focusable?: boolean; // Android

View File

@ -40,6 +40,7 @@ export type ReactVideoSourceProperties = {
textTracks?: TextTracks; textTracks?: TextTracks;
ad?: AdConfig; ad?: AdConfig;
minLoadRetryCount?: number; // Android minLoadRetryCount?: number; // Android
bufferConfig?: BufferConfig;
}; };
export type ReactVideoSource = Readonly< export type ReactVideoSource = Readonly<
@ -289,6 +290,7 @@ export interface ReactVideoProps extends ReactVideoEvents, ViewProps {
adLanguage?: ISO639_1; adLanguage?: ISO639_1;
audioOutput?: AudioOutput; // Mobile audioOutput?: AudioOutput; // Mobile
automaticallyWaitsToMinimizeStalling?: boolean; // iOS automaticallyWaitsToMinimizeStalling?: boolean; // iOS
/** @deprecated Use source.bufferConfig */
bufferConfig?: BufferConfig; // Android bufferConfig?: BufferConfig; // Android
bufferingStrategy?: BufferingStrategyType; bufferingStrategy?: BufferingStrategyType;
chapters?: Chapters[]; // iOS chapters?: Chapters[]; // iOS