之前在App Store上架了一个音乐播放器软件,用的是AVPlayer做的音乐播放器。很多用户反映没有后台播放,最近决定更新一下。
注意,重点是持续后台播放,网络歌曲也可以,重点是持续播放,后台播放很简单,但是后台持续播放,则需要做一些处理,申请后台id,才能实现持续播放。
1.开启所需要的后台模式:
选中Targets-->Capabilities-->BackgroundModes-->ON,
并勾选Audio and AirPlay选项,如下图
设置后台模式
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键回到后台,音乐会继续播放~
应简友要求,在此贴出播放器代码:
简单看下界面
list player now play info center-
PlayerViewController.h
#import "RootViewController.h"
#import "songInfoModel.h"
#import <AVFoundation/AVFoundation.h>
#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 <AVFoundation/AVFoundation.h>
#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 <ShareSDK/ShareSDK.h>
#import "Maker.h"
#import <MediaPlayer/MediaPlayer.h>
#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 ()<UITableViewDataSource, UITableViewDelegate>{
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:@"<lrclink>/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<names.count;i++){
MenuItem *item=[MenuItem itemWithTitle:names[i] iconName:images[i]];
[array addObject:item];
}
_menu=[[PopMenu alloc]initWithFrame:CGRectMake(kWidth/2-160, kHeight/2-150, 320, 320) items:array];
_menu.menuAnimationType=kPopMenuAnimationTypeNetEase;
_menu.backgroundColor=[UIColor clearColor];
__weak typeof(self) weakSelf=self;
_menu.didSelectedItemCompletion=^(MenuItem *item){
[weakSelf selectItem:item];
};
_hideShareGesture=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(showSharelist)];
}
#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(songIndex<self.songArray.count-1){
self.model=[self.songArray objectAtIndex:songIndex+1];
}else{
self.model=[self.songArray objectAtIndex:0];
}
[self refreshWithModel:self.model];
}else{
FMSongListModel *lm=nil;
if(_currentSongIndex<self.songArray.count-1){
_currentSongIndex++;
lm=[self.songArray objectAtIndex:_currentSongIndex];
}else{
_currentSongIndex=0;
lm=[self.songArray objectAtIndex:0];
}
MCDataEngine * network = [MCDataEngine new];
__weak typeof(self) weakSelf=self;
[network getSongInformationWith:lm.song_id WithCompletionHandler:^(FMSongModel *smodel) {
//获取歌曲信息
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) {
NSLog(@"%@",error.localizedDescription);
}];
}
}
#pragma mark - 上一首
-(void)previous
{
if(self.songArray.count==0){
return;
}
//若为单曲循环,则不切歌
if(self.playType==MusicPlayTypeSingle){
return;
}
if((!self.songUrl||self.songUrl.length==0)){
NSInteger songIndex=[self.songArray indexOfObject:self.model];
if(songIndex>0){
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<ISSContent> 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<ISSPlatformShareInfo> statusInfo, id<ICMErrorInfo> 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 <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@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 <ShareSDK/ShareSDK.h>
#import <TencentOpenAPI/QQApiInterface.h>
#import <TencentOpenAPI/TencentOAuth.h>
#import "WXApi.h"
#import "WeiboSDK.h"
#import <AVFoundation/AVFoundation.h>
#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
网友评论
你去app store下一个“音乐榜”,里面虽然很多接口都无法访问了,但是第二个tab“歌手榜”,随便选个歌手,随便播放一首歌,然后按home键,是可以正常播放的。而这个app的代码就是本文的代码播放器部分。
@Implementation MusicPicViewController
+(instancetype)sharedPlayerController{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
musicController=[[MusicPicViewController alloc] init];
});
return musicController;
}
#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];
}
AVAudioSession *a = [AVAudioSession sharedInstance];
[a setCategory:AVAudioSessionCategoryPlayback error:nil];