通过这个文章可以实现长音频的播放、音量、播放进度控制,以及中断事件的处理和线路切换的响应

一、配置音频会话

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    AVAudioSession *session = [AVAudioSession sharedInstance];
    NSError *error;
    if ( ![session setCategory:AVAudioSessionCategoryPlayback error:&error] ) {//设置任务类型
        NSLog(@"category error log : %@",error.localizedDescription);
    }
    if ( ![session setActive:YES error:&error] ) {//设置活跃状态
        NSLog(@"active error log : %@",error.localizedDescription);
    }
    return YES;
}

setCategory 说明:

  • AVAudioSessionCategoryAmbient 游戏、效率应用程序类型
  • AVAudioSessionCategorySoloAmbient 游戏、效率应用程序类型(默认类型)
  • AVAudioSessionCategoryPlayback 音频和视频播放器类型
  • AVAudioSessionCategoryRecord 录音机、音频捕捉类型
  • AVAudioSessionCategoryPlayAndRecord VoIP、语音聊天类型
  • AVAudioSessionCategoryAudioProcessing 离线会话和处理类型
  • AVAudioSessionCategoryMultiRoute 使用外部硬件的高级A/V应用程序

这里我们使用的是AVAudioSessionCategoryPlayback 类型

二、创建并使用AVAudioPlayer

有两种方法可以创建 AVAudioPlayer,通过NSData创建或者通过本地音频文件的NSURL创建,通过NSURL创建必须是本地路径。这里直接贴代码,功能简单就不做封装了。。。

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
#import <QuartzCore/QuartzCore.h>

#define  SCREEN_WIDTH  [UIScreen mainScreen].bounds.size.width
#define  SCREEN_HEIGHT   [UIScreen mainScreen].bounds.size.height


@interface ViewController ()<AVAudioPlayerDelegate>

@property(nonatomic,strong)AVAudioPlayer *audioPlayer;
@property(nonatomic,strong)UIButton *playButton;
@property(nonatomic,strong)UISlider *volumeControl;
@property(nonatomic,strong)UISlider *progressControl;
@property(nonatomic,strong)NSTimer *timer;
@end

@implementation ViewController
@synthesize audioPlayer = __audioPlayer;
@synthesize playButton = __playButton;

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    NSError *error;
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"晴天" withExtension:@"mp3"];
    __audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
    if ( __audioPlayer ) {
        __audioPlayer.delegate = self;//设置代理
        __audioPlayer.volume = 1.0f;//设置音量
        [__audioPlayer prepareToPlay];//初始化准备工作
        NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
        //注册facetime 电话呼入等中断事件监听
        [notificationCenter addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
        //注册线路变化 监听
        [notificationCenter addObserver:self selector:@selector(handleRouteChange:) name:AVAudioSessionRouteChangeNotification object:[AVAudioSession sharedInstance]];
    }else{
        NSLog(@"player init error log %@",error.localizedDescription);
    }
    [self configView];
}

- (void)configView{
    //播放/暂停控制按钮
    [self controlButton];
    //音量控制
    [self volumeControlView];
    //进度控制
    [self progressControlView];
}

//控制按钮
- (void)controlButton{
    __playButton = [UIButton buttonWithType:UIButtonTypeCustom];
   __playButton.frame = CGRectMake((SCREEN_WIDTH - 100)/2, 500, 100, 40);
    [__playButton setTitle:@"播放" forState:UIControlStateNormal];
    [__playButton setTitle:@"停止" forState:UIControlStateSelected];
    [__playButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    __playButton.backgroundColor = [UIColor blueColor];
    [__playButton addTarget:self action:@selector(audioPlay) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:__playButton];
}

//音量控制
- (void)volumeControlView{
    UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake((SCREEN_WIDTH - 300)/2, 370, 80, 20)];
    label.text = @"音量控制";
    label.textAlignment  = NSTextAlignmentCenter;
    label.textColor = [UIColor blackColor];
    [self.view addSubview:label];
    
    self.volumeControl = [[UISlider alloc]initWithFrame:CGRectMake((SCREEN_WIDTH - 300)/2+100, 375, 200, 10)];
    self.volumeControl.maximumValue = 1.0f;
    self.volumeControl.minimumValue = 0.0f;
    self.volumeControl.value =__audioPlayer.volume;
    [self.volumeControl addTarget:self action:@selector(volumeChange:) forControlEvents:UIControlEventValueChanged];
    [self.view addSubview:self.volumeControl];
    
}

//进度控制
- (void)progressControlView{
    UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake((SCREEN_WIDTH - 300)/2, 420, 80, 20)];
    label.text = @"进度控制";
    label.textAlignment  = NSTextAlignmentCenter;
    label.textColor = [UIColor blackColor];
    [self.view addSubview:label];
    
    self.progressControl = [[UISlider alloc]initWithFrame:CGRectMake((SCREEN_WIDTH - 300)/2+100, 425, 200, 10)];
    self.progressControl.maximumValue = __audioPlayer.duration;
    self.progressControl.minimumValue = 0.0f;
    self.progressControl.value = __audioPlayer.currentTime;
    [self.progressControl addTarget:self action:@selector(timeChange:) forControlEvents:UIControlEventValueChanged];
    [self.view addSubview:self.progressControl];
}

#pragma mark -- ACTION
//监听通知回调事件
- (void)handleInterruption:(NSNotification *)notification{
    NSDictionary *info = notification.userInfo;
//    NSLog(@"handleInterruption info %@",info);
    AVAudioSessionInterruptionType type = [info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
    if ( type == AVAudioSessionInterruptionTypeBegan ) {
            //任务中断
            [self stopPlay];
    }else{
        //任务开始
        AVAudioSessionInterruptionOptions options = [info[AVAudioSessionInterruptionOptionKey] unsignedIntegerValue];
        if ( options == AVAudioSessionInterruptionOptionShouldResume ) {//状态恢复
                [self startPlay];
        }
    }
}

//线路变化回调事件
- (void)handleRouteChange:(NSNotification *)notification{
    NSDictionary *info = notification.userInfo;
    AVAudioSessionRouteChangeReason reason = [info[AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue];
    if ( reason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable ) {//之前播放的设备不能使用
        AVAudioSessionRouteDescription *previousRoute = info [AVAudioSessionRouteChangePreviousRouteKey];//获取以前的播放线路
        AVAudioSessionPortDescription *previousOutput  = previousRoute.outputs[0];//获取线路输出设备
        NSString *portType = previousOutput.portType;//线路接口类型
        if ( [portType isEqualToString:AVAudioSessionPortHeadphones] ) {//耳机或者耳机输出类型
            [self stopPlay];//断开耳机,停止播放
        }
    }
    if ( reason == AVAudioSessionRouteChangeReasonNewDeviceAvailable ) {//新的设备接入
        [self startPlay];//开始播放
    }
    
}

//更新播放进度条
- (void)updateProgress{
    __block typeof(*&self) wself = self;
    dispatch_async(dispatch_get_main_queue(), ^{
        [wself.progressControl setValue:wself->__audioPlayer.currentTime animated:YES];
    });
}

//音量控制事件
- (void)volumeChange:(UISlider *)slider{
    __audioPlayer.volume = slider.value;
}
//播放时间控制事件
- (void)timeChange:(UISlider *)slider{
    __audioPlayer.currentTime = slider.value;
}

//按钮点击事件
- (void)audioPlay{
    if ( !__audioPlayer.isPlaying && !__playButton.selected ) {
        [self startPlay];
    }else{
        [self stopPlay];
    }
    
}
//开始播放
- (void)startPlay{
    __block typeof(*&self) wself = self;
    dispatch_async(dispatch_get_main_queue(), ^{
        wself->__playButton.selected = YES;
    });
    [__audioPlayer play];
    if ( !self.timer ) {
        __weak typeof(*&self) wself = self;
        //设置1s 调用一次,cpu 占用率最低
        self.timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
            [wself updateProgress];
        }];
    }
}

//停止播放
- (void)stopPlay{
    __block typeof(*&self) wself = self;
    dispatch_async(dispatch_get_main_queue(), ^{
        wself->__playButton.selected = NO;
    });
    [__audioPlayer pause];//暂停
    if ( self.timer ) {
        [self.timer invalidate];
        self.timer = nil;
    }
}


#pragma mark -- AVAudioPlayerDelegate
//播放完成
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
    if ( flag ) {
        __playButton.selected = NO;
    }
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    // Dispose of any resources that can be recreated.
}


@end

deney
91 声望4 粉丝

闲着没事就搬砖的码农,欢迎交流