AVPlayer is fully customizable, unfortunately there are convenient methods in AVPlayer for showing the time line progress bar.
AVPl
I took the answers from the iOSPawan and Raphael and then adapted to my needs. So I have music and UIProgressView which is always in loop and when you go to the next screen and come back the the song and the bar continued where they were left.
Code:
@interface YourClassViewController (){
NSObject * periodicPlayerTimeObserverHandle;
}
@property (nonatomic, strong) AVPlayer *player;
@property (nonatomic, strong) UIProgressView *progressView;
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
if(_player != nil && ![self isPlaying])
{
[self musicPlay];
}
}
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if (_player != nil) {
[self stopPlaying];
}
}
// ----------
// PLAYER
// ----------
-(BOOL) isPlaying
{
return ([_player rate] > 0);
}
-(void) musicPlay
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[_player currentItem]];
__weak typeof(self) weakSelf = self;
periodicPlayerTimeObserverHandle = [_player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(1.0 / 60.0, NSEC_PER_SEC)
queue:NULL
usingBlock:^(CMTime time){
[weakSelf updateProgressBar];
}];
[_player play];
}
-(void) stopPlaying
{
@try {
if(periodicPlayerTimeObserverHandle != nil)
{
[_player removeTimeObserver:periodicPlayerTimeObserverHandle];
periodicPlayerTimeObserverHandle = nil;
}
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
[_player pause];
}
@catch (NSException * __unused exception) {}
}
-(void) playPreviewSong:(NSURL *) previewSongURL
{
[self configureAVPlayerAndPlay:previewSongURL];
}
-(void) configureAVPlayerAndPlay: (NSURL*) url {
if(_player)
[self stopPlaying];
AVAsset *audioFileAsset = [AVURLAsset URLAssetWithURL:url options:nil];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:audioFileAsset];
_player = [AVPlayer playerWithPlayerItem:playerItem];
[_player addObserver:self forKeyPath:@"status" options:0 context:nil];
CRLPerformBlockOnMainThreadAfterDelay(^{
NSError *loadErr;
if([audioFileAsset statusOfValueForKey:@"playable" error:&loadErr] == AVKeyValueStatusLoading)
{
[audioFileAsset cancelLoading];
[self stopPlaying];
[self showNetworkError:NSLocalizedString(@"Could not play file",nil)];
}
}, NETWORK_REQUEST_TIMEOUT);
}
- (void)updateProgressBar
{
double currentTime = CMTimeGetSeconds(_player.currentTime);
if(currentTime <= 0.05){
[_progressView setProgress:(float)(0.0) animated:NO];
return;
}
if (isfinite(currentTime) && (currentTime > 0))
{
float maxValue = CMTimeGetSeconds(_player.currentItem.asset.duration);
[_progressView setProgress:(float)(currentTime/maxValue) animated:YES];
}
}
-(void) showNetworkError:(NSString*)errorMessage
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"No connection", nil) message:errorMessage preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
// do nothing
}]];
[self presentViewController:alert animated:YES completion:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (object == _player && [keyPath isEqualToString:@"status"]) {
if (_player.status == AVPlayerStatusFailed) {
[self showNetworkError:NSLocalizedString(@"Could not play file", nil)];
} else if (_player.status == AVPlayerStatusReadyToPlay) {
NSLog(@"AVPlayerStatusReadyToPlay");
[TLAppAudioAccess setAudioAccess:TLAppAudioAccessType_Playback];
[self musicPlay];
} else if (_player.status == AVPlayerItemStatusUnknown) {
NSLog(@"AVPlayerItemStatusUnknown");
}
}
}
- (void)playerItemDidReachEnd:(NSNotification *)notification {
if ([notification.object isEqual:self.player.currentItem])
{
[self.player seekToTime:kCMTimeZero];
[self.player play];
}
}
-(void) dealloc{
@try {
[_player removeObserver:self forKeyPath:@"status"];
}
@catch (NSException * __unused exception) {}
[self stopPlaying];
_player = nil;
}