//  ViewController.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h> @class AVAudioPlayer; @interface PlayViewController : UIViewController<AVAudioPlayerDelegate> @property(nonatomic, strong) AVAudioPlayer *player; + (PlayViewController *)defaultPlayVC; //将该播放页面定义成单例 @end
//  ViewController.m
#import "PlayViewController.h" @interface PlayViewController () @property (retain, nonatomic) IBOutlet UIButton *suspendBtn; //暂停按钮
@property (retain, nonatomic) IBOutlet UIButton *formerBtn; //上一首按钮
@property (retain, nonatomic) IBOutlet UIButton *nextBtn; //下一首按钮
@property (retain, nonatomic) IBOutlet UISlider *slider; //滑块
@property (retain, nonatomic) NSArray *musicUrlArray; //音乐网址数组
@property (retain, nonatomic) NSArray *musicAllTimeArray; //音乐时间数组
@property (retain, nonatomic) NSTimer *timer; //计时器
@property (assign, nonatomic) int currentIndex; //当前音频下标 @end @implementation PlayViewController
#pragma mark 单例初始化方法
+ (PlayViewController *)defaultPlayVC {
static PlayViewController *playVC = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
playVC = [[PlayViewController alloc] init];
});
return playVC;
} - (void)viewDidLoad {
[super viewDidLoad];
self.currentIndex = 0;
self.musicUrlArray = [NSArray arrayWithObjects:@"http://fdfs.xmcdn.com/group10/M08/D4/2E/wKgDaVZ9EYaQ-j48AFIOaAXL-wM019.mp3",
@"http://fdfs.xmcdn.com/group13/M09/D4/17/wKgDXVZ6fR2wR1E8AFuO_VClRZA066.mp3",
@"http://fdfs.xmcdn.com/group16/M0A/D5/16/wKgDbFZ89SqyFGWGAHoEKd7yPsw709.mp3",
@"http://fdfs.xmcdn.com/group8/M01/D4/34/wKgDYFZ6y1nR6QpZAEDVy7rUTTc247.mp3",
@"http://fdfs.xmcdn.com/group9/M00/D4/EF/wKgDZlZ7aLGCQEEDAHMsQsurq_Y170.mp3",
@"http://fdfs.xmcdn.com/group12/M07/D4/C4/wKgDW1Z70rWxoDA7ABAp1lwS5nI990.mp3", nil];
self.musicAllTimeArray = [NSArray arrayWithObjects:@(1344.36), @(1500.04), @(1999.06), @(1062.22), @(1886.96), @(264.76), nil]; //滑块
self.slider.minimumValue = 0;
[self.slider addTarget:self action:@selector(changValue:) forControlEvents:UIControlEventValueChanged]; //添加滑动事件
[self.slider setThumbImage:[UIImage imageNamed:@"playProcessDot_n"]forState:UIControlStateNormal]; //播放音频之前先要设置AVAudioSession模式 是它可以后台播放
//并且要在plist文件中 添加required background modes这个key项,并选择"App plays audio or streams audio/video using AirPlay"这个value项。
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:nil];
[session setActive:YES error:nil]; [self playerCurrentMusic];
} -(void)playerCurrentMusic { //创建串行队列 (放入线程中,免得页面假死)
dispatch_queue_t serialQueue = dispatch_queue_create("com.audio.www", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{ NSString *url = self.musicUrlArray[self.currentIndex];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
self.player = [[AVAudioPlayer alloc] initWithData:data error:nil];
self.player.delegate = self;
[self.player prepareToPlay];
[self.player play]; //滑块
CGFloat allTime = [self.musicAllTimeArray[self.currentIndex] floatValue];
self.slider.maximumValue = allTime; //计时器只能在主线程中
dispatch_async(dispatch_get_main_queue(), ^{
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(reloadAction) userInfo:nil repeats:YES];
});
});
} #pragma mark -- 每1秒 给进度条赋一次值
-(void)reloadAction {
if ([self.player isPlaying]) {
self.slider.value = self.player.currentTime;
}
} #pragma mark 点击暂停
- (IBAction)suspendAction:(UIButton *)sender {
sender.selected = !sender.selected;
if (sender.selected) {
[self.player pause]; //暂停
[sender setTitle:@"播放" forState:UIControlStateSelected];
} else {
[self.player play]; //播放
[sender setTitle:@"暂停" forState:UIControlStateNormal];
}
} #pragma mark 点击上一首
- (IBAction)formerAction:(UIButton *)sender {
[self myPlayFormer]; //播放上一首
} #pragma mark 点击下一首
- (IBAction)nextAction:(UIButton *)sender {
[self myPlayNext]; //播放下一首
} #pragma mark 上一首
-(void)myPlayFormer {
if (self.currentIndex > 0) {
[self.player pause];
self.currentIndex--;
[self playerCurrentMusic];
}
}
#pragma mark 下一首
-(void)myPlayNext {
if (self.currentIndex < self.musicUrlArray.count - 1) {
[self.player pause];
self.currentIndex++;
[self playerCurrentMusic];
}
} /***************** 控制台 *****************/
#pragma mark -- 声明App接收远程控制事件
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
} #pragma mark -- App结束声明接收远程控制事件
- (void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
[self resignFirstResponder];
} #pragma mark -- 接受控制台的控制事件
- (void)remoteControlReceivedWithEvent: (UIEvent *) receivedEvent {
if (receivedEvent.type == UIEventTypeRemoteControl) {
//判断点击按钮的类型
switch (receivedEvent.subtype) { case UIEventSubtypeRemoteControlPlay:
[self.player play]; //播放
break;
case UIEventSubtypeRemoteControlPause:
[self.player pause]; //暂停
break;
case UIEventSubtypeRemoteControlPreviousTrack:
[self myPlayFormer]; //播放上一首
break;
case UIEventSubtypeRemoteControlNextTrack:
[self myPlayNext]; //播放下一首
break;
default:
break;
}
}
} #pragma mark 实现后台播放完一首后, 继续播放下一首
- (BOOL)canBecomeFirstResponder {
return YES;
} /***************** AVAudioPlayer 代理 *****************/
#pragma mark -- 后台播放被打断, 继续恢复播放 (比如打电话...)
- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player withOptions:(NSUInteger)flags {
[self.player play];
}
#pragma mark -- 播放完当前声音后,播放下一首
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
if (self.currentIndex < self.musicUrlArray.count - 1) {
self.currentIndex++;
[self playerCurrentMusic];
}
} #pragma mark -- 滑块滑动改变播放进度(代理方法)
-(void)changValue:(UISlider *)slider {
//拖动滑块时, 停止计时器
[self.timer invalidate];
self.player.currentTime = slider.value;
//开始计时器
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(reloadAction) userInfo:nil repeats:YES];
}

想要实现后台播放(即程序进入后台,音乐继续播放)需要修改plist文件:

1.添加required background modes这个key项,并选择"App plays audio or streams audio/video using AirPlay"这个value项。
2.XCode7.1以上获取网络数据,需要修改plist文件
在Info.plist中添加App Transport Security Settings类型Dictionary。
在App Transport Security Settings下添加Allow Arbitrary Loads类型Boolean,值设为YES

需要在后台实现播放页的各种上一首,下一首...各种功能, 还需要在Appdelegate.m的background方法里:

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

    //程序进入后台后, 为了让音乐继续播放, 在此方法里创建该代理播放页, 并指定它播放器的代理
PlayViewController *player = [PlayViewController defaultPlayVC];
player.player.delegate = player;
}

当前工程Demo地址: http://download.csdn.net/detail/margaret_mo/9412069

AVAudioPlayer播放并实现了后台播放和远程控制的更多相关文章

  1. iOS从零开始学习直播之音频2.后台播放和在线播放

    本篇主要讲音频的后台播放和在线播放. 后台播放   上一篇写的工程运行之后程序退至后台,发现运行不了,歌停止了,这显然不行,音乐后台播放是标配啊.今天就来讲一下后台播放. 1.在plist文件里,告诉 ...

  2. iOS后台播放音乐

    iOS实现在后台播放音乐 iOS4之后就支持后台播放音频了.只需下面两步就可以实现后台播放音频操作了. 1. 在Info.plist中,添加"Required background mode ...

  3. iOS开发--QQ音乐练习,后台播放和锁屏界面

    一.设置后台播放 首先允许程序后台播放 代码实现 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOpti ...

  4. iOS- 关于AVAudioSession的使用——后台播放音乐

    1.前言 •AVAudioSession是一个单例,无需实例化即可直接使用.AVAudioSession在各种音频环境中起着非常重要的作用 •针对不同的音频应用场景,需要设置不同的音频会话分类   1 ...

  5. iOS AvPlayer AvAudioPlayer音频的后台播放问题

    iOS 4开始引入的multitask,我们可以实现像ipod程序那样在后台播放音频了.如果音频操作是用苹果官方的AVFoundation.framework实现,像用AvAudioPlayer,Av ...

  6. iOS 后台播放音乐

    在info.plist文件中添加 下面是后台播放音频的完整测试代码: 引入文件<AVFoundation/AVFoundation.h> //后台播放音频设置 AVAudioSession ...

  7. IOS后台运行 之 后台播放音乐

    iOS 4开始引入的multitask,我们可以实现像ipod程序那样在后台播放音频了.如果音频操作是用苹果官方的AVFoundation.framework实现,像用AvAudioPlayer,Av ...

  8. iOS多媒体总结&进入后台播放音乐

    1. 播放mp3需要导入框架,AVFoundation支持音频文件(.caf..aif..wav..wmv和.mp3)的播放. #import <AVFoundation/AVFoundatio ...

  9. iOS后台播放

    ### 音乐后台播放 * .当程序进入后台的时候,开启后台任务 ``` - (void)applicationDidEnterBackground:(UIApplication *) { // 开启后 ...

随机推荐

  1. 记一个同时支持模糊匹配和静态推导的Atom语法补全插件的开发过程: 序

    简介 过去的一周,都睡的很晚,终于做出了Atom上的APICloud语法提示与补全插件:apicloud_autocomplete.个中滋味,感觉还是有必要记录下来的.代码基于 GPL-3.0 开源, ...

  2. SQL Server获取下一个编码字符实现继续重构与增强

        我在SQL Server获取下一个编码字符实现的博文中,虽然实现了这个问题,但是感觉维护起来比较麻烦,例如如果调整编码字符串的固定长度,就需要变更三个函数,这样的为何成本确实比较大.面向对象编 ...

  3. div模拟textarea实现高度自增长

    今天突然有位前端的朋友问我textarea怎么实现高度随内容自增长,我一下子懵了,首先想到的是用js改变textarea的高度,但是百度了很多参考代码效果都不是很理想. 因为之前实际项目中用的text ...

  4. List<T>保存为XML文件

    今天我们学习怎样把List<T>写成一个XML文件保存起来.因为我们在做动态网站开发时,需要对一些不太常变化的数据产生为XML文件,让程序直接去读取,而不是每次是SQL数据库取. 为了解决 ...

  5. jquery时间轴幻灯展示源代码

    查看效果:http://hovertree.com/texiao/jquery/75/ 源代码下载:http://hovertree.com/h/bjaf/8jlpc2wu.htm 效果图如下: 代码 ...

  6. Oracle命名规范

    1.编写目的 使用统一的命名和编码规范,使数据库命名及编码风格标准化,以便于阅读.理解和继承. 2.适用范围 本规范适用于公司范围内所有以ORACLE作为后台数据库的应用系统和项目开发工作. 3.对象 ...

  7. mysql 批量插入数据

    MySQL使用INSERT插入多条记录,应该如何操作呢?下面就为您详细介绍MySQL使用INSERT插入多条记录的实现方法,供您参考. 看到这个标题也许大家会问,这有什么好说的,调用多次INSERT语 ...

  8. MVC5+EF6 入门完整教程13 -- 动态生成多级菜单

    稍微有一定复杂性的系统,多级菜单都是一个必备组件. 本篇专题讲述如何生成动态多级菜单的通用做法. 我们不用任何第三方的组件,完全自己构建灵活通用的多级菜单. 需要达成的效果:容易复用,可以根据mode ...

  9. TreeView使用

    1.添加节点,实现拖拽功能 private void Form1_Load(object sender, EventArgs e) { TreeNode node1 = new TreeNode(); ...

  10. int和Integer的区别

    int是一种数据类型,Integer是一个类,有各种方法,如Integer.parseInt(string)等.