//  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. maven中使用junit老是找不到包

    如题,烦恼好久,突然看到scope一直是test,改成compile就好了. compile (编译范围) compile是默认的范围:如果没有提供一个范围,那该依赖的范围就是编译范围.编译范围依赖在 ...

  2. python生成随机密码

    有时候我们会想生成一个随机密码,这样我们通过Python中的一些随机方法,就可生成我们任意长度和复杂度的密码,代码如下: # -*- coding=utf-8 -*- import random im ...

  3. Android Studio快捷键每日一练(3)

    原文地址:http://www.developerphil.com/android-studio-tips-of-the-day-roundup-3/ 23.启停用断点 苹果:Cmd+F8    Wi ...

  4. SQL Server - 把星期一(周一)当作每个星期的开始在一年中求取周数

    先感叹一句!好长时间没有更新博客了!偶尔看到一句话,觉得被电击了 - 庸人败于懒,能人败于傲! 因此,不能再懒惰了! 今天想写一个有关计算 Week Number 的函数,刚开始觉得应该很简单,凭着感 ...

  5. html中charset和content-language的区别

    假设下面的这一段html中meta的两行配置. <html> <head> <meta http-equiv="Content-Type" conte ...

  6. MS SQL中使用UPDATE ... INNER JOIN ...

    昨天的SQL编程中,有使用到一个方法,就是把一个表某一字段更新至另一个表的字段中去. 实现这个方法,Insus.NET有尝试了几个方法,下面一一分享出来,让大家参考参考. 下面的数据只是模拟了,形式与 ...

  7. Web API接口设计经验总结

    在Web API接口的开发过程中,我们可能会碰到各种各样的问题,我在前面两篇随笔<Web API应用架构在Winform混合框架中的应用(1)>.<Web API应用架构在Winfo ...

  8. R语言介绍

    R语言简介 R语言是一种为统计计算和图形显示而设计的语言环境,是贝尔实验室(Bell Laboratories)的Rick Becker.John Chambers和Allan Wilks开发的S语言 ...

  9. Python中的编码

    http://liguangming.com/how-to-use-utf-8-with-python http://www.lijiejie.com/python-sys-setdefaultenc ...

  10. [java] StringBuilder / StringBuffer / String 建立字符串

    1.三者在建立新字符串速度方面的比较: StringBuilder >  StringBuffer  >  String 2.线程安全性: StringBuilder:线程非安全的 Str ...