美文网首页学学人家的框架iOS资源库IT圈
iOS播放音乐、后台播放、控制台控制相关的一些TIPS,基于St

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

作者: 大灰灰iOS | 来源:发表于2015-04-06 23:42 被阅读8395次

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

    相关文章

      网友评论

      • liwb:StreamingKit播放.wav 怎么搞???
      • 最后还是个农:请问下StreamingKit支持哪些音频格式,ape等无损格式支持吗?
      • 5fff1c1a968e:hi,有个问题问一下,就是UIEventSubtype这个API没有控制播放进度的,那个slider滑动不了,你是怎么解决的
      • 冷月天涯:MBAudioPlayer这个播放器在哪里下载啊??? Dome里面没有啊?
        大灰灰iOS:@冷月天涯 github搜一下,不确定现在还有没有
      • 小微向前冲:请问有什么方法,让在一个特定时段,唤醒播放器么?
      • 啊啊啊啊啊啊__:问一下,退到后台以后上方会有红色区域,想问一下这个怎么去掉。。
      • yumiao:随机数那块,改进建议: 产生一个随机数,如果与当前播放序号一样,则+1取余后使用。做成递归显得不太好啊~~~~~~
        大灰灰iOS:@yumiao :relaxed: 是的。。递归确实不太好。。那时候做东西还是太粗暴
      • Mr大先生:请问有做过类似qq音乐的定时关闭功能吗?
      • 牧童s:怎样拿到播放过网络音乐的缓存地址呢?StreamingKit每次播放都要从网络加载?
      • 131b09cc6f52:你好,我在锁屏远程控制的时候,点击下一首的时候,音乐进入下一首,但锁屏界面突然什么都没有显示了,这会是什么情况? :sob:
        大灰灰iOS:@qYong_ 新的一首歌数据没传进来呀。。尤其是封面,异步加载的
      • J_Knight_:您好,我问一下关于程序挂起之后的代码:既然您说只有在播放时才给权限,那么为什么在判断里面会有“[MBAudioPlayer shareInstance].audioPlayer.state == STKAudioPlayerStatePaused ||[MBAudioPlayer shareInstance].audioPlayer.state == STKAudioPlayerStateStopped”的情况?
        J_Knight_:@大灰灰iOS 是用 “在挂起后,音乐是否正在释放”来判断的么?
        J_Knight_:@大灰灰iOS 哦哦 没关系。再请问一下您当时写的时候,挂起+锁屏 和 挂起 + 非锁屏 是如何区分的?
        大灰灰iOS:@Hero_SJ 好久以前得了。回忆了下,pause和stop是为了可以快速开始播放,细节回去还要看看代码。。
      • A天天涨不停:灰神,膜拜下
      • 花前月下:棒棒的。学习了。
        大灰灰iOS:@花前月下 么么哒~
      • Raybon_lee:你好,看到你也在用streaming Kit 这个库,请问一下,我们也是做的音乐播放器,遇到一个小问题,就是在线音乐无法播放,不知道问题出在哪里了,只有一个百家讲坛的播放不了,但是获取的地址是可以播放的,看到的画大神可否加我QQ: 948709987, 帮我看下,根据调试的结果都是正确的,播放提示系统错误
        大灰灰iOS:@bfforeverli 这个库我后来就没碰过了。。音乐那边好像一直没啥问题。。
        Raybon_lee:@大灰灰iOS 里面的库代理方法一直被释放,数据源获取不到,我更新了一下库就好了,暂时还没研究呢,准备研究一下
        大灰灰iOS:@bfforeverli 格式不对吧,我也遇到过一次,一个MP3播放不了。。最后没解决。换了个音乐源。。
      • 雨晨子龙:你好,请问下。我现在的需求是不需要后台播放,点击其他按钮就结束播放。怎么解决了?
        大灰灰iOS:@雨晨子龙 其他按钮?你播放控件是单例啊,其他按钮都能控制开始结束的。。

      本文标题:iOS播放音乐、后台播放、控制台控制相关的一些TIPS,基于St

      本文链接:https://www.haomeiwen.com/subject/tilzxttx.html