• AVAudioPlayer播放并实现了后台播放和远程控制


    //  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





  • 相关阅读:
    Java并发编程
    Git
    Spring Boot
    IDEA工具
    Java基础
    数据库架构
    设计模式
    网络基础
    管理知识
    linux安装数据库mysql
  • 原文地址:https://www.cnblogs.com/moxiaoyan33/p/5309256.html
Copyright © 2020-2023  润新知