首先给大家放一个StreamingKit的链接
简单的播放使用例子,可以看开源作者的演示demo。
由于整个播放器涉及到UI啊数据啊比较多,所以就不全抠下来当demo了,就在这里列一点TIPS,希望能帮助到大家。
歌曲播放形式我是这么写的:
.h里:
/**
歌曲播放形式
*/
typedef enum : NSUInteger {
MBAudioPlayTypeCircle, //循环播放
MBAudioPlayTypeRandom, //随机播放
MBAudioPlayTypeOneMusic,//单曲循环
MBAudioPlayTypeNoNext, //播完就不播了
} MBAudioPlayType;
.m里:
/**
* 下一首
*/
- (void)playNextMusic
{
switch (self.playType) {
case MBAudioPlayTypeCircle:
{
//循环播放
_nowMusicLocal++;
if (_nowMusicLocal >= [self allLocal]) {
_nowMusicLocal = 0;
}
[self playMusic];
}
break;
case MBAudioPlayTypeRandom:
{
//随机播放
[self randomWithTimes:5];
if (_nowMusicLocal >= [self allLocal]) {
_nowMusicLocal = 0;
}
[self playMusic];
}
break;
case MBAudioPlayTypeOneMusic:
{
//单曲循环
[self playMusicWithInfo];
}
break;
case MBAudioPlayTypeNoNext:
{
//播完就不播了
}
break;
default:
break;
}
}
#pragma mark - 随机播放随机数
/**
* 随机递归
*
* @param num 递归次数
*/
-(void)randomWithTimes:(NSInteger)num
{
NSInteger randomMusic = arc4random() % [self allLocal];
DLog(@"随机值为:%ld",(long)randomMusic);
if (_nowMusicLocal == randomMusic && [self allLocal] != 1) {
//防止递归死循环
if (num != 0) {
num--;
[self randomWithTimes:num];
return;
}else
{
randomMusic++;
//递归多次还一样,就强行设一个了(低概率事件)
_nowMusicLocal = randomMusic;
}
}
else
{
//正常情况
_nowMusicLocal = randomMusic;
}
}
这个随机算法写的其实挺搓的,不过勉强能用吧。。。
获取后台播放权限
在target-capabilities-background modes 开启 audio and airplay
在AppDelegate中
#import <AVFoundation/AVFoundation.h>
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
xxxxx;
NSError* error;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
}
漏掉最重要的了,在程序挂起的时候,要手动加权限的,
- (void)applicationWillResignActive:(UIApplication *)application
{
DLog(@"\n\n倔强的打出一行字告诉你我要挂起了。。\n\n");
//MBAudioPlayer是我为播放器写的单例,这段就是当音乐还在播放状态的时候,给后台权限,不在播放状态的时候,收回后台权限
if ([MBAudioPlayer shareInstance].audioPlayer.state == STKAudioPlayerStatePlaying||[MBAudioPlayer shareInstance].audioPlayer.state == STKAudioPlayerStateBuffering||[MBAudioPlayer shareInstance].audioPlayer.state == STKAudioPlayerStatePaused ||[MBAudioPlayer shareInstance].audioPlayer.state == STKAudioPlayerStateStopped) {
//有音乐播放时,才给后台权限,不做流氓应用。
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
//开启定时器
[[MBAudioPlayer shareInstance] decideTimerWithType:MBAudioTimerStartBackground andBeginState:YES];
[[MBAudioPlayer shareInstance] configNowPlayingInfoCenter];
}
else
{
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
[self resignFirstResponder];
//检测是都关闭定时器
[[MBAudioPlayer shareInstance] decideTimerWithType:MBAudioTimerStartBackground andBeginState:NO];
}
}
锁屏时,更新控制台、锁屏信息(定时器调用)
#pragma mark - 锁屏控制
/**
* 设置锁屏信息
*/
-(void)configNowPlayingInfoCenter
{
if (self.nowPlayingMusicInfo == nil) {
return;
}
@autoreleasepool {
NSDictionary *info = self.nowPlayingMusicInfo;
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
//歌曲名称
[dict setObject:[info ObjectNullForKey:@"title"] forKey:MPMediaItemPropertyTitle];
//演唱者
[dict setObject:[info ObjectNullForKey:@"author"] forKey:MPMediaItemPropertyArtist];
//专辑名
//[dict setObject:[info ObjectNullForKey:@"album"] forKey:MPMediaItemPropertyAlbumTitle];
//专辑缩略图
NSString *imagePath = [info ObjectNullForKey:@"thumb"];
imagePath = [NSString stringWithFormat:@"EGOImageLoader-%lu", (unsigned long)[[imagePath description] hash]];
NSString *imageLocalPath = [NSString stringWithFormat:@"%@/%@", EGOCacheDirectory(),imagePath];
NSData * thumbData = [NSData dataWithContentsOfFile:imageLocalPath];
if (thumbData != nil) {
UIImage *image = [UIImage imageWithData:thumbData];
MPMediaItemArtwork *artwork = [[MPMediaItemArtwork alloc] initWithImage:image];
[dict setObject:artwork forKey:MPMediaItemPropertyArtwork];
}else
{
// FIXME: 无图的时候,读取图
}
//音乐剩余时长
[dict setObject:[NSNumber numberWithDouble:self.audioPlayer.duration] forKey:MPMediaItemPropertyPlaybackDuration];
//音乐当前播放时间 在计时器中修改
[dict setObject:[NSNumber numberWithDouble:self.audioPlayer.progress] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
//设置锁屏状态下屏幕显示播放音乐信息
//DLog(@"显示播放音乐信息:%@\n%@",dict,[info ObjectNullForKey:@"title"]);
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:dict];
}
}
/**
* 响应远程音乐播放控制消息
*
* @param receivedEvent
*/
- (void)remoteControlReceivedWithEvent:(UIEvent *)receivedEvent {
if (receivedEvent.type == UIEventTypeRemoteControl) {
switch (receivedEvent.subtype) {
case UIEventSubtypeRemoteControlPause:
//点击了暂停
[self pauseStreamer];
break;
case UIEventSubtypeRemoteControlNextTrack:
//点击了下一首
[self playNextMusic];
break;
case UIEventSubtypeRemoteControlPreviousTrack:
//点击了上一首
[self playPreMusic];
//此时需要更改歌曲信息
break;
case UIEventSubtypeRemoteControlPlay:
//点击了播放
[self pauseStreamer];
break;
default:
break;
}
}
}
最后,那些在锁屏中带歌词的产品么,据说是不停的的把歌词和专辑图片结合在一起,然后根据歌词时间刷新图片。。。如果有这个产品需求,可以按这个思路来做。。
简书已经弃用,欢迎移步我的小专栏:
https://xiaozhuanlan.com/dahuihuiiOS