From 5007419abbbf1129d39f5dc084dd8f394ec80bf4 Mon Sep 17 00:00:00 2001 From: Michele Simone Date: Tue, 2 May 2017 16:21:53 +0100 Subject: [PATCH 1/4] loading the asset from the local filesystem if available. --- PersistentStreamPlayer.m | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/PersistentStreamPlayer.m b/PersistentStreamPlayer.m index 9e1aa51..2f9b1aa 100644 --- a/PersistentStreamPlayer.m +++ b/PersistentStreamPlayer.m @@ -63,8 +63,13 @@ - (void)dealloc - (void)prepareToPlay { self.pendingRequests = [NSMutableArray array]; + AVURLAsset *asset; + if ([self localFileExists]) { + asset = [AVURLAsset URLAssetWithURL:self.localURL options:nil]; + } else { + asset = [AVURLAsset URLAssetWithURL:self.audioRemoteStreamingURL options:nil]; + } - AVURLAsset *asset = [AVURLAsset URLAssetWithURL:self.audioRemoteStreamingURL options:nil]; [asset.resourceLoader setDelegate:self queue:dispatch_get_main_queue()]; AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset automaticallyLoadedAssetKeys:@[@"duration"]]; self.player = [[AVPlayer alloc] initWithPlayerItem:playerItem]; @@ -175,6 +180,12 @@ - (BOOL)tempFileExists { return [[NSFileManager defaultManager] fileExistsAtPath:self.tempURL.path]; } + +- (BOOL)localFileExists + { + //TODO: this should also do some sanity check on the file + return [[NSFileManager defaultManager] fileExistsAtPath:self.localURL.path]; + } - (NSData *)dataFromFileInRange:(NSRange)range { From c768b98ceacc13ddfa87f5e8c25d86c70e60a8ad Mon Sep 17 00:00:00 2001 From: Jessica Wu Date: Thu, 11 May 2017 17:48:09 -0400 Subject: [PATCH 2/4] implemented NSURLConnection delegate method to handle the case when failed to make the connection. --- PersistentStreamPlayer.m | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/PersistentStreamPlayer.m b/PersistentStreamPlayer.m index 2f9b1aa..3abd0db 100644 --- a/PersistentStreamPlayer.m +++ b/PersistentStreamPlayer.m @@ -211,6 +211,27 @@ - (void)connectionDidFinishLoading:(NSURLConnection *)connection } } +- (void)connection:(NSURLConnection *)connection + didFailWithError:(NSError *)error{ + + for (AVAssetResourceLoadingRequest *loadingRequest in self.pendingRequests) { + NSURLComponents * component = [[NSURLComponents alloc] initWithURL:loadingRequest.request.URL resolvingAgainstBaseURL:NO]; + component.scheme = self.originalURLScheme ?: @"http"; + + if ([component.URL.absoluteString isEqualToString: connection.currentRequest.URL.absoluteString] ) { + [loadingRequest finishLoadingWithError:error]; + [self.pendingRequests removeObject:loadingRequest]; + } + } + + if ([self.pendingRequests count] == 0) { + if ([self.delegate respondsToSelector:@selector(persistentStreamPlayerDidFailToLoadAsset:)]) { + [self.delegate persistentStreamPlayerDidFailToLoadAsset:self]; + } + } + +} + - (float)volume { return self.player.volume; From 0585275f050bdc02bb7c159d4fca06caf4133063 Mon Sep 17 00:00:00 2001 From: Jessica Wu Date: Fri, 12 May 2017 09:52:01 -0400 Subject: [PATCH 3/4] added a delegate method that handles situation when failed to make the url connection. --- PersistentStreamPlayer.m | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/PersistentStreamPlayer.m b/PersistentStreamPlayer.m index 2f9b1aa..3abd0db 100644 --- a/PersistentStreamPlayer.m +++ b/PersistentStreamPlayer.m @@ -211,6 +211,27 @@ - (void)connectionDidFinishLoading:(NSURLConnection *)connection } } +- (void)connection:(NSURLConnection *)connection + didFailWithError:(NSError *)error{ + + for (AVAssetResourceLoadingRequest *loadingRequest in self.pendingRequests) { + NSURLComponents * component = [[NSURLComponents alloc] initWithURL:loadingRequest.request.URL resolvingAgainstBaseURL:NO]; + component.scheme = self.originalURLScheme ?: @"http"; + + if ([component.URL.absoluteString isEqualToString: connection.currentRequest.URL.absoluteString] ) { + [loadingRequest finishLoadingWithError:error]; + [self.pendingRequests removeObject:loadingRequest]; + } + } + + if ([self.pendingRequests count] == 0) { + if ([self.delegate respondsToSelector:@selector(persistentStreamPlayerDidFailToLoadAsset:)]) { + [self.delegate persistentStreamPlayerDidFailToLoadAsset:self]; + } + } + +} + - (float)volume { return self.player.volume; From de8cf9dde93f60fce312841cd404f9acb64c570c Mon Sep 17 00:00:00 2001 From: Qiao Jing Wu Date: Mon, 27 Nov 2017 13:02:46 -0500 Subject: [PATCH 4/4] Added delegate method for authentication challenge (#2) * added a delegate method for authentication challenge * only write to file when it's 200 * make sure the local saved content is playable, if not get the file from server again. * making sure the method in the delegate is implemented before calling. --- PersistentStreamPlayer.h | 3 +++ PersistentStreamPlayer.m | 19 +++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/PersistentStreamPlayer.h b/PersistentStreamPlayer.h index 97dd386..bcac8e1 100644 --- a/PersistentStreamPlayer.h +++ b/PersistentStreamPlayer.h @@ -13,6 +13,9 @@ - (void)persistentStreamPlayerDidLoadAsset:(nonnull PersistentStreamPlayer *)player; - (void)persistentStreamPlayerDidFailToLoadAsset:(nonnull PersistentStreamPlayer *)player; +- (void)persistentStreamPlayerWillSendRequestForAuthenticationChallenge:(nonnull NSURLAuthenticationChallenge *)challenge; + + @end @interface PersistentStreamPlayer : NSObject diff --git a/PersistentStreamPlayer.m b/PersistentStreamPlayer.m index 3abd0db..9610c30 100644 --- a/PersistentStreamPlayer.m +++ b/PersistentStreamPlayer.m @@ -151,6 +151,14 @@ - (void)seekToTime:(NSTimeInterval)time } #pragma mark - NSURLConnection delegate +- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge +{ + if ([self.delegate respondsToSelector:@selector(persistentStreamPlayerWillSendRequestForAuthenticationChallenge:)]) { + [self.delegate persistentStreamPlayerWillSendRequestForAuthenticationChallenge:challenge]; + } + +} + - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { self.fullAudioDataLength = 0; @@ -161,7 +169,9 @@ - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLRespon - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { self.fullAudioDataLength += data.length; - [self appendDataToTempFile:data]; + if (self.response.statusCode == 200) { + [self appendDataToTempFile:data]; + } [self processPendingRequests]; } @@ -184,7 +194,12 @@ - (BOOL)tempFileExists - (BOOL)localFileExists { //TODO: this should also do some sanity check on the file - return [[NSFileManager defaultManager] fileExistsAtPath:self.localURL.path]; + + // Check if the content stored in the file is playable, if not try to get the file from the server again. + NSURL *localFileURL = [[NSURL alloc] initFileURLWithPath:self.localURL.path]; + AVAsset *asset = [AVAsset assetWithURL:localFileURL]; + + return asset.isPlayable ? [[NSFileManager defaultManager] fileExistsAtPath:self.localURL.path] : NO; } - (NSData *)dataFromFileInRange:(NSRange)range