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