iOS后台持续播放音乐

之前在App Store上架了一个音乐播放器软件,用的是AVPlayer做的音乐播放器。很多用户反映没有后台播放,最近决定更新一下。
注意,重点是持续后台播放,网络歌曲也可以,重点是持续播放,后台播放很简单,但是后台持续播放,则需要做一些处理,申请后台id,才能实现持续播放。

1.开启所需要的后台模式:

选中Targets-->Capabilities-->BackgroundModes-->ON,
并勾选Audio and AirPlay选项,如下图


iOS后台持续播放音乐_第1张图片
设置后台模式

2.在Appdelegate.m的applicationWillResignActive:方法中激活后台播放,代码如下:

-(void)applicationWillResignActive:(UIApplication *)application
{
    //开启后台处理多媒体事件
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
    AVAudioSession *session=[AVAudioSession sharedInstance];
    [session setActive:YES error:nil];
    //后台播放
    [session setCategory:AVAudioSessionCategoryPlayback error:nil];
    //这样做,可以在按home键进入后台后 ,播放一段时间,几分钟吧。但是不能持续播放网络歌曲,若需要持续播放网络歌曲,还需要申请后台任务id,具体做法是:
_bgTaskId=[AppDelegate backgroundPlayerID:_bgTaskId];
    //其中的_bgTaskId是后台任务UIBackgroundTaskIdentifier _bgTaskId;
}
实现一下backgroundPlayerID:这个方法:
+(UIBackgroundTaskIdentifier)backgroundPlayerID:(UIBackgroundTaskIdentifier)backTaskId
{
    //设置并激活音频会话类别
    AVAudioSession *session=[AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategoryPlayback error:nil];
    [session setActive:YES error:nil];
    //允许应用程序接收远程控制
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
    //设置后台任务ID
    UIBackgroundTaskIdentifier newTaskId=UIBackgroundTaskInvalid;
    newTaskId=[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
    if(newTaskId!=UIBackgroundTaskInvalid&&backTaskId!=UIBackgroundTaskInvalid)
    {
        [[UIApplication sharedApplication] endBackgroundTask:backTaskId];
    }
    return newTaskId;
}

3.处理中断事件,如电话,微信语音等。

原理是,在音乐播放被中断时,暂停播放,在中断完成后,开始播放。具体做法是:
-->在通知中心注册一个事件中断的通知:
//处理中断事件的通知

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterreption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];

实现接收到中断通知时的方法

//处理中断事件

-(void)handleInterreption:(NSNotification *)sender
{
    if(_played)
    {
      [self.playView.player pause];
        _played=NO;
    }
    else
    {
        [self.playView.player play];
        _played=YES;
    }
}

4.至此音乐后台持续播放搞定,大功告成!现在可以打开软件播放一首歌曲,然后按home键回到后台,音乐会继续播放~

应简友要求,在此贴出播放器代码:

简单看下界面

iOS后台持续播放音乐_第2张图片
list
iOS后台持续播放音乐_第3张图片
player
iOS后台持续播放音乐_第4张图片
now play info center
  • PlayerViewController.h

#import "RootViewController.h"
#import "songInfoModel.h"
#import 
#import "PlayView.h"
#import "FMSongListModel.h"

@interface PlayerViewController : RootViewController

//下载链接
@property(nonatomic, strong)NSString        *sourceURLString;
@property(nonatomic, copy)NSString          *songname;
@property(nonatomic, copy)NSString          *singerName;
@property(nonatomic, copy)NSString          *songUrl;
@property(nonatomic, copy)NSString          *songPicUrl;
@property(nonatomic, strong)songInfoModel   *model;
@property(nonatomic,assign)NSInteger        currentSongIndex;
@property(nonatomic,strong)NSArray          *songArray;

+(instancetype)sharedPlayerController;
//刷新播放的歌曲
-(void)refreshWithModel:(songInfoModel *)sim;
//停止播放
-(void)stop;
//暂停
-(void)pauseMusic;

@end
  • PlayerViewController.m

#import "PlayerViewController.h"
#import 
#import "UIImageView+WebCache.h"
#import "mvListModel.h"
#import "PlayView.h"
#import "Word.h"
#import "auditionListModel.h"
#import "AFNetworking.h"
#import "QFHttpManager.h"
#import "QFHttpRequest.h"
#import 
#import "Maker.h"
#import 
#import "Constant.h"
#import "PopMenu.h"
#import "KxMenu.h"
#import "FMSongListModel.h"
#import "FMSongModel.h"
#import "MCDataEngine.h"
#import "ProgressHUD.h"
#import "DownloadViewController.h"
#import "DownloadModel.h"
#import "DownloadDBManager.h"
#import "FGGDownloadManager.h"
@interface PlayerViewController (){
    
    UITableView             *_tbView;
    //分享菜单
    PopMenu *_menu;
    UITapGestureRecognizer  *_hideShareGesture;
    //暂无歌词的提示Label
    UILabel                 *_noLrcLb;
}

@property(nonatomic,assign)MusicPlayType      playType;
//标记分享菜单是否显示
@property(nonatomic,assign)BOOL               isListShow;
//透明背景
@property(nonatomic,strong)UIView             *shareBackView;
@property(nonatomic,copy)NSString             *totalTime;
//当前歌词行
@property(nonatomic,assign)NSInteger          currentWordRow;
@property(nonatomic, strong)UIProgressView    *videoProgress;
@property(nonatomic, strong)UIImageView       *singerImageView;
@property(nonatomic,strong)NSArray            *wordsArray;
@property(nonatomic, strong)AVPlayerItem      *playerItem;
@property(nonatomic, strong)PlayView          *playView;
@property(nonatomic,assign)BOOL               played;
@property(nonatomic, strong)id                playbackTimeObserver;

@end
static PlayerViewController *musicController=nil;

@implementation MusicPicViewController

+(instancetype)sharedPlayerController{
    
    if(!musicController){
        
        musicController=[[PlayerViewController alloc] init];
    }
    return musicController;
}
- (void)viewDidLoad {
    
    [super viewDidLoad];
    [self setUp];
    [self createBackView];
    [self createUI];
    [self createTitleView];
    [self loadLyric];
    [self createShareList];
    [self preload];
    [self load];
}
//初始化
-(void)setUp {
    
    self.view.backgroundColor = [UIColor blackColor];
    self.automaticallyAdjustsScrollViewInsets=NO;
    self.navigationController.navigationBar.barStyle=UIBarStyleBlackOpaque;
    _currentWordRow=0;
    //默认循环播放
    _playType=MusicPlayTypeRound;
}
#pragma mark - 背景图片
-(void)createBackView {
    
    UIImageView * backImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 64, kWidth, kHeight-64-90)];
    backImageView.image = [UIImage returnImageWithName:@"bg.jpg"];
    backImageView.alpha=0.7;
    [self.view addSubview:backImageView];
}
- (void)createUI {
    
    _playView = [[PlayView alloc] initWithFrame:CGRectMake(0, 0, kWidth, kHeight)];
    [self.view addSubview:_playView];
    __weak typeof(self) weakSelf=self;
    _playView.nextBtnDidClickedBlock=^{
        if(weakSelf.playType==MusicPlayTypeRandom)
           [weakSelf randomNext];
        else
            [weakSelf next];
    };
    _playView.previousBtnDidClickedBlock=^{
        if(weakSelf.playType==MusicPlayTypeRandom)
            [weakSelf randomNext];
        else
            [weakSelf previous];
    };
    //切换播放模式
    _playView.typeBtnDidClickedBlock=^(UIButton *sender){
        
        if(weakSelf.playType==MusicPlayTypeRound){
            
            [sender setTitle:@"单曲" forState:UIControlStateNormal];
            //[sender setImage:[UIImage imageNamed:@"single"] forState:UIControlStateNormal];
            weakSelf.playType=MusicPlayTypeSingle;
            [ProgressHUD showSuccess:@"单曲循环"];
            
        }else if(weakSelf.playType==MusicPlayTypeSingle){
            
            [sender setTitle:@"随机" forState:UIControlStateNormal];
            //[sender setImage:[UIImage imageNamed:@"random"] forState:UIControlStateNormal];
            weakSelf.playType=MusicPlayTypeRandom;
            [ProgressHUD showSuccess:@"随机播放"];
            
        }else if(weakSelf.playType==MusicPlayTypeRandom){
            
            [sender setTitle:@"循环" forState:UIControlStateNormal];
            //[sender setImage:[UIImage imageNamed:@"round"] forState:UIControlStateNormal];
            weakSelf.playType=MusicPlayTypeRound;
            [ProgressHUD showSuccess:@"循环播放"];
        }
    };
    [self.playView.slider addTarget:self action:@selector(videoSliderChangeValue:) forControlEvents:UIControlEventValueChanged];
    
    self.videoProgress=[[UIProgressView alloc] initWithFrame:CGRectMake(93, kHeight-48, kWidth-180, 15)];
    _videoProgress.alpha=0.6;
    _videoProgress.progressTintColor=RGB(76, 168, 76);
    [self.view addSubview:_videoProgress];

    [self.playView.playButton addTarget:self action:@selector(onClickChangeState) forControlEvents:UIControlEventTouchUpInside];
    
    UIImageView * singerImageView =[[UIImageView alloc] initWithFrame:CGRectMake(10, kHeight-80, 60, 60)];
    singerImageView.tag=kSingerImageTag;
    self.singerImageView = singerImageView;
    if(self.model.mvListArray) {
        
        mvListModel * model=nil;
        if ([self.model.mvListArray count]){
            
             model= [self.model.mvListArray firstObject];
        }
        singerImageView.image=[UIImage imageNamed:@"defaultNomusic.png"];
        NSURL *url=nil;
        if(model.picUrl.length>0){
            
            url=[NSURL URLWithString:model.picUrl];
        }
        if(url){
            
            [singerImageView sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"defaultNomusic.png"]];
        }
        
    }else{
        
        NSURL *url=[NSURL URLWithString:self.songPicUrl];
        [singerImageView sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"defaultNomusic.png"]];
    }
    singerImageView.clipsToBounds = YES;
    singerImageView.layer.cornerRadius = 30;
    [self.view addSubview:singerImageView];
    
    //歌手头像循环滚动
    [self repeadRatation];
    
    _tbView=[[UITableView alloc]initWithFrame:CGRectMake(10, 64, kWidth-20,kHeight-64-90) style:UITableViewStylePlain];
    _tbView.delegate=self;
    _tbView.dataSource=self;
    _tbView.separatorStyle=UITableViewCellSeparatorStyleNone;
    [self.view addSubview:_tbView];
    _tbView.showsVerticalScrollIndicator=NO;
    _tbView.backgroundColor=[UIColor clearColor];
    
    //暂无歌词的label
    _noLrcLb=[[UILabel alloc]initWithFrame:CGRectMake(0, 0, 100, 40)];
    _noLrcLb.center=self.view.center;
    _noLrcLb.backgroundColor=[UIColor clearColor];
    _noLrcLb.textAlignment=NSTextAlignmentCenter;
    _noLrcLb.font=[UIFont systemFontOfSize:16];
    _noLrcLb.textColor=[UIColor whiteColor];
    [self.view addSubview:_noLrcLb];
    if(_wordsArray.count>0){
        
        _noLrcLb.text=nil;
        
    }else{
        
        _noLrcLb.text=@"暂无歌词~";
    }
}
-(void)createTitleView{
    
    UILabel *statusLb=[[UILabel alloc]initWithFrame:CGRectMake(0, 0, kWidth, 64)];
    statusLb.backgroundColor=RGB(76, 168, 76);
    [self.view addSubview:statusLb];
    
    UILabel * songlabel = [[UILabel alloc] initWithFrame:CGRectMake(40,15, kWidth-80, 34)];
    songlabel.numberOfLines=2;
    songlabel.tag=kSongNameTag;
    songlabel.text = self.model.name;
    songlabel.font = [UIFont boldSystemFontOfSize:15];
    songlabel.adjustsFontSizeToFitWidth=YES;
    songlabel.textColor = [UIColor whiteColor];
    songlabel.textAlignment = NSTextAlignmentCenter;
    songlabel.backgroundColor=[UIColor clearColor];
    [self.view addSubview:songlabel];
    
    UILabel * singerLabel = [[UILabel alloc] initWithFrame:CGRectMake(40, 50, kWidth-80, 10)];
    singerLabel.tag=kSingerNameTag;
    singerLabel.text = self.model.singerName;
    singerLabel.font = [UIFont systemFontOfSize:12];
    singerLabel.textColor = [UIColor whiteColor];
    singerLabel.textAlignment = NSTextAlignmentCenter;
    singerLabel.backgroundColor=[UIColor clearColor];
    [self.view addSubview:singerLabel];
    
    UIButton *menuBtn=[[UIButton alloc]initWithFrame:CGRectMake(kWidth-40, 30, 20, 16)];
    [menuBtn setImage:[UIImage imageNamed:@"list"] forState:UIControlStateNormal];
    [self.view addSubview:menuBtn];
    [menuBtn addTarget:self action:@selector(showMenu:) forControlEvents:UIControlEventTouchUpInside];
    
    UIButton * backButton = [[UIButton alloc] initWithFrame:CGRectMake(10, 20, 30, 30)];
    [backButton setImage:[UIImage returnImageWithName:@"back.png"] forState:UIControlStateNormal];
    [backButton addTarget:self action:@selector(onClickBack) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:backButton];
}
#pragma mark - 加载歌词
- (void)loadLyric{
    
    NSString * singerName = self.model.singerName;
    NSString * songName1 = self.model.name;
    NSArray * songNameArray = [songName1 componentsSeparatedByString:@"("];
    NSString * songName = songNameArray[0];
    NSString * lrcURL = [NSString stringWithFormat:SEARCH_LRC_URL, singerName, songName];
    NSString * newLrcURL = [lrcURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    [[QFHttpManager sharedManager] addTask:newLrcURL delegate:self action:@selector(requestFinished:)];
}
#pragma mark - 下载歌词
-(void)requestFinished:(QFHttpRequest*)Request{
    
    NSString * str = [[NSString alloc] initWithData:Request.downloadData encoding:NSUTF8StringEncoding];
    NSRange range = [str rangeOfString:@"/data2/lrc"];
    //暂无歌词的情况
    if (!range.length){
        
        _wordsArray=nil;
        [_tbView reloadData];
        _noLrcLb.text=@"暂无歌词~";
        return;
    }
    NSString * string = [str substringFromIndex:range.location];
    NSArray * array = [string componentsSeparatedByString:@">"];
    NSString * laststr = [NSString stringWithFormat:@"http://musicdata.baidu.com%@", array[1]];
    NSArray * lrcArray = [laststr componentsSeparatedByString:@"<"];
    NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:lrcArray[0]]];
    
    NSString * downloadPath = [NSString stringWithFormat:@"%@/%@-%@.lrc", kLrcPath,self.model.singerName,self.model.name];
    AFHTTPRequestOperation * requestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    requestOperation.outputStream = [NSOutputStream outputStreamToFileAtPath:downloadPath append:NO];
    [requestOperation start];
    __weak typeof(self) weakSelf=self;
    [requestOperation setCompletionBlock:^{
        
        [weakSelf readFileOfPath:downloadPath];
    }];
}
#pragma mark - 读取歌词
- (void)readFileOfPath:(NSString *)path{
    
    self.wordsArray=[[Word alloc] wordsWithFilePath:path];
    if(_wordsArray.count>0){
        
        _noLrcLb.text=nil;
    }
    [_tbView reloadData];
}
#pragma mark - 创建分享视图
-(void)createShareList {
    
    NSArray *names=@[@"微信",@"微信朋友圈",@"新浪微博",@"QQ",@"QQ空间",@"短信"];
    NSArray *images=@[@"wx",@"wx_friend",@"sina",@"qq",@"qzone",@"sms"];
    NSMutableArray *array=[NSMutableArray array];
    for(int i=0;i
#pragma mark - 显示隐藏分享视图
-(void)showSharelist{
    
    [self loadSound];
    if(_isListShow){
        
        if ([[self.view gestureRecognizers] containsObject:_hideShareGesture])
        {
            [self.view removeGestureRecognizer:_hideShareGesture];
        }
        [_menu dismissMenu];
        [_menu performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:0.3];
        _isListShow=NO;
    }
    else{
        
        _isListShow=YES;
        [_menu showMenuAtView:self.view.window];
        [self.view addGestureRecognizer:_hideShareGesture];
    }
}
-(void)loadSound {
    
    //播放音效
    SystemSoundID soundID;
    AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"open.wav" ofType:nil]],&soundID);
    //播放短音频
    AudioServicesPlaySystemSound(soundID);
    //增加震动效果
    //AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
-(void)preload{
    
    if(self.model.auditionArray){
        
        if(self.model.auditionArray.count>0){
            
            auditionListModel * auModel = [[auditionListModel alloc] init];
            if(self.model.auditionArray.count>0){
                
                auModel = self.model.auditionArray[0];
            }
            if (self.model.auditionArray.count >= 2) {
                
                auModel = self.model.auditionArray[1];
            }
            self.sourceURLString=auModel.url;
        }
        else{
            
            self.sourceURLString=[[NSString stringWithFormat:@"file://%@/%@.mp3",kMusicPath,self.model.name] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        }
        
    }else{
        
        self.sourceURLString=self.songUrl;
    }
}
-(void)load{
    
    NSURL * playURL=[NSURL URLWithString:self.sourceURLString];
    self.playerItem =[AVPlayerItem playerItemWithURL:playURL];
    //监听status属性
    [self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    //监听loadedTimeRanges
    [self.playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
    self.playView.player = [AVPlayer playerWithPlayerItem:self.playerItem];
    //播放结束 通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem];
    //处理中断事件的通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterreption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
    //处理远程控制
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(listeningRemoteControl:) name:kAppDidReceiveRemoteControlNotification object:nil];
    //注册删除已经下载的歌曲的通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downloadingStateDidChanged:) name:kDownloadMusicDidDeleteNotification object:nil];
    //注册歌曲下载完成的通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downloadingStateDidChanged:) name:kMusicDidFinishDownloadingNotification object:nil];
}
- (void)moviePlayDidEnd:(NSNotification *)notification {
    
    __weak typeof(self) weakSelf=self;
    [self.playView.player seekToTime:kCMTimeZero completionHandler:^(BOOL finished){
        
         switch (weakSelf.playType) {
                 
             case MusicPlayTypeRound:
                 
                 [weakSelf next];
                 break;
                 
            case MusicPlayTypeSingle:
                 
                 [weakSelf.playView.player play];
                 break;
                 
            case MusicPlayTypeRandom:
                 
                 [weakSelf randomNext];
                 break;
                 
             default:
                 break;
         }
    }];
}
#pragma mark - 处理中断事件
- (void)handleInterreption:(NSNotification *)sender {
    
    if(_played){
        
      [self.playView.player pause];
        _played=NO;
        
    }else{
        
        [self.playView.player play];
        _played=YES;
    }
}
#pragma mark - 接收到远程控制时执行的方法
-(void)listeningRemoteControl:(NSNotification *)sender{
    
    NSDictionary *dict=sender.userInfo;
    NSInteger order=[[dict objectForKey:@"order"] integerValue];
    switch (order) {
            
        case UIEventSubtypeRemoteControlPause:{
            
            [self onClickChangeState];
            break;
        }
        case UIEventSubtypeRemoteControlPlay:{
            
            [self onClickChangeState];
            break;
        }
        case UIEventSubtypeRemoteControlTogglePlayPause:{
            
            [self onClickChangeState];
            break;
        }
        case UIEventSubtypeRemoteControlNextTrack:{
            
            if(self.playType==MusicPlayTypeRandom){
                
                [self randomNext];
                
            }else{
                
                [self next];
            }
            break;
        }
        case UIEventSubtypeRemoteControlPreviousTrack:{
            
            if(self.playType==MusicPlayTypeRandom){
                
                [self randomNext];
                
            }else{
                
                [self previous];
            }
            break;
        }
        default:
            break;
    }
}
#pragma mark - 播放状按钮
-(void)onClickChangeState {
    
    if(self.model){
        
        [self setNowPlayingInfo];
    }
    if (!_played){
        
        [self.playView.player play];
        self.playView.playButton.selected=YES;
        
    }else{
        
        [self.playView.player pause];
        self.playView.playButton.selected=NO;
    }
    _played = !_played;
}
#pragma mark -设置控制中心正在播放的信息

-(void)setNowPlayingInfo{
    
    NSMutableDictionary *songDict=[NSMutableDictionary dictionary];
    [songDict setObject:self.model.name forKey:MPMediaItemPropertyTitle];
    [songDict setObject:self.model.singerName forKey:MPMediaItemPropertyArtist];
    [songDict setObject:[NSNumber numberWithDouble:CMTimeGetSeconds(self.playerItem.duration)] forKeyedSubscript:MPMediaItemPropertyPlaybackDuration];
    //设置歌曲图片
    MPMediaItemArtwork *imageItem=[[MPMediaItemArtwork alloc]initWithImage:_singerImageView.image];
    [songDict setObject:imageItem forKey:MPMediaItemPropertyArtwork];
    
    [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songDict];
    [MPNowPlayingInfoCenter defaultCenter];
}
#pragma mark -随机下一首
-(void)randomNext {
    
    if(self.songArray.count==0){
        
        return;
    }
    if((!self.songUrl||self.songUrl.length==0)){
        
        NSInteger songIndex=arc4random()%_songArray.count;
        self.model=[self.songArray objectAtIndex:songIndex];
        [self refreshWithModel:self.model];
        
    }else{
        
        _currentSongIndex=arc4random()%_songArray.count;
        FMSongListModel *lm=[_songArray objectAtIndex:_currentSongIndex];
    
        MCDataEngine * network = [MCDataEngine new];
        __weak typeof(self) weakSelf=self;
        [ProgressHUD show:@"Loading"];
        [network getSongInformationWith:lm.song_id WithCompletionHandler:^(FMSongModel *smodel) {
            
            [ProgressHUD dismiss];
            //获取歌曲信息
            NSString *songName=smodel.songName;
            NSString *songUrl=smodel.songLink;
            NSString *singerName=lm.author;
            songInfoModel *sim=[songInfoModel new];
            sim.name=songName;
            sim.singerName=singerName;
            
            weakSelf.songUrl=songUrl;
            weakSelf.songPicUrl=smodel.songPicBig;
            weakSelf.model=sim;
            [weakSelf refreshWithModel:sim];
            
        } errorHandler:^(NSError *error) {
            
            [ProgressHUD showError:error.localizedDescription];
        }];
    }
}
#pragma mark - 下一首
//播放下一首
-(void)next{
    
    //若为单曲循环,则不切歌
    if(self.playType==MusicPlayTypeSingle){
        
        return;
    }
    if(self.songArray.count==0){
        
        return;
    }
    if((!self.songUrl||self.songUrl.length==0)){
        
        NSInteger songIndex=[self.songArray indexOfObject:self.model];
        if(songIndex0){
            
            self.model=[self.songArray objectAtIndex:songIndex-1];
            
        }else{
            
            self.model=self.songArray.lastObject;
        }
        [self refreshWithModel:self.model];
    }
    else{
        
        FMSongListModel *lm=nil;
        if(_currentSongIndex>0){
            
            _currentSongIndex--;
            lm=[self.songArray objectAtIndex:_currentSongIndex];
            
        }else{
            
            _currentSongIndex=self.songArray.count-1;
            lm=self.songArray.lastObject;
        }
        MCDataEngine * network = [MCDataEngine new];
        __weak typeof(self) weakSelf=self;
        [ProgressHUD show:@"Loading"];
        [network getSongInformationWith:lm.song_id WithCompletionHandler:^(FMSongModel *smodel) {
            
            [ProgressHUD dismiss];
            //获取歌曲信息
            NSString *songName=smodel.songName;
            NSString *songUrl=smodel.songLink;
            NSString *singerName=lm.author;
            songInfoModel *sim=[songInfoModel new];
            sim.name=songName;
            sim.singerName=singerName;
            
            weakSelf.songUrl=songUrl;
            weakSelf.songPicUrl=smodel.songPicBig;
            weakSelf.model=sim;
            [weakSelf refreshWithModel:sim];
            
        } errorHandler:^(NSError *error) {
            
            [ProgressHUD showError:error.localizedDescription];
        }];
    }
}
#pragma mark - 刷新播放的歌曲

-(void)refreshWithModel:(songInfoModel *)sim
{
    self.model=sim;
    self.playView.playButton.enabled = NO;
    self.playView.playButton.selected=NO;
    [self.playView.slider setValue:0.0 animated:YES];
    UIProgressView *progress=(UIProgressView *)[self.view viewWithTag:MUSIC_PROGRESS_TAG];
    [progress setProgress:0.0 animated:YES];
    _currentWordRow=0;
    if((!self.songUrl||self.songUrl.length==0)){
        
        mvListModel * model=nil;
        if ([sim.mvListArray count]){
            
            model= [sim.mvListArray firstObject];
        }
        NSURL *url=nil;
        if(model.picUrl.length>0){
            
            url=[NSURL URLWithString:model.picUrl];
        }
        if(url){
            
            UIImageView *smiv=(UIImageView *)[self.view viewWithTag:kSingerImageTag];
            [smiv sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"defaultNomusic.png"]];
        }
        
    }else{
        
        UIImageView *smiv=(UIImageView *)[self.view viewWithTag:kSingerImageTag];
        [smiv sd_setImageWithURL:[NSURL URLWithString:self.songPicUrl] placeholderImage:[UIImage imageNamed:@"defaultNomusic.png"]];
    }
    UILabel *songNameLb=(UILabel *)[self.view viewWithTag:kSongNameTag];
    UILabel *singerNameLb=(UILabel *)[self.view viewWithTag:kSingerNameTag];
    songNameLb.text=sim.name;
    singerNameLb.text=sim.singerName;
    if(!self.songUrl||self.songUrl.length==0){
        
        if(sim.auditionArray.count>0){
            
            auditionListModel * auModel = [[auditionListModel alloc] init];
            if(sim.auditionArray.count>0){
                
                auModel = sim.auditionArray[0];
            }
            if (sim.auditionArray.count >= 2) {
                
                auModel = sim.auditionArray[1];
            }
            self.sourceURLString=auModel.url;
            
        }else{
            
            self.sourceURLString=[[NSString stringWithFormat:@"file://%@/%@.mp3",kMusicPath,sim.name] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        }
        
    }else{
        
        self.sourceURLString=self.songUrl;
    }
    NSURL * playURL=[NSURL URLWithString:self.sourceURLString];
    //先移除observer
    [self.playerItem removeObserver:self forKeyPath:@"status"];
    [self.playerItem removeObserver:self forKeyPath:@"loadedTimeRanges"];
    //播放结束 通知
    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem];
    if([self.playView.player observationInfo]){
        
        self.playbackTimeObserver=nil;
    }
    if(self.playerItem){
        
        self.playerItem=nil;
    }
    self.playerItem =[AVPlayerItem playerItemWithURL:playURL];
    //监听status属性
    [self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    //监听loadedTimeRanges
    [self.playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
    //播放结束 通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem];
    if(self.playView.player){
        
        if(_played){
            
            [self.playView.player pause];
        }
        self.playView.player=nil;
    }
    self.playView.player = [AVPlayer playerWithPlayerItem:self.playerItem];
    //播放结束 通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem];
    //加载歌词
    [self loadLyric];
}
//接收到下载页面左滑删除的通知时 或 音乐下载完毕时
-(void)downloadingStateDidChanged:(NSNotification *)sender{
    
    //如果播放的列表是下载歌曲列表
    if(self.model.musicURL.length>0){
        
        NSMutableArray *songInfoArray=[NSMutableArray array];
        NSArray *array=[[DownloadDBManager sharedManager] getAllRecords];
        for(DownloadModel *m in array){
            
            if([[FGGDownloadManager shredManager] lastProgress:m.urlString]==1.0){
                
                songInfoModel *s=[songInfoModel new];
                s.name=m.song_name;
                s.singerName=m.singger_name;
                s.musicURL=m.urlString;
                [songInfoArray addObject:s];
            }
        }
        self.songArray=songInfoArray;
    }
}
#pragma mark - 点击分享项目时
-(void)selectItem:(MenuItem *)item{
    
    ShareType type;
    switch (item.index) {
            
        case 0:
            
            type=ShareTypeWeixiSession;
            break;
            
        case 1:
            
            type=ShareTypeWeixiTimeline;
            break;
            
        case 2:
            
            type=ShareTypeSinaWeibo;
            break;
            
        case 3:
            
            type=ShareTypeQQ;
            break;
            
        case 4:
            
            type=ShareTypeQQSpace;
            break;
            
        case 5:
            
            type=ShareTypeSMS;
            break;
            
        default:
            break;
    }
    NSString *contentString=@"在线听歌看MV,快来试试吧!";
    NSString *imgPath=[[NSBundle mainBundle] pathForResource:@"icon-share" ofType:@"png"];
    NSString *title=[NSString stringWithFormat:@"歌曲-%@",self.model.name];
    NSString *shareURLString;
    if([self.sourceURLString hasPrefix:@"file:"]){
        
        shareURLString=self.model.musicURL;
        
    }else{
        
        shareURLString=self.sourceURLString;
    }
    
    id pushContent=[ShareSDK content:contentString
                                  defaultContent:contentString
                                           image:[ShareSDK imageWithPath:imgPath]
                                           title:title
                                             url:shareURLString
                                     description:contentString
                                       mediaType:SSPublishContentMediaTypeMusic];
    
    [ShareSDK showShareViewWithType:type
                          container:nil
                            content:pushContent
                      statusBarTips:YES
                        authOptions:nil
                       shareOptions:nil
                             result:^(ShareType type, SSResponseState state, id statusInfo, id error, BOOL end) {
                                 
                                 if (state==SSResponseStateSuccess){
                                     
                                     [ProgressHUD showSuccess:@"分享成功"];
                                     
                                 }else if (state==SSResponseStateFail){
                                     
                                     NSString *errorMessage=[error errorDescription];
                                     UIAlertView *a=[[UIAlertView alloc]initWithTitle:@"错误" message:errorMessage delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
                                     [a show];
                                 }
                             }];
    //隐藏分享列表
    [self showSharelist];
}
//移动slider值变化
- (void)videoSliderChangeValue:(UISlider *)slider{
    
    if(self.playView.player.status!=AVPlayerStatusReadyToPlay){
        
        return;
    }
    CMTime changedTime = CMTimeMakeWithSeconds(slider.value, 1);
    __weak typeof(self) weakSelf=self;
    [self.playView.player seekToTime:changedTime completionHandler:^(BOOL finished) {
        
        [weakSelf.playView.player play];
        weakSelf.playView.playButton.selected = YES;
        weakSelf.played = YES;
    }];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    AVPlayerItem * playerItem = (AVPlayerItem *)object;
    if ([keyPath isEqualToString:@"status"]){
        
        if ([playerItem status] == AVPlayerStatusReadyToPlay){
            
            self.playView.playButton.enabled = YES;
            self.playView.playButton.selected=YES;
            [self.playView.player play];
            //设置正在播放信息
            [self setNowPlayingInfo];
            _played=YES;
            
            //获取音乐总长度
            CMTime duration = self.playerItem.duration;
            self.playView.slider.maximumValue = CMTimeGetSeconds(duration);
            
            //转换成秒
            CGFloat totalSecond = playerItem.duration.value / playerItem.duration.timescale;// 转换成秒
            _totalTime = [self convertTime:totalSecond];
            
            // 监听播放状态
            [self monitoringPlayback:self.playerItem];
            
        }else if([playerItem status] == AVPlayerStatusFailed){
            
            [ProgressHUD showError:@"加载失败"];
        }
        
    }else if ([keyPath isEqualToString:@"loadedTimeRanges"]){
        
        NSTimeInterval timeInterval = [self availableDuration];// 计算缓冲进度
        CMTime duration = self.playerItem.duration;
        CGFloat totalDuration = CMTimeGetSeconds(duration);
        [self.videoProgress setProgress:timeInterval/totalDuration animated:YES];
    }
}
- (NSTimeInterval)availableDuration{
    
    NSArray *loadedTimeRanges = [[self.playView.player currentItem] loadedTimeRanges];
    CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue];// 获取缓冲区域
    float startSeconds = CMTimeGetSeconds(timeRange.start);
    float durationSeconds = CMTimeGetSeconds(timeRange.duration);
    NSTimeInterval result = startSeconds + durationSeconds;// 计算缓冲总进度
    return result;
}
- (void)monitoringPlayback:(AVPlayerItem *)playerItem{
    
    __weak typeof(self) weakSelf=self;
    
    if(self.playbackTimeObserver){
        
        self.playbackTimeObserver=nil;
    }
    self.playbackTimeObserver = [self.playView.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:NULL usingBlock:^(CMTime time){
        
        CGFloat currentSecond = playerItem.currentTime.value/playerItem.currentTime.timescale;// 计算当前在第几秒
        [weakSelf updateVideoSlider:currentSecond];
        
        //更新控制中心歌曲的当前时间
        NSDictionary *info=[[MPNowPlayingInfoCenter defaultCenter] nowPlayingInfo];
        NSMutableDictionary *dict=[NSMutableDictionary dictionaryWithDictionary:info];
        [dict setObject:@(currentSecond) forKeyedSubscript:MPNowPlayingInfoPropertyElapsedPlaybackTime];
        [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:dict];
        
        NSString *timeString = [weakSelf convertTime:currentSecond];
        UILabel * timeLabel = (id)[weakSelf.view viewWithTag:TIME_LABEL_TAG];
        timeLabel.text = [NSString stringWithFormat:@"%@/%@",timeString,weakSelf.totalTime];
    }];
}
- (NSString *)convertTime:(CGFloat)second{
    
    NSDate * d = [NSDate dateWithTimeIntervalSince1970:second];
    NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
    if (second/3600>=1){
        
        [formatter setDateFormat:@"HH:mm:ss"];
        
    }else{
        
        [formatter setDateFormat:@"mm:ss"];
    }
    NSString * showtimeNew = [formatter stringFromDate:d];
    return showtimeNew;
}
#pragma mark - TableView
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    
    return _wordsArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
    static NSString *cid=@"cid";
    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cid];
    if(!cell){
        
        cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cid];
    }
    cell.backgroundColor=[UIColor clearColor];
    cell.selectionStyle=UITableViewCellSelectionStyleNone;
    Word *word=_wordsArray[indexPath.row];
    cell.textLabel.text=word.text;
    cell.textLabel.font=[UIFont systemFontOfSize:14];
    cell.textLabel.numberOfLines=0;
    cell.textLabel.textAlignment=NSTextAlignmentCenter;
    cell.textLabel.alpha=0.6;
    cell.textLabel.textColor=[UIColor whiteColor];
    if(indexPath.row==_currentWordRow){
        
        cell.textLabel.textColor=[UIColor yellowColor];
        cell.textLabel.font=[UIFont systemFontOfSize:16];
    }
    return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    return 40;
}
//离开页面时,隐藏播放列表
-(void)viewWillDisappear:(BOOL)animated{
    
    [super viewWillDisappear:animated];
    if(_isListShow){
        
        [self showSharelist];
    }
}
-(BOOL)prefersStatusBarHidden{
    
    return YES;
}
#pragma mark - 歌手头像循环滚动
-(void)repeadRatation{
    
    [UIView beginAnimations:@"animation" context:nil];
    [UIView setAnimationDuration:4];
    [UIView setAnimationDelegate:self];
    //循环调用,可以让让动画无限循环
    [UIView setAnimationDidStopSelector:@selector(repeadRatation)];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    _singerImageView.transform=CGAffineTransformRotate(_singerImageView.transform, M_PI);
    [UIView commitAnimations];
}
//时间走动设置
- (void)updateVideoSlider:(CGFloat)currentSecond{
    
    [self.playView.slider setValue:currentSecond animated:YES];
    //歌词同步
    [self setCurrentWordWithTime:currentSecond];
}

#pragma mark - 设置歌词滚动
-(void)setCurrentWordWithTime:(CGFloat)currentTime {
    
    if(_wordsArray.count>0){
        
        for(int i=0;i<=_wordsArray.count-1;i++){
            
            Word *rear=_wordsArray[i];
            if(currentTime>=rear.timeLength){
                
                _currentWordRow=i;
                [_tbView reloadData];
                [_tbView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:_currentWordRow inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
            }
        }
    }
}
#pragma mark - 停止播放
-(void)stop{
    
    self.playView.playButton.selected = NO;
    [[QFHttpManager sharedManager] removeAllTask:self];
    //移除观察者及通知
    [self.playerItem removeObserver:self forKeyPath:@"status" context:nil];
    [self.playerItem removeObserver:self forKeyPath:@"loadedTimeRanges" context:nil];
    //播放结束
    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem];
    //处理远程控制
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kAppDidReceiveRemoteControlNotification object:nil];
    //中断通知注销
    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
    //删除下载歌曲通知注销
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kDownloadMusicDidDeleteNotification object:nil];
    //注销音乐下载完成的通知
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kMusicDidFinishDownloadingNotification object:nil];
    
    if([self.playView.player observationInfo]){
        
        self.playbackTimeObserver=nil;
    }
    if(_played){
        
        [self.playView.player pause];
    }
    self.playView.player = nil;
    self.playerItem=nil;
    if(musicController){
        
        musicController=nil;
    }
}
#pragma mark - 暂停
-(void)pauseMusic{
    
    if(_played){
        
        [self.playView.player pause];
        self.playView.playButton.selected=NO;
        _played = NO;
        
    }else{
        
        if(self.model){
            
            [self.playView.player play];
            self.playView.playButton.selected=YES;
            _played =YES;
        }
    }
}
  • PlayerView.h

#import 
#import 

@interface PlayView : UIView

@property (nonatomic, strong) UIButton * playButton;
@property (nonatomic, strong) AVPlayer * player;
@property (nonatomic, strong) UISlider * slider;
//@property (nonatomic, strong) UIProgressView *videoProgress;
@property(nonatomic,copy)void (^nextBtnDidClickedBlock)();
@property(nonatomic,copy)void (^previousBtnDidClickedBlock)();
@property(nonatomic,copy)void (^typeBtnDidClickedBlock)(UIButton *sender);

@end
  • PlayerView.m

#import "PlayView.h"
#import "Constant.h"

@implementation PlayView

- (instancetype)initWithFrame:(CGRect)frame{
    
    if (self = [super initWithFrame:frame]){
        
        UIView *backView=[[UIView alloc] initWithFrame:CGRectMake(0, kHeight-90, kWidth, 90)];
        backView.backgroundColor=RGB(76, 168, 76);
        [self addSubview:backView];
        
        //播放按钮
        self.playButton = [[UIButton alloc] initWithFrame:CGRectMake(kWidth/2-12.5,  kHeight-38, 25, 25)];
        _playButton.tag = PLAYSTOP_BUTTON_TAG;
        [_playButton setImage:[UIImage imageNamed:@"GplayButton"] forState:UIControlStateNormal];
        [_playButton setImage:[UIImage imageNamed:@"Pause1"] forState:UIControlStateSelected];
        [self addSubview:_playButton];
        
        //上一首
        UIButton *previousBtn=[[UIButton alloc]initWithFrame:CGRectMake(CGRectGetMinX(_playButton.frame)-50, kHeight-38, 25, 25)];
        [previousBtn setImage:[UIImage imageNamed:@"stepbackward"] forState:UIControlStateNormal];
        [self addSubview:previousBtn];
        [previousBtn addTarget:self action:@selector(previousAction) forControlEvents:UIControlEventTouchUpInside];
        
        //下一首
        UIButton *nextBtn=[[UIButton alloc]initWithFrame:CGRectMake(CGRectGetMaxX(_playButton.frame)+25, kHeight-38, 25, 25)];
        [nextBtn setImage:[UIImage imageNamed:@"stepforward"] forState:UIControlStateNormal];
        [self addSubview:nextBtn];
        [nextBtn addTarget:self action:@selector(nextAction) forControlEvents:UIControlEventTouchUpInside];
        //滑动条
        self.slider=[[UISlider alloc] initWithFrame:CGRectMake(91, kHeight-55, kWidth-176, 15)];
        [_slider setMinimumTrackTintColor:RGB(196, 192, 192)];
        [_slider setMaximumTrackTintColor:[UIColor whiteColor]];
        
        [_slider setThumbImage:[UIImage imageNamed:@"player-progress-point-h"] forState:UIControlStateNormal];
        [self addSubview:self.slider];
        
        //时间
        UILabel * timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(kWidth/2-50, kHeight-80, 100, 20)];
        timeLabel.font=[UIFont systemFontOfSize:14];
        timeLabel.textAlignment=NSTextAlignmentCenter;
        timeLabel.text = @"00:00/00:00";
        timeLabel.adjustsFontSizeToFitWidth=YES;
        timeLabel.textColor = [UIColor whiteColor];
        timeLabel.tag = TIME_LABEL_TAG;
        [self addSubview:timeLabel];
        
        //播放模式切换按钮
        UIButton *typeBtn=[[UIButton alloc]initWithFrame:CGRectMake(kWidth-60, kHeight-60, 40, 30)];
        [typeBtn setTitle:@"循环" forState:UIControlStateNormal];
        typeBtn.titleLabel.font=[UIFont boldSystemFontOfSize:14];
        [typeBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
        [self addSubview:typeBtn];
        [typeBtn addTarget:self action:@selector(typeTroggleAction:) forControlEvents:UIControlEventTouchUpInside];
    }
    return self;
}
//上一首
-(void)previousAction{
    
    if(self.previousBtnDidClickedBlock){
        
        self.previousBtnDidClickedBlock();
    }
}
//下一首
-(void)nextAction{
    
    if(self.nextBtnDidClickedBlock){
        
        self.nextBtnDidClickedBlock();
    }
}
//模式切换
-(void)typeTroggleAction:(UIButton *)sender{
    
    if(self.typeBtnDidClickedBlock){
        
        self.typeBtnDidClickedBlock(sender);
    }
}
@end
  • AppDelegate.m

#import "AppDelegate.h"
#import "ReadingViewController.h"
#import "RelatedShareSDK.h"

#import 
#import 
#import 
#import "WXApi.h"
#import "WeiboSDK.h"

#import 

#import "PlayerViewController.h"
#import "QFHttpManager.h"

#import "LeftViewController.h"
#import "Constant.h"
#import "CustomTabBarController.h"
#import "FGGDownloadManager.h"

@interface AppDelegate ()
{
    //后台播放任务Id
    UIBackgroundTaskIdentifier _bgTaskId;
}
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    [self setUp];
    
    [ShareSDK registerApp:Appkey_ShareSDK];
    [self initilizePlatform];
    
    CustomTabBarController *tabBar=[[CustomTabBarController alloc]init];
    LeftViewController *left=[[LeftViewController alloc]init];
    _sideMenu=[[RESideMenu alloc]initWithContentViewController:tabBar leftMenuViewController:left rightMenuViewController:nil];
    
    self.window.rootViewController=_sideMenu;
    
    //开启后台处理多媒体事件
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
    
    return YES;
}
//初始化
-(void)setUp
{
    //移动资源文件
    NSString *dbPath = [docPath stringByAppendingPathComponent:@"FreeMusic.db"];
    if (![[NSFileManager defaultManager] fileExistsAtPath:dbPath])
    {
        NSString *srcPath = [[NSBundle mainBundle] pathForResource:@"FreeMusic" ofType:@"db"];
        [[NSFileManager defaultManager] copyItemAtPath:srcPath toPath:dbPath error:nil];
    }
    //创建歌词文件夹
    if(![[NSFileManager defaultManager] fileExistsAtPath:kLrcPath])
    {
        [[NSFileManager defaultManager] createDirectoryAtPath:kLrcPath withIntermediateDirectories:YES attributes:nil error:nil];
    }
    //创建歌曲下载文件夹
    if(![[NSFileManager defaultManager] fileExistsAtPath:kMusicPath])
    {
        [[NSFileManager defaultManager]createDirectoryAtPath:kMusicPath withIntermediateDirectories:YES attributes:nil error:nil];
    }
}
-(void)initilizePlatform
{
    /**
     连接微信应用以使用相关功能,此应用需要引用WeChatConnection.framework和微信官方SDK
     http://open.weixin.qq.com上注册应用,并将相关信息填写以下字段
     **/
    [ShareSDK connectWeChatWithAppId:kWXAppkey
                           appSecret:kWXSecret
                           wechatCls:[WXApi class]];
    //微信朋友圈
    [ShareSDK connectWeChatTimelineWithAppId:kWXAppkey
                                   appSecret:kWXSecret
                                   wechatCls:[WXApi class]];
    /**
     连接新浪微博开放平台应用以使用相关功能,此应用需要引用SinaWeiboConnection.framework
     http://open.weibo.com上注册新浪微博开放平台应用,并将相关信息填写到以下字段
     **/
    [ShareSDK connectSinaWeiboWithAppKey:kWeiboAppkey
                               appSecret:kWeiboSecret
                             redirectUri:kSinaURI];
    /**
     连接QQ应用以使用相关功能,此应用需要引用QQConnection.framework和QQApi.framework库
     http://mobile.qq.com/api/上注册应用,并将相关信息填写到以下字段
     **/
    [ShareSDK connectQQWithQZoneAppKey:kQQAppkey
                     qqApiInterfaceCls:[QQApiInterface class]
                       tencentOAuthCls:[TencentOAuth class]];
    /**
     连接QQ空间应用以使用相关功能,此应用需要引用QZoneConnection.framework
     http://connect.qq.com/intro/login/上申请加入QQ登录,并将相关信息填写到以下字段
     
     如果需要实现SSO,需要导入TencentOpenAPI.framework,并引入QQApiInterface.h和TencentOAuth.h,将QQApiInterface和TencentOAuth的类型传入接口
     **/
    [ShareSDK connectQZoneWithAppKey:kQQAppkey
                           appSecret:kQQSecret
                   qqApiInterfaceCls:[QQApiInterface class]
                     tencentOAuthCls:[TencentOAuth class]];
    
    //短信
//    [ShareSDK connectSMS];     
}
- (BOOL)application:(UIApplication *)application
      handleOpenURL:(NSURL *)url
{
    return [ShareSDK handleOpenURL:url
                        wxDelegate:self];
}

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation
{
    return [ShareSDK handleOpenURL:url
                 sourceApplication:sourceApplication
                        annotation:annotation
                        wxDelegate:self];
}

-(void)applicationWillResignActive:(UIApplication *)application
{
    AVAudioSession *session=[AVAudioSession sharedInstance];
    [session setActive:YES error:nil];
    //后台播放
    [session setCategory:AVAudioSessionCategoryPlayback error:nil];
    
    _bgTaskId=[AppDelegate backgroundPlayerID:_bgTaskId];
}
+(UIBackgroundTaskIdentifier)backgroundPlayerID:(UIBackgroundTaskIdentifier)backTaskId
{
    //设置并激活音频会话类别
    AVAudioSession *session=[AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategoryPlayback error:nil];
    [session setActive:YES error:nil];
    //允许应用程序接收远程控制
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
    //设置后台任务ID
    UIBackgroundTaskIdentifier newTaskId=UIBackgroundTaskInvalid;
    newTaskId=[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
    if(newTaskId!=UIBackgroundTaskInvalid&&backTaskId!=UIBackgroundTaskInvalid)
    {
        [[UIApplication sharedApplication] endBackgroundTask:backTaskId];
    }
    return newTaskId;
}
#pragma mark - 接收到远程控制事件

-(void)remoteControlReceivedWithEvent:(UIEvent *)event
{
    if(event.type==UIEventTypeRemoteControl)
    {
        NSInteger order=-1;
        switch (event.subtype) {
            case UIEventSubtypeRemoteControlPause:
                order=UIEventSubtypeRemoteControlPause;
                break;
            case UIEventSubtypeRemoteControlPlay:
                order=UIEventSubtypeRemoteControlPlay;
                break;
            case UIEventSubtypeRemoteControlNextTrack:
                order=UIEventSubtypeRemoteControlNextTrack;
                break;
            case UIEventSubtypeRemoteControlPreviousTrack:
                order=UIEventSubtypeRemoteControlPreviousTrack;
                break;
            case UIEventSubtypeRemoteControlTogglePlayPause:
                order=UIEventSubtypeRemoteControlTogglePlayPause;
                break;
            default:
                order=-1;
                break;
        }
        NSDictionary *orderDict=@{@"order":@(order)};
        //发送通知
        [[NSNotificationCenter defaultCenter] postNotificationName:kAppDidReceiveRemoteControlNotification object:nil userInfo:orderDict];
    }
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
}

- (void)applicationWillEnterForeground:(UIApplication *)application {

}

- (void)applicationDidBecomeActive:(UIApplication *)application {

}
- (void)applicationWillTerminate:(UIApplication *)application {
    
    PlayerViewController *music=[PlayerViewController sharedPlayerController];
    [music stop];
    //取消所有下载任务
    [[FGGDownloadManager shredManager] cancelAllTasks];
}
@end
iOS后台持续播放音乐_第5张图片

你可能感兴趣的:(iOS后台持续播放音乐)