iOS 开发每天分享优质文章ios开发音视频iOS面试

iOS音乐后台播放、锁屏封面及播放控制

2018-09-04  本文已影响228人  半岛夏天

前言

在默认环境下App被切换到后台时,音乐的就停止播放了,但音乐类App的一般都会需要在后台继续播放,这样用户就可以一边听音乐,一边操作其他的App。对于这种情况我们可以对App做一些简单的配置,实现后台播放功能。当app切换到后台,用户就无法控制和查看app当前播放歌曲了。这个对于用户来说并不是很友好。既然是后台播放,那么就应该提供便捷的播放控制方式。iOS系统已经预留了接口,允许开发者在锁屏界面显示播放歌曲信息(以下称为锁屏封面),以及在底部菜单栏提供播放控制器。下面我们就来给App添加这些功能吧。

一、后台播放

设置App的plist,使app可以在后台播放音乐。

myApp-Info.plist中添加UIBackgroundModes键值,添加子键值为audio。

然后再程序中添加入下代码:

AVAudioSession  *session  =  [AVAudioSession  sharedInstance];
[session setActive:YES error:nil];
[session setCategory:AVAudioSessionCategoryPlayback error:nil];

二、添加播放控制器(Remote Control Events)

首先我们要告诉系统,我要接受系统的播放控制消息,这样系统才会给我们发送播放控制命令。流程是这样的:

App启动 -> 告诉系统我需要接受播放控制消息 -> 等待 -> 用户点击系统播放控制器按钮 -> 系统传递消息给App -> 我们接受到消息,做出相应的响应。

想要接收播放控制消息,我们必须要做三件事:

请注意第三点,我们的App必须在开始播放音频后,才能收到控制消息。否则,即使你满足了前两点,也无法接收到控制消息。


//AppDelegate.m

-  (BOOL)application:(UIApplication  *)application didFinishLaunchingWithOptions:(NSDictionary  *)launchOptions

{

 //...

 //告诉系统,我们要接受远程控制事件

    [[UIApplication  sharedApplication] beginReceivingRemoteControlEvents];

    [self  becomeFirstResponder];

}

-  (BOOL)canBecomeFirstResponder

{

    return  YES;

}

//响应远程音乐播放控制消息

-  (void)remoteControlReceivedWithEvent:(UIEvent  *)receivedEvent  {

    if  (receivedEvent.type  ==  UIEventTypeRemoteControl)  {

        switch  (receivedEvent.subtype)  {

            case UIEventSubtypeRemoteControlTogglePlayPause:

                [[PlayController  sharedInstance] pause];

                NSLog(@"RemoteControlEvents: pause");

                break;

            case UIEventSubtypeRemoteControlNextTrack:

                [[PlayController  sharedInstance] playModeNext];

                NSLog(@"RemoteControlEvents: playModeNext");

                break;

            case UIEventSubtypeRemoteControlPreviousTrack:

                [[PlayController  sharedInstance] playPrev];

                NSLog(@"RemoteControlEvents: playPrev");

                break;

            default:

                break;

        }

    }

}

播放音频的代码,这里给出一段简单的示例:


-  (void)playBtnClicked

{

    NSError  *error  =  nil;

    NSString  *path  =  [[NSBundle  mainBundle] pathForResource:@"music" ofType:@"mp3"];

    AVAudioPlayer  *player  =  [[AVAudioPlayer  alloc] initWithContentsOfURL:[NSURL URLWithString:path] error:&error];

    if  (error)  {

        NSLog(@"Error:%@",  [error localizedDescription]);

    }

    [player play];

}

在开始播放音频后,使用耳机线控的播放暂停等按键,或者锁屏封面上的播放控制按键,就能够收到控制消息了。

关于耳机线控的一点说明

苹果耳机的线控上有三个按钮:加号,中部,减号。其中加号和减号是用于控制音量,这两个按钮点击是收不到消息的——UIEventSubtype没有音量改变的事件类型。而中部按钮的点击,是可以收到消息的,按一下是播放/暂停切换,快按两下是播放下一首,快按三下是播放上一首,快按两下并摁住是快进,快按三下并摁住是快退。

三、在锁屏界面显示播放歌曲信息

代码如下,其实就是设置一个全局变量的值,当系统处于音乐播放状态时,锁屏界面就会将NowPlayingInfo中的信息展示出来。可惜的是,这里的定制性不是太强,例如歌曲图片无法平铺整个屏幕大小,根据我的测试,歌曲图片在320×320时,可以完整显示在屏幕中央位置,两侧不会留下黑边。


Class playingInfoCenter = NSClassFromString(@"MPNowPlayingInfoCenter");
    
    if (playingInfoCenter) {
        NSMutableDictionary *songInfo = [[NSMutableDictionary alloc] init];
        UIImage *image = [UIImage imageNamed:@"image"];
        MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage:image];
        //歌曲名称
        [songInfo setObject:@"深夜地下铁" forKey:MPMediaItemPropertyTitle];
        //演唱者
        [songInfo setObject:@"陶钰玉" forKey:MPMediaItemPropertyArtist];
        //专辑名
        [songInfo setObject:@"深夜地下铁" forKey:MPMediaItemPropertyAlbumTitle];
        //专辑缩略图
        [songInfo setObject:albumArt forKey:MPMediaItemPropertyArtwork];
        [songInfo setObject:[NSNumber numberWithDouble:[audioY getCurrentAudioTime]] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime]; //音乐当前已经播放时间
        [songInfo setObject:[NSNumber numberWithFloat:1.0] forKey:MPNowPlayingInfoPropertyPlaybackRate];//进度光标的速度 (这个随 自己的播放速率调整,我默认是原速播放)
        [songInfo setObject:[NSNumber numberWithDouble:[audioY getAudioDuration]] forKey:MPMediaItemPropertyPlaybackDuration];//歌曲总时间设置
        
        //        设置锁屏状态下屏幕显示音乐信息
        [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songInfo];
    }

经过了如上配置后,程序应该就能够正常显示了。

四、遇到的问题

问题:不显示当前进度
解决:添加MPMediaItemPropertyPlaybackDuration同时也出现问题,剩余时间每次减2秒

问题:出现了剩余时间每次减2秒的情况
解决:要添加MPNowPlayingInfoPropertyPlaybackRate就可以


NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[[MPNowPlayingInfoCenter defaultCenter] nowPlayingInfo]];
[dict setObject:[NSNumber numberWithDouble:audioPlayer.playableDuration] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime]; //音乐当前已经过时间
 [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:dict];

上一篇下一篇

猜你喜欢

热点阅读