iOS播放音乐、后台播放、控制台控制相关的一些TIPS,基于StreamingKit

首先给大家放一个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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 207,248评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,681评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,443评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,475评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,458评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,185评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,451评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,112评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,609评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,083评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,163评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,803评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,357评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,357评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,590评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,636评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,925评论 2 344

推荐阅读更多精彩内容