代码地址如下:
http://www.demodashi.com/demo/11944.html天道酬勤
前言
作为一名iOS
开发者,每当使用APP
的时候,总难免会情不自禁的去想想,这个怎么做的?该怎么实现呢?很久之前,就想写一个关于音乐方面的播放器,最近刚好得空,就趁机摸索着写了下,写的不好,还望多多指教。
前提准备
为了能够有明确的思路来做这个demo
,我下载了QQ音乐
和网易云音乐
,然后分别对比,最终选择了QQ音乐
来参照,先是获取了其中的所有资源文件,在这之后就是研究使用技术,这里我选择了FreeStreamer
,虽然系统也有,但是该框架可能更好用点。
实现部分
在这之前,先来看看大概效果图吧
再看完效果图之后,我们就来看看这其中涉及到的几个难点吧(在我看开~)
- 1、先让播放器跑起来
这里我使用的是pods
来管理三方库,代码如下
platform:ios,’8.0’
target "GLMusicBox" do
pod 'FreeStreamer', '~> 3.7.3'
pod 'SDWebImage', '~> 4.0.0’
pod 'MJRefresh', '~> 3.1.11’
pod 'Masonry', '~> 1.0.2'
pod 'Reachability', '~> 3.2'
pod 'AFNetworking', '~> 3.0'
pod 'IQKeyboardManager', '~> 3.3.2’
end
针对FreeStreamer
我简单进行了封装下
#import "FSAudioStream.h"
@class GLMusicLRCModel;
typedef NS_ENUM(NSInteger,GLLoopState){
GLSingleLoop = 0,//单曲循环
GLForeverLoop,//重复循环
GLRandomLoop,//随机播放
GLOnceLoop//列表一次顺序播放
};
@protocol GLMusicPlayerDelegate<NSObject>
/**
*
实时更新
*
**/
- (void)updateProgressWithCurrentPosition:(FSStreamPosition)currentPosition endPosition:(FSStreamPosition)endPosition;
- (void)updateMusicLrc;
@end
@interface GLMusicPlayer : FSAudioStream
/**
*
播放列表
*
**/
@property (nonatomic,strong) NSMutableArray *musicListArray;
/**
当前播放歌曲的歌词
*/
@property (nonatomic,strong) NSMutableArray <GLMusicLRCModel*>*musicLRCArray;
/**
*
当前播放
*
**/
@property (nonatomic,assign,readonly) NSUInteger currentIndex;
/**
*
当前播放的音乐的标题
*
**/
@property (nonatomic,strong) NSString *currentTitle;
/**
是否是暂停状态
*/
@property (nonatomic,assign) BOOL isPause;
@property (nonatomic,weak) id<GLMusicPlayerDelegate>glPlayerDelegate;
//默认 重复循环 GLForeverLoop
@property (nonatomic,assign) GLLoopState loopState;
/**
*
单例播放器
*
**/
+ (instancetype)defaultPlayer;
/**
播放队列中的指定的文件
@param index 序号
*/
- (void)playMusicAtIndex:(NSUInteger)index;
/**
播放前一首
*/
- (void)playFont;
/**
播放下一首
*/
- (void)playNext;
@end
这里继承了FSAudioStream
,并且采用了单例模式
+ (instancetype)defaultPlayer
{
static GLMusicPlayer *player = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
FSStreamConfiguration *config = [[FSStreamConfiguration alloc] init];
config.httpConnectionBufferSize *=2;
config.enableTimeAndPitchConversion = YES;
player = [[super alloc] initWithConfiguration:config];
player.delegate = (id)self;
player.onFailure = ^(FSAudioStreamError error, NSString *errorDescription) {
//播放错误
//有待解决
};
player.onCompletion = ^{
//播放完成
NSLog(@" 打印信息: 播放完成1");
};
player.onStateChange = ^(FSAudioStreamState state) {
switch (state) {
case kFsAudioStreamPlaying:
{
NSLog(@" 打印信息 playing.....");
player.isPause = NO;
[GLMiniMusicView shareInstance].palyButton.selected = YES;
}
break;
case kFsAudioStreamStopped:
{
NSLog(@" 打印信息 stop.....%@",player.url.absoluteString);
}
break;
case kFsAudioStreamPaused:
{
//pause
player.isPause = YES;
[GLMiniMusicView shareInstance].palyButton.selected = NO;
NSLog(@" 打印信息: pause");
}
break;
case kFsAudioStreamPlaybackCompleted:
{
NSLog(@" 打印信息: 播放完成2");
[player playMusicForState];
}
break;
default:
break;
}
};
//设置音量
[player setVolume:0.5];
//设置播放速率
[player setPlayRate:1];
player.loopState = GLForeverLoop;
});
return player;
}
然后实现了播放方法
- (void)playFromURL:(NSURL *)url
{
//根据地址 在本地找歌词
NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"musiclist" ofType:@"plist"]];
for (NSString *playStringKey in dic.allKeys) {
if ([[dic valueForKey:playStringKey] isEqualToString:url.absoluteString]) {
self.currentTitle = playStringKey;
break;
}
}
[self stop];
if (![url.absoluteString isEqualToString:self.url.absoluteString]) {
[super playFromURL:url];
}else{
[se