Fix for files that are stored in the Documents folder on iOS (and not as resources in the JS app)

This commit is contained in:
Ash Mishra 2018-08-16 15:32:36 -07:00
parent 887010f291
commit f7fd5dc5b7

View File

@ -129,24 +129,24 @@ static int const RCTVideoUnset = -1;
- (CMTime)playerItemDuration - (CMTime)playerItemDuration
{ {
AVPlayerItem *playerItem = [_player currentItem]; AVPlayerItem *playerItem = [_player currentItem];
if (playerItem.status == AVPlayerItemStatusReadyToPlay) if (playerItem.status == AVPlayerItemStatusReadyToPlay)
{ {
return([playerItem duration]); return([playerItem duration]);
} }
return(kCMTimeInvalid); return(kCMTimeInvalid);
} }
- (CMTimeRange)playerItemSeekableTimeRange - (CMTimeRange)playerItemSeekableTimeRange
{ {
AVPlayerItem *playerItem = [_player currentItem]; AVPlayerItem *playerItem = [_player currentItem];
if (playerItem.status == AVPlayerItemStatusReadyToPlay) if (playerItem.status == AVPlayerItemStatusReadyToPlay)
{ {
return [playerItem seekableTimeRanges].firstObject.CMTimeRangeValue; return [playerItem seekableTimeRanges].firstObject.CMTimeRangeValue;
} }
return (kCMTimeRangeZero); return (kCMTimeRangeZero);
} }
-(void)addPlayerTimeObserver -(void)addPlayerTimeObserver
@ -164,11 +164,11 @@ static int const RCTVideoUnset = -1;
/* Cancels the previously registered time observer. */ /* Cancels the previously registered time observer. */
-(void)removePlayerTimeObserver -(void)removePlayerTimeObserver
{ {
if (_timeObserver) if (_timeObserver)
{ {
[_player removeTimeObserver:_timeObserver]; [_player removeTimeObserver:_timeObserver];
_timeObserver = nil; _timeObserver = nil;
} }
} }
#pragma mark - Progress #pragma mark - Progress
@ -211,43 +211,43 @@ static int const RCTVideoUnset = -1;
- (void)audioRouteChanged:(NSNotification *)notification - (void)audioRouteChanged:(NSNotification *)notification
{ {
NSNumber *reason = [[notification userInfo] objectForKey:AVAudioSessionRouteChangeReasonKey]; NSNumber *reason = [[notification userInfo] objectForKey:AVAudioSessionRouteChangeReasonKey];
NSNumber *previousRoute = [[notification userInfo] objectForKey:AVAudioSessionRouteChangePreviousRouteKey]; NSNumber *previousRoute = [[notification userInfo] objectForKey:AVAudioSessionRouteChangePreviousRouteKey];
if (reason.unsignedIntValue == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) { if (reason.unsignedIntValue == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
self.onVideoAudioBecomingNoisy(@{@"target": self.reactTag}); self.onVideoAudioBecomingNoisy(@{@"target": self.reactTag});
} }
} }
#pragma mark - Progress #pragma mark - Progress
- (void)sendProgressUpdate - (void)sendProgressUpdate
{ {
AVPlayerItem *video = [_player currentItem]; AVPlayerItem *video = [_player currentItem];
if (video == nil || video.status != AVPlayerItemStatusReadyToPlay) { if (video == nil || video.status != AVPlayerItemStatusReadyToPlay) {
return; return;
} }
CMTime playerDuration = [self playerItemDuration]; CMTime playerDuration = [self playerItemDuration];
if (CMTIME_IS_INVALID(playerDuration)) { if (CMTIME_IS_INVALID(playerDuration)) {
return; return;
} }
CMTime currentTime = _player.currentTime; CMTime currentTime = _player.currentTime;
const Float64 duration = CMTimeGetSeconds(playerDuration); const Float64 duration = CMTimeGetSeconds(playerDuration);
const Float64 currentTimeSecs = CMTimeGetSeconds(currentTime); const Float64 currentTimeSecs = CMTimeGetSeconds(currentTime);
[[NSNotificationCenter defaultCenter] postNotificationName:@"RCTVideo_progress" object:nil userInfo:@{@"progress": [NSNumber numberWithDouble: currentTimeSecs / duration]}]; [[NSNotificationCenter defaultCenter] postNotificationName:@"RCTVideo_progress" object:nil userInfo:@{@"progress": [NSNumber numberWithDouble: currentTimeSecs / duration]}];
if( currentTimeSecs >= 0 && self.onVideoProgress) { if( currentTimeSecs >= 0 && self.onVideoProgress) {
self.onVideoProgress(@{ self.onVideoProgress(@{
@"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(currentTime)], @"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(currentTime)],
@"playableDuration": [self calculatePlayableDuration], @"playableDuration": [self calculatePlayableDuration],
@"atValue": [NSNumber numberWithLongLong:currentTime.value], @"atValue": [NSNumber numberWithLongLong:currentTime.value],
@"atTimescale": [NSNumber numberWithInt:currentTime.timescale], @"atTimescale": [NSNumber numberWithInt:currentTime.timescale],
@"target": self.reactTag, @"target": self.reactTag,
@"seekableDuration": [self calculateSeekableDuration], @"seekableDuration": [self calculateSeekableDuration],
}); });
} }
} }
/*! /*!
@ -277,12 +277,12 @@ static int const RCTVideoUnset = -1;
- (NSNumber *)calculateSeekableDuration - (NSNumber *)calculateSeekableDuration
{ {
CMTimeRange timeRange = [self playerItemSeekableTimeRange]; CMTimeRange timeRange = [self playerItemSeekableTimeRange];
if (CMTIME_IS_NUMERIC(timeRange.duration)) if (CMTIME_IS_NUMERIC(timeRange.duration))
{ {
return [NSNumber numberWithFloat:CMTimeGetSeconds(timeRange.duration)]; return [NSNumber numberWithFloat:CMTimeGetSeconds(timeRange.duration)];
} }
return [NSNumber numberWithInteger:0]; return [NSNumber numberWithInteger:0];
} }
- (void)addPlayerItemObservers - (void)addPlayerItemObservers
@ -346,11 +346,11 @@ static int const RCTVideoUnset = -1;
id uri = [source objectForKey:@"uri"]; id uri = [source objectForKey:@"uri"];
id type = [source objectForKey:@"type"]; id type = [source objectForKey:@"type"];
self.onVideoLoadStart(@{@"src": @{ self.onVideoLoadStart(@{@"src": @{
@"uri": uri ? uri : [NSNull null], @"uri": uri ? uri : [NSNull null],
@"type": type ? type : [NSNull null], @"type": type ? type : [NSNull null],
@"isNetwork": [NSNumber numberWithBool:(bool)[source objectForKey:@"isNetwork"]]}, @"isNetwork": [NSNumber numberWithBool:(bool)[source objectForKey:@"isNetwork"]]},
@"target": self.reactTag @"target": self.reactTag
}); });
} }
}); });
@ -358,7 +358,7 @@ static int const RCTVideoUnset = -1;
} }
- (NSURL*) urlFilePath:(NSString*) filepath { - (NSURL*) urlFilePath:(NSString*) filepath {
if ([filepath containsString:@"file://"]) { if ([filepath containsString:@"file://"] && ![filepath containsString:@"/Documents/"]) {
return [NSURL URLWithString:filepath]; return [NSURL URLWithString:filepath];
} }
@ -391,11 +391,11 @@ static int const RCTVideoUnset = -1;
if (isNetwork) { if (isNetwork) {
/* Per #1091, this is not a public API. We need to either get approval from Apple to use this /* Per #1091, this is not a public API. We need to either get approval from Apple to use this
* or use a different approach. * or use a different approach.
NSDictionary *headers = [source objectForKey:@"requestHeaders"]; NSDictionary *headers = [source objectForKey:@"requestHeaders"];
if ([headers count] > 0) { if ([headers count] > 0) {
[assetOptions setObject:headers forKey:@"AVURLAssetHTTPHeaderFieldsKey"]; [assetOptions setObject:headers forKey:@"AVURLAssetHTTPHeaderFieldsKey"];
} }
*/ */
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]; NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
[assetOptions setObject:cookies forKey:AVURLAssetHTTPCookiesKey]; [assetOptions setObject:cookies forKey:AVURLAssetHTTPCookiesKey];
asset = [AVURLAsset URLAssetWithURL:[NSURL URLWithString:uri] options:assetOptions]; asset = [AVURLAsset URLAssetWithURL:[NSURL URLWithString:uri] options:assetOptions];
@ -442,9 +442,9 @@ static int const RCTVideoUnset = -1;
addMutableTrackWithMediaType:AVMediaTypeText addMutableTrackWithMediaType:AVMediaTypeText
preferredTrackID:kCMPersistentTrackID_Invalid]; preferredTrackID:kCMPersistentTrackID_Invalid];
[textCompTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.timeRange.duration) [textCompTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.timeRange.duration)
ofTrack:textTrackAsset ofTrack:textTrackAsset
atTime:kCMTimeZero atTime:kCMTimeZero
error:nil]; error:nil];
} }
if (validTextTracks.count != _textTracks.count) { if (validTextTracks.count != _textTracks.count) {
[self setTextTracks:validTextTracks]; [self setTextTracks:validTextTracks];
@ -602,7 +602,7 @@ static int const RCTVideoUnset = -1;
- (void)playerItemDidReachEnd:(NSNotification *)notification - (void)playerItemDidReachEnd:(NSNotification *)notification
{ {
if(self.onVideoEnd) { if(self.onVideoEnd) {
self.onVideoEnd(@{@"target": self.reactTag}); self.onVideoEnd(@{@"target": self.reactTag});
} }
if (_repeat) { if (_repeat) {
@ -636,8 +636,8 @@ static int const RCTVideoUnset = -1;
- (void)setAllowsExternalPlayback:(BOOL)allowsExternalPlayback - (void)setAllowsExternalPlayback:(BOOL)allowsExternalPlayback
{ {
_allowsExternalPlayback = allowsExternalPlayback; _allowsExternalPlayback = allowsExternalPlayback;
_player.allowsExternalPlayback = _allowsExternalPlayback; _player.allowsExternalPlayback = _allowsExternalPlayback;
} }
- (void)setPlayWhenInactive:(BOOL)playWhenInactive - (void)setPlayWhenInactive:(BOOL)playWhenInactive
@ -770,52 +770,52 @@ static int const RCTVideoUnset = -1;
- (void)setMediaSelectionTrackForCharacteristic:(AVMediaCharacteristic)characteristic - (void)setMediaSelectionTrackForCharacteristic:(AVMediaCharacteristic)characteristic
withCriteria:(NSDictionary *)criteria withCriteria:(NSDictionary *)criteria
{ {
NSString *type = criteria[@"type"]; NSString *type = criteria[@"type"];
AVMediaSelectionGroup *group = [_player.currentItem.asset AVMediaSelectionGroup *group = [_player.currentItem.asset
mediaSelectionGroupForMediaCharacteristic:characteristic]; mediaSelectionGroupForMediaCharacteristic:characteristic];
AVMediaSelectionOption *mediaOption; AVMediaSelectionOption *mediaOption;
if ([type isEqualToString:@"disabled"]) { if ([type isEqualToString:@"disabled"]) {
// Do nothing. We want to ensure option is nil // Do nothing. We want to ensure option is nil
} else if ([type isEqualToString:@"language"] || [type isEqualToString:@"title"]) { } else if ([type isEqualToString:@"language"] || [type isEqualToString:@"title"]) {
NSString *value = criteria[@"value"]; NSString *value = criteria[@"value"];
for (int i = 0; i < group.options.count; ++i) { for (int i = 0; i < group.options.count; ++i) {
AVMediaSelectionOption *currentOption = [group.options objectAtIndex:i]; AVMediaSelectionOption *currentOption = [group.options objectAtIndex:i];
NSString *optionValue; NSString *optionValue;
if ([type isEqualToString:@"language"]) { if ([type isEqualToString:@"language"]) {
optionValue = [currentOption extendedLanguageTag]; optionValue = [currentOption extendedLanguageTag];
} else { } else {
optionValue = [[[currentOption commonMetadata] optionValue = [[[currentOption commonMetadata]
valueForKey:@"value"] valueForKey:@"value"]
objectAtIndex:0]; objectAtIndex:0];
} }
if ([value isEqualToString:optionValue]) { if ([value isEqualToString:optionValue]) {
mediaOption = currentOption; mediaOption = currentOption;
break; break;
} }
}
//} else if ([type isEqualToString:@"default"]) {
// option = group.defaultOption; */
} else if ([type isEqualToString:@"index"]) {
if ([criteria[@"value"] isKindOfClass:[NSNumber class]]) {
int index = [criteria[@"value"] intValue];
if (group.options.count > index) {
mediaOption = [group.options objectAtIndex:index];
}
}
} else { // default. invalid type or "system"
[_player.currentItem selectMediaOptionAutomaticallyInMediaSelectionGroup:group];
return;
} }
//} else if ([type isEqualToString:@"default"]) {
// option = group.defaultOption; */
} else if ([type isEqualToString:@"index"]) {
if ([criteria[@"value"] isKindOfClass:[NSNumber class]]) {
int index = [criteria[@"value"] intValue];
if (group.options.count > index) {
mediaOption = [group.options objectAtIndex:index];
}
}
} else { // default. invalid type or "system"
[_player.currentItem selectMediaOptionAutomaticallyInMediaSelectionGroup:group];
return;
}
// If a match isn't found, option will be nil and text tracks will be disabled // If a match isn't found, option will be nil and text tracks will be disabled
[_player.currentItem selectMediaOption:mediaOption inMediaSelectionGroup:group]; [_player.currentItem selectMediaOption:mediaOption inMediaSelectionGroup:group];
} }
- (void)setSelectedAudioTrack:(NSDictionary *)selectedAudioTrack { - (void)setSelectedAudioTrack:(NSDictionary *)selectedAudioTrack {
_selectedAudioTrack = selectedAudioTrack; _selectedAudioTrack = selectedAudioTrack;
[self setMediaSelectionTrackForCharacteristic:AVMediaCharacteristicAudible [self setMediaSelectionTrackForCharacteristic:AVMediaCharacteristicAudible
withCriteria:_selectedAudioTrack]; withCriteria:_selectedAudioTrack];
} }
- (void)setSelectedTextTrack:(NSDictionary *)selectedTextTrack { - (void)setSelectedTextTrack:(NSDictionary *)selectedTextTrack {
@ -950,25 +950,25 @@ static int const RCTVideoUnset = -1;
- (NSArray *)getAudioTrackInfo - (NSArray *)getAudioTrackInfo
{ {
NSMutableArray *audioTracks = [[NSMutableArray alloc] init]; NSMutableArray *audioTracks = [[NSMutableArray alloc] init];
AVMediaSelectionGroup *group = [_player.currentItem.asset AVMediaSelectionGroup *group = [_player.currentItem.asset
mediaSelectionGroupForMediaCharacteristic:AVMediaCharacteristicAudible]; mediaSelectionGroupForMediaCharacteristic:AVMediaCharacteristicAudible];
for (int i = 0; i < group.options.count; ++i) { for (int i = 0; i < group.options.count; ++i) {
AVMediaSelectionOption *currentOption = [group.options objectAtIndex:i]; AVMediaSelectionOption *currentOption = [group.options objectAtIndex:i];
NSString *title = @""; NSString *title = @"";
NSArray *values = [[currentOption commonMetadata] valueForKey:@"value"]; NSArray *values = [[currentOption commonMetadata] valueForKey:@"value"];
if (values.count > 0) { if (values.count > 0) {
title = [values objectAtIndex:0]; title = [values objectAtIndex:0];
}
NSString *language = [currentOption extendedLanguageTag] ? [currentOption extendedLanguageTag] : @"";
NSDictionary *audioTrack = @{
@"index": [NSNumber numberWithInt:i],
@"title": title,
@"language": language
};
[audioTracks addObject:audioTrack];
} }
return audioTracks; NSString *language = [currentOption extendedLanguageTag] ? [currentOption extendedLanguageTag] : @"";
NSDictionary *audioTrack = @{
@"index": [NSNumber numberWithInt:i],
@"title": title,
@"language": language
};
[audioTracks addObject:audioTrack];
}
return audioTracks;
} }
- (NSArray *)getTextTrackInfo - (NSArray *)getTextTrackInfo
@ -1000,7 +1000,7 @@ static int const RCTVideoUnset = -1;
- (BOOL)getFullscreen - (BOOL)getFullscreen
{ {
return _fullscreenPlayerPresented; return _fullscreenPlayerPresented;
} }
- (void)setFullscreen:(BOOL) fullscreen { - (void)setFullscreen:(BOOL) fullscreen {
@ -1010,11 +1010,11 @@ static int const RCTVideoUnset = -1;
if (!_fullscreenOptions) { if (!_fullscreenOptions) {
[self setFullscreenOptions: [self setFullscreenOptions:
@{ @{
@"enabled": enabled, @"enabled": enabled,
@"autorotate": @"0", @"autorotate": @"0",
@"preferredOrientation": @"default" @"preferredOrientation": @"default"
}]; }];
} }
else { else {
[_fullscreenOptions setValue:enabled forKey:@"enabled"]; [_fullscreenOptions setValue:enabled forKey:@"enabled"];
@ -1077,14 +1077,14 @@ static int const RCTVideoUnset = -1;
- (void)usePlayerViewController - (void)usePlayerViewController
{ {
if( _player ) if( _player )
{ {
_playerViewController = [self createPlayerViewController:_player withPlayerItem:_playerItem]; _playerViewController = [self createPlayerViewController:_player withPlayerItem:_playerItem];
// to prevent video from being animated when resizeMode is 'cover' // to prevent video from being animated when resizeMode is 'cover'
// resize mode must be set before subview is added // resize mode must be set before subview is added
[self setResizeMode:_resizeMode]; [self setResizeMode:_resizeMode];
[self addSubview:_playerViewController.view]; [self addSubview:_playerViewController.view];
} }
} }
- (void)usePlayerLayer - (void)usePlayerLayer
@ -1108,21 +1108,21 @@ static int const RCTVideoUnset = -1;
- (void)setControls:(BOOL)controls - (void)setControls:(BOOL)controls
{ {
if( _controls != controls || (!_playerLayer && !_playerViewController) ) if( _controls != controls || (!_playerLayer && !_playerViewController) )
{
_controls = controls;
if( _controls )
{ {
_controls = controls; [self removePlayerLayer];
if( _controls ) [self usePlayerViewController];
{
[self removePlayerLayer];
[self usePlayerViewController];
}
else
{
[_playerViewController.view removeFromSuperview];
_playerViewController = nil;
[self usePlayerLayer];
}
} }
else
{
[_playerViewController.view removeFromSuperview];
_playerViewController = nil;
[self usePlayerLayer];
}
}
} }
- (void)setProgressUpdateInterval:(float)progressUpdateInterval - (void)setProgressUpdateInterval:(float)progressUpdateInterval
@ -1149,24 +1149,24 @@ static int const RCTVideoUnset = -1;
- (void)videoPlayerViewControllerWillDismiss:(AVPlayerViewController *)playerViewController - (void)videoPlayerViewControllerWillDismiss:(AVPlayerViewController *)playerViewController
{ {
if (_playerViewController == playerViewController && _fullscreenPlayerPresented && self.onVideoFullscreenPlayerWillDismiss) if (_playerViewController == playerViewController && _fullscreenPlayerPresented && self.onVideoFullscreenPlayerWillDismiss)
{ {
self.onVideoFullscreenPlayerWillDismiss(@{@"target": self.reactTag}); self.onVideoFullscreenPlayerWillDismiss(@{@"target": self.reactTag});
} }
} }
- (void)videoPlayerViewControllerDidDismiss:(AVPlayerViewController *)playerViewController - (void)videoPlayerViewControllerDidDismiss:(AVPlayerViewController *)playerViewController
{ {
if (_playerViewController == playerViewController && _fullscreenPlayerPresented) if (_playerViewController == playerViewController && _fullscreenPlayerPresented)
{ {
_fullscreenPlayerPresented = false; _fullscreenPlayerPresented = false;
_presentingViewController = nil; _presentingViewController = nil;
_playerViewController = nil; _playerViewController = nil;
[self applyModifiers]; [self applyModifiers];
if(self.onVideoFullscreenPlayerDidDismiss) { if(self.onVideoFullscreenPlayerDidDismiss) {
self.onVideoFullscreenPlayerDidDismiss(@{@"target": self.reactTag}); self.onVideoFullscreenPlayerDidDismiss(@{@"target": self.reactTag});
}
} }
}
} }
#pragma mark - React View Management #pragma mark - React View Management
@ -1182,12 +1182,12 @@ static int const RCTVideoUnset = -1;
if( _controls ) if( _controls )
{ {
view.frame = self.bounds; view.frame = self.bounds;
[_playerViewController.contentOverlayView insertSubview:view atIndex:atIndex]; [_playerViewController.contentOverlayView insertSubview:view atIndex:atIndex];
} }
else else
{ {
RCTLogError(@"video cannot have any subviews"); RCTLogError(@"video cannot have any subviews");
} }
return; return;
} }
@ -1196,7 +1196,7 @@ static int const RCTVideoUnset = -1;
{ {
if( _controls ) if( _controls )
{ {
[subview removeFromSuperview]; [subview removeFromSuperview];
} }
else else
{ {
@ -1219,10 +1219,10 @@ static int const RCTVideoUnset = -1;
} }
else else
{ {
[CATransaction begin]; [CATransaction begin];
[CATransaction setAnimationDuration:0]; [CATransaction setAnimationDuration:0];
_playerLayer.frame = self.bounds; _playerLayer.frame = self.bounds;
[CATransaction commit]; [CATransaction commit];
} }
} }