1. 程式人生 > >Objective-C簡單的音樂播放器(邊下邊播)

Objective-C簡單的音樂播放器(邊下邊播)

Objective-C中的音樂播放大多用AVAudioPlayer,它有很多優點:
(1)可以播放任意長度音樂;
(2)可以迴圈播放;
(3)可以控制播放的時間;
(4)可以控制聲道的音量實現立體聲效果;
(5)可以調整音量。
但是AVAudioPlayer有一個很大的缺點,那就是隻能用於播放本地音訊,網路資源播放之前必須先載入,不能立即播放;但系統為我們提供了另一個更為豐富的類MPMoviePlayerController和AVPlayer來播放流媒體,MPMoviePlayerController使用更簡單,但功能不如AVPlayer強大。這裡介紹一下AVPlayer播放線上音訊,播放視訊以後再介紹。直接上程式碼,註釋會盡量寫的詳細一些:
新建一個類繼承自NSObject:AudioPlayer
.h檔案程式碼:

#import <Foundation/Foundation.h>
@class AudioPlayer;

@protocol AudioPlayerDelegate <NSObject>

//再播放中每秒都執行的事件
- (void)audioplayerPlayWith:(AudioPlayer *)audioplayer Progress:(float)progress;

//當一首歌曲播放完成之後執行這個事件
- (void)audioplayerDidFinishItem:(AudioPlayer *)audioplayer;

@end


@interface
AudioPlayer : NSObject
@property(nonatomic,assign)id<AudioPlayerDelegate>delegate; @property(nonatomic,assign)BOOL isPlaying; +(AudioPlayer*)sharePlayer; -(void)play; -(void)pause; -(void)seekToTime:(float)time; -(void)setPrepareMusicUrl:(NSString*)urlStr; @end

.m檔案程式碼:

#import "AudioPlayer.h"
@import AVFoundation; @interface AudioPlayer () { BOOL _isPrepare;//播放是否準備成功 BOOL _isPlaying;//播放器是否正在播放 } @property(nonatomic,strong)AVPlayer *player; @property(nonatomic,strong)NSTimer *timer; @end @implementation AudioPlayer +(AudioPlayer*)sharePlayer { static AudioPlayer *player = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ player = [AudioPlayer new]; }); return player; } - (instancetype)init { self = [super init]; if (self) { //通知中心 [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(endAction:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil]; } return self; } -(void)setPrepareMusicUrl:(NSString*)urlStr { if (self.player.currentItem) { [self.player.currentItem removeObserver:self forKeyPath:@"status"]; } //建立一個item資源 AVPlayerItem *item = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:urlStr]]; [item addObserver:self forKeyPath:@"status" options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) context:nil]; [self.player replaceCurrentItemWithPlayerItem:item]; } -(void)play { //判斷資源是否準備成功 if (!_isPrepare) { return; } [self.player play]; _isPlaying = YES; //播放時候的圖片轉動效果 //timer初始化 if (_timer) { return; } //建立一個timer self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(playingAction:) userInfo:nil repeats:YES]; } -(void)pause { if (!_isPlaying) { return; } [self.player pause]; _isPlaying = NO; //銷燬計時器 [_timer invalidate]; _timer = nil; } -(void)seekToTime:(float)time { //當音樂播放器時間改變時,先暫停後播放 [self pause]; [self.player seekToTime:CMTimeMakeWithSeconds(time, self.player.currentTime.timescale) completionHandler:^(BOOL finished) { if (finished) { [self play]; } }]; } //每隔0.1秒執行一下這個事件 -(void)playingAction:(id)sender { if (self.delegate&&[self.delegate respondsToSelector:@selector(audioplayerPlayWith:Progress:)]) { //獲取當前播放歌曲的時間 float progress = 1.0 * self.player.currentTime.value / self.player.currentTime.timescale; [self.delegate audioplayerPlayWith:self Progress:progress]; } } -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { AVPlayerStatus staute = [change[@"new"] integerValue]; switch (staute) { case AVPlayerStatusReadyToPlay: NSLog(@"載入成功,可以播放了"); _isPrepare = YES; [self play]; break; case AVPlayerStatusFailed: NSLog(@"載入失敗"); break; case AVPlayerStatusUnknown: NSLog(@"資源找不到"); break; default: break; } NSLog(@"change:%@",change); } //當一首歌播放結束時會執行下面的方法 -(void)endAction:(NSNotification *)not { if (self.delegate &&[self.delegate respondsToSelector:@selector(audioplayerDidFinishItem:)]) { [self.delegate audioplayerDidFinishItem:self]; } } -(AVPlayer*)player { if (_player==nil) { _player = [AVPlayer new]; } return _player; } -(BOOL)isPlaying{ return _isPlaying; } @end

使用方法很簡單,傳正確的url初始化然後呼叫對應的方法,我就不玩滾這裡貼上了。此外推薦一個第三方庫AFSoundManager, 簡化了 iOS 音訊播放功能,支援本地檔案和流媒體,通過一個完全 Block 驅動的 Objective-C 類實現。使用 AudioToolbox 和 AVFoundation 框架。我在Demo中也對其進行了封裝。用法和我們剛剛封裝的AudioPlayer類似。感興趣的可以看看。
demo:
這裡寫圖片描述
GitHub:https://github.com/FEverStar/AudioDemo